001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.hivemind.ant;
016
017 import java.util.ArrayList;
018 import java.util.Collection;
019 import java.util.HashSet;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Set;
023
024 import javax.xml.parsers.DocumentBuilder;
025 import javax.xml.parsers.DocumentBuilderFactory;
026 import javax.xml.parsers.ParserConfigurationException;
027
028 import org.apache.hivemind.ApplicationRuntimeException;
029 import org.apache.hivemind.Attribute;
030 import org.apache.hivemind.ClassResolver;
031 import org.apache.hivemind.ErrorHandler;
032 import org.apache.hivemind.ModuleDescriptorProvider;
033 import org.apache.hivemind.Occurances;
034 import org.apache.hivemind.impl.DefaultClassResolver;
035 import org.apache.hivemind.impl.DefaultErrorHandler;
036 import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
037 import org.apache.hivemind.internal.Visibility;
038 import org.apache.hivemind.parse.AttributeMappingDescriptor;
039 import org.apache.hivemind.parse.ConfigurationPointDescriptor;
040 import org.apache.hivemind.parse.ContributionDescriptor;
041 import org.apache.hivemind.parse.ConversionDescriptor;
042 import org.apache.hivemind.parse.CreateInstanceDescriptor;
043 import org.apache.hivemind.parse.DependencyDescriptor;
044 import org.apache.hivemind.parse.ImplementationDescriptor;
045 import org.apache.hivemind.parse.InstanceBuilder;
046 import org.apache.hivemind.parse.InterceptorDescriptor;
047 import org.apache.hivemind.parse.InvokeFactoryDescriptor;
048 import org.apache.hivemind.parse.ModuleDescriptor;
049 import org.apache.hivemind.parse.ServicePointDescriptor;
050 import org.apache.hivemind.parse.SubModuleDescriptor;
051 import org.apache.hivemind.schema.AttributeModel;
052 import org.apache.hivemind.schema.ElementModel;
053 import org.apache.hivemind.schema.Rule;
054 import org.apache.hivemind.schema.impl.SchemaImpl;
055 import org.apache.hivemind.schema.rules.CreateObjectRule;
056 import org.apache.hivemind.schema.rules.InvokeParentRule;
057 import org.apache.hivemind.schema.rules.PushAttributeRule;
058 import org.apache.hivemind.schema.rules.PushContentRule;
059 import org.apache.hivemind.schema.rules.ReadAttributeRule;
060 import org.apache.hivemind.schema.rules.ReadContentRule;
061 import org.apache.hivemind.schema.rules.SetModuleRule;
062 import org.apache.hivemind.schema.rules.SetParentRule;
063 import org.apache.hivemind.schema.rules.SetPropertyRule;
064 import org.apache.hivemind.util.IdUtils;
065 import org.w3c.dom.Document;
066 import org.w3c.dom.Element;
067
068 /**
069 * This class serializes a set of {@link ModuleDescriptor module descriptors} into a
070 * {@link Document XML document}. The set of module descriptors to process is specified indirectly
071 * by supplying one or several {@link ModuleDescriptorProvider} (see
072 * {@link #addModuleDescriptorProvider(ModuleDescriptorProvider)}). In this respect this class is
073 * used the same way as {@link org.apache.hivemind.impl.RegistryBuilder}. There is even a
074 * corresponding {@link #createDefaultRegistryDocument() static method} to serialize the modules of
075 * the default registry.
076 * <p>
077 * The resulting XML file does not conform to the hivemind module deployment descriptor schema. The
078 * following changes occur:
079 * <ul>
080 * <li>The outermost element is <registry> (which contains a list of <module>)
081 * <li>A unique id (unique within the file) is assigned to each <module>,
082 * <configuration-point>, <service-point>, <contribution>, &tl;schema> and
083 * <implementation> (this is to make it easier to generate links and anchors)
084 * <li>Unqualified ids are converted to qualified ids (whereever possible).
085 * </ul>
086 *
087 * @author Knut Wannheden
088 * @since 1.1
089 */
090 public class RegistrySerializer
091 {
092 private Set _processedSchemas = new HashSet();
093
094 private List _providers = new ArrayList();
095
096 private ErrorHandler _handler;
097
098 private Document _document;
099
100 private ModuleDescriptor _md;
101
102 public RegistrySerializer()
103 {
104 _handler = new DefaultErrorHandler();
105 }
106
107 public void addModuleDescriptorProvider(ModuleDescriptorProvider provider)
108 {
109 _providers.add(provider);
110 }
111
112 public Document createRegistryDocument()
113 {
114 DocumentBuilder builder = getBuilder();
115
116 _document = builder.newDocument();
117
118 Element registry = _document.createElement("registry");
119
120 _document.appendChild(registry);
121
122 for (Iterator i = _providers.iterator(); i.hasNext();)
123 {
124 ModuleDescriptorProvider provider = (ModuleDescriptorProvider) i.next();
125
126 processModuleDescriptorProvider(registry, provider);
127 }
128
129 return _document;
130 }
131
132 private void processModuleDescriptorProvider(Element registry, ModuleDescriptorProvider provider)
133 {
134 for (Iterator j = provider.getModuleDescriptors(_handler).iterator(); j.hasNext();)
135 {
136 _md = (ModuleDescriptor) j.next();
137
138 Element module = getModuleElement(_md);
139
140 registry.appendChild(module);
141 }
142 }
143
144 private Element getModuleElement(ModuleDescriptor md)
145 {
146 Element module = _document.createElement("module");
147
148 module.setAttribute("id", md.getModuleId());
149 module.setAttribute("version", md.getVersion());
150 module.setAttribute("package", md.getPackageName());
151
152 module.appendChild(_document.createTextNode(md.getAnnotation()));
153
154 addDependencies(module);
155
156 addServicePoints(module);
157
158 addConfigurationPoints(module);
159
160 addContributions(module);
161
162 addImplementations(module);
163
164 addSchemas(module);
165
166 addSubModules(module);
167
168 return module;
169 }
170
171 private void addDependencies(Element module)
172 {
173 List dependencies = _md.getDependencies();
174
175 if (dependencies != null)
176 {
177 for (Iterator i = dependencies.iterator(); i.hasNext();)
178 {
179 DependencyDescriptor dd = (DependencyDescriptor) i.next();
180
181 Element dependency = getDependencyElement(dd);
182
183 module.appendChild(dependency);
184 }
185 }
186 }
187
188 private void addServicePoints(Element module)
189 {
190 List servicePoints = _md.getServicePoints();
191
192 if (servicePoints != null)
193 {
194 for (Iterator i = servicePoints.iterator(); i.hasNext();)
195 {
196 ServicePointDescriptor spd = (ServicePointDescriptor) i.next();
197
198 Element servicePoint = getServicePointElement(spd);
199
200 module.appendChild(servicePoint);
201
202 SchemaImpl s = (SchemaImpl) spd.getParametersSchema();
203
204 if (s != null && s.getId() != null)
205 addSchema(module, s, "schema");
206 }
207 }
208 }
209
210 private void addConfigurationPoints(Element module)
211 {
212 List configurationPoints = _md.getConfigurationPoints();
213
214 if (configurationPoints != null)
215 {
216 for (Iterator i = configurationPoints.iterator(); i.hasNext();)
217 {
218 ConfigurationPointDescriptor cpd = (ConfigurationPointDescriptor) i.next();
219
220 Element configurationPoint = getConfigurationPointElement(cpd);
221
222 module.appendChild(configurationPoint);
223
224 SchemaImpl s = (SchemaImpl) cpd.getContributionsSchema();
225
226 if (s != null && s.getId() != null)
227 addSchema(module, s, "schema");
228 }
229 }
230 }
231
232 private void addContributions(Element module)
233 {
234 List contributions = _md.getContributions();
235
236 if (contributions != null)
237 {
238 for (Iterator i = contributions.iterator(); i.hasNext();)
239 {
240 ContributionDescriptor cd = (ContributionDescriptor) i.next();
241
242 Element contribution = getContributionElement(cd);
243
244 module.appendChild(contribution);
245 }
246 }
247 }
248
249 private void addImplementations(Element module)
250 {
251 List implementations = _md.getImplementations();
252
253 if (implementations != null)
254 {
255 for (Iterator i = implementations.iterator(); i.hasNext();)
256 {
257 ImplementationDescriptor id = (ImplementationDescriptor) i.next();
258
259 Element implementation = getImplementationElement(id);
260
261 module.appendChild(implementation);
262 }
263 }
264 }
265
266 private void addSchemas(Element module)
267 {
268 Collection schemas = _md.getSchemas();
269
270 for (Iterator i = schemas.iterator(); i.hasNext();)
271 {
272 SchemaImpl s = (SchemaImpl) i.next();
273
274 addSchema(module, s, "schema");
275 }
276 }
277
278 private void addSubModules(Element module)
279 {
280 List subModules = _md.getSubModules();
281
282 if (subModules != null)
283 {
284 for (Iterator i = subModules.iterator(); i.hasNext();)
285 {
286 SubModuleDescriptor smd = (SubModuleDescriptor) i.next();
287
288 Element subModule = getSubModuleElement(smd);
289
290 module.appendChild(subModule);
291 }
292 }
293 }
294
295 private Element getDependencyElement(DependencyDescriptor dd)
296 {
297 Element dependency = _document.createElement("dependency");
298
299 dependency.setAttribute("module-id", dd.getModuleId());
300 dependency.setAttribute("version", dd.getVersion());
301
302 return dependency;
303 }
304
305 private Element getServicePointElement(ServicePointDescriptor spd)
306 {
307 Element servicePoint = _document.createElement("service-point");
308
309 servicePoint.setAttribute("id", qualify(spd.getId()));
310 servicePoint.setAttribute("interface", spd.getInterfaceClassName());
311 if (spd.getVisibility() == Visibility.PRIVATE)
312 servicePoint.setAttribute("visibility", "private");
313 if (spd.getParametersCount() != Occurances.REQUIRED)
314 servicePoint.setAttribute("parameters-occurs", spd.getParametersCount().getName()
315 .toLowerCase());
316
317 servicePoint.appendChild(_document.createTextNode(spd.getAnnotation()));
318
319 if (spd.getParametersSchema() != null)
320 addSchema(servicePoint, (SchemaImpl) spd.getParametersSchema(), "parameters-schema");
321 else if (spd.getParametersSchemaId() != null)
322 servicePoint.setAttribute("parameters-schema-id", qualify(spd.getParametersSchemaId()));
323
324 InstanceBuilder ib = spd.getInstanceBuilder();
325
326 if (ib != null)
327 {
328 Element instanceBuilder = getInstanceBuilderElement(ib);
329
330 servicePoint.appendChild(instanceBuilder);
331 }
332
333 List interceptors = spd.getInterceptors();
334
335 if (interceptors != null)
336 {
337 for (Iterator i = interceptors.iterator(); i.hasNext();)
338 {
339 InterceptorDescriptor icd = (InterceptorDescriptor) i.next();
340
341 Element interceptor = getInterceptorElement(icd);
342
343 servicePoint.appendChild(interceptor);
344 }
345 }
346
347 return servicePoint;
348 }
349
350 private Element getConfigurationPointElement(ConfigurationPointDescriptor cpd)
351 {
352 Element configurationPoint = _document.createElement("configuration-point");
353
354 configurationPoint.setAttribute("id", qualify(cpd.getId()));
355 if (cpd.getVisibility() == Visibility.PRIVATE)
356 configurationPoint.setAttribute("visibility", "private");
357
358 configurationPoint.appendChild(_document.createTextNode(cpd.getAnnotation()));
359
360 if (cpd.getContributionsSchema() != null)
361 addSchema(configurationPoint, (SchemaImpl) cpd.getContributionsSchema(), "schema");
362 else if (cpd.getContributionsSchemaId() != null)
363 configurationPoint.setAttribute("schema-id", qualify(cpd.getContributionsSchemaId()));
364
365 return configurationPoint;
366 }
367
368 private Element getContributionElement(ContributionDescriptor cd)
369 {
370 Element contribution = _document.createElement("contribution");
371
372 contribution.setAttribute("configuration-id", qualify(cd.getConfigurationId()));
373
374 if (cd.getConditionalExpression() != null)
375 contribution.setAttribute("if", cd.getConditionalExpression());
376
377 List parameters = cd.getElements();
378
379 if (parameters != null)
380 {
381 for (Iterator i = parameters.iterator(); i.hasNext();)
382 {
383 org.apache.hivemind.Element parameter = (org.apache.hivemind.Element) i.next();
384
385 Element element = getParamterElement(parameter);
386
387 contribution.appendChild(element);
388 }
389 }
390
391 contribution.appendChild(_document.createTextNode(cd.getAnnotation()));
392
393 return contribution;
394 }
395
396 private Element getImplementationElement(ImplementationDescriptor id)
397 {
398 Element implementation = _document.createElement("implementation");
399
400 implementation.setAttribute("service-id", qualify(id.getServiceId()));
401
402 if (id.getConditionalExpression() != null)
403 implementation.setAttribute("if", id.getConditionalExpression());
404
405 implementation.appendChild(_document.createTextNode(id.getAnnotation()));
406
407 InstanceBuilder ib = id.getInstanceBuilder();
408
409 if (ib != null)
410 {
411 Element instanceBuilder = getInstanceBuilderElement(ib);
412
413 implementation.appendChild(instanceBuilder);
414 }
415
416 List interceptors = id.getInterceptors();
417
418 if (interceptors != null)
419 {
420 for (Iterator i = interceptors.iterator(); i.hasNext();)
421 {
422 InterceptorDescriptor icd = (InterceptorDescriptor) i.next();
423
424 Element interceptor = getInterceptorElement(icd);
425
426 implementation.appendChild(interceptor);
427 }
428 }
429
430 return implementation;
431 }
432
433 private Element getSubModuleElement(SubModuleDescriptor smd)
434 {
435 Element subModule = _document.createElement("sub-module");
436
437 subModule.setAttribute("descriptor", smd.getDescriptor().getPath());
438
439 return subModule;
440 }
441
442 private Element getInstanceBuilderElement(InstanceBuilder ib)
443 {
444 Element instanceBuilder;
445
446 if (ib instanceof CreateInstanceDescriptor)
447 {
448 CreateInstanceDescriptor cid = (CreateInstanceDescriptor) ib;
449 instanceBuilder = _document.createElement("create-instance");
450
451 instanceBuilder.setAttribute("class", cid.getInstanceClassName());
452 if (!cid.getServiceModel().equals("singleton"))
453 instanceBuilder.setAttribute("model", cid.getServiceModel());
454 }
455 else
456 {
457 InvokeFactoryDescriptor ifd = (InvokeFactoryDescriptor) ib;
458 instanceBuilder = _document.createElement("invoke-factory");
459
460 if (!ifd.getFactoryServiceId().equals("hivemind.BuilderFactory"))
461 instanceBuilder.setAttribute("service-id", qualify(ifd.getFactoryServiceId()));
462 if (ifd.getServiceModel() != null)
463 instanceBuilder.setAttribute("model", ifd.getServiceModel());
464
465 List parameters = ifd.getParameters();
466
467 if (parameters != null)
468 {
469 for (Iterator i = parameters.iterator(); i.hasNext();)
470 {
471 org.apache.hivemind.Element parameter = (org.apache.hivemind.Element) i.next();
472
473 Element element = getParamterElement(parameter);
474
475 instanceBuilder.appendChild(element);
476 }
477 }
478 }
479
480 return instanceBuilder;
481 }
482
483 private Element getInterceptorElement(InterceptorDescriptor icd)
484 {
485 Element interceptor = _document.createElement("interceptor");
486
487 interceptor.setAttribute("service-id", qualify(icd.getFactoryServiceId()));
488 if (icd.getBefore() != null)
489 interceptor.setAttribute("before", icd.getBefore());
490 if (icd.getAfter() != null)
491 interceptor.setAttribute("after", icd.getAfter());
492 return interceptor;
493 }
494
495 private Element getParamterElement(org.apache.hivemind.Element parameter)
496 {
497 Element element = _document.createElement(parameter.getElementName());
498
499 List attributes = parameter.getAttributes();
500
501 for (Iterator i = attributes.iterator(); i.hasNext();)
502 {
503 Attribute attribute = (Attribute) i.next();
504
505 element.setAttribute(attribute.getName(), attribute.getValue());
506 }
507
508 List elements = parameter.getElements();
509
510 for (Iterator i = elements.iterator(); i.hasNext();)
511 {
512 org.apache.hivemind.Element nestedParameter = (org.apache.hivemind.Element) i.next();
513
514 element.appendChild(getParamterElement(nestedParameter));
515 }
516
517 return element;
518 }
519
520 private void addSchema(Element container, SchemaImpl s, String elementName)
521 {
522 if (_processedSchemas.contains(s))
523 return;
524
525 Element schema = _document.createElement(elementName);
526
527 if (s.getId() != null)
528 schema.setAttribute("id", qualify(s.getId()));
529
530 if (s.getVisibility() == Visibility.PRIVATE)
531 schema.setAttribute("visibility", "private");
532
533 schema.appendChild(_document.createTextNode(s.getAnnotation()));
534
535 for (Iterator j = s.getElementModel().iterator(); j.hasNext();)
536 {
537 ElementModel em = (ElementModel) j.next();
538
539 Element element = getElementElement(em);
540
541 schema.appendChild(element);
542 }
543
544 container.appendChild(schema);
545
546 _processedSchemas.add(s);
547 }
548
549 private Element getRulesElement(ElementModel em)
550 {
551 Element rules = _document.createElement("rules");
552
553 for (Iterator i = em.getRules().iterator(); i.hasNext();)
554 {
555 Rule r = (Rule) i.next();
556
557 Element rule = null;
558
559 if (r instanceof CreateObjectRule)
560 {
561 CreateObjectRule cor = (CreateObjectRule) r;
562 rule = _document.createElement("create-object");
563
564 rule.setAttribute("class", cor.getClassName());
565 }
566 else if (r instanceof InvokeParentRule)
567 {
568 InvokeParentRule ipr = (InvokeParentRule) r;
569 rule = _document.createElement("invoke-parent");
570
571 rule.setAttribute("method", ipr.getMethodName());
572 if (ipr.getDepth() != 1)
573 rule.setAttribute("depth", Integer.toString(ipr.getDepth()));
574 }
575 else if (r instanceof PushAttributeRule)
576 {
577 PushAttributeRule par = (PushAttributeRule) r;
578 rule = _document.createElement("push-attribute");
579
580 rule.setAttribute("attribute", par.getAttributeName());
581 }
582 else if (r instanceof PushContentRule)
583 {
584 rule = _document.createElement("push-content");
585 }
586 else if (r instanceof ReadAttributeRule)
587 {
588 ReadAttributeRule rar = (ReadAttributeRule) r;
589 rule = _document.createElement("read-attribute");
590
591 rule.setAttribute("property", rar.getPropertyName());
592 rule.setAttribute("attribute", rar.getAttributeName());
593 if (!rar.getSkipIfNull())
594 rule.setAttribute("skip-if-null", "false");
595 if (rar.getTranslator() != null)
596 rule.setAttribute("translator", rar.getTranslator());
597 }
598 else if (r instanceof ReadContentRule)
599 {
600 ReadContentRule rcr = (ReadContentRule) r;
601 rule = _document.createElement("read-content");
602
603 rule.setAttribute("property", rcr.getPropertyName());
604 }
605 else if (r instanceof SetModuleRule)
606 {
607 SetModuleRule smr = (SetModuleRule) r;
608 rule = _document.createElement("set-module");
609
610 rule.setAttribute("property", smr.getPropertyName());
611 }
612 else if (r instanceof SetParentRule)
613 {
614 SetParentRule spr = (SetParentRule) r;
615 rule = _document.createElement("set-parent");
616
617 rule.setAttribute("property", spr.getPropertyName());
618 }
619 else if (r instanceof SetPropertyRule)
620 {
621 SetPropertyRule spr = (SetPropertyRule) r;
622 rule = _document.createElement("set-property");
623
624 rule.setAttribute("property", spr.getPropertyName());
625 rule.setAttribute("value", spr.getValue());
626 }
627 else if (r instanceof ConversionDescriptor)
628 {
629 ConversionDescriptor cd = (ConversionDescriptor) r;
630 rule = _document.createElement("conversion");
631
632 rule.setAttribute("class", cd.getClassName());
633 if (!cd.getParentMethodName().equals("addElement"))
634 rule.setAttribute("parent-method", cd.getParentMethodName());
635
636 for (Iterator j = cd.getAttributeMappings().iterator(); j.hasNext();)
637 {
638 AttributeMappingDescriptor amd = (AttributeMappingDescriptor) j.next();
639
640 Element map = _document.createElement("map");
641
642 map.setAttribute("attribute", amd.getAttributeName());
643 map.setAttribute("property", amd.getPropertyName());
644
645 rule.appendChild(map);
646 }
647 }
648 else
649 {
650 rule = _document.createElement("custom");
651
652 rule.setAttribute("class", r.getClass().getName());
653 }
654
655 if (rule != null)
656 rules.appendChild(rule);
657 }
658 return rules;
659 }
660
661 private Element getElementElement(ElementModel em)
662 {
663 Element element = _document.createElement("element");
664 element.setAttribute("name", em.getElementName());
665
666 element.appendChild(_document.createTextNode(em.getAnnotation()));
667
668 for (Iterator i = em.getAttributeModels().iterator(); i.hasNext();)
669 {
670 AttributeModel am = (AttributeModel) i.next();
671
672 Element attribute = getAttributeElement(am);
673
674 element.appendChild(attribute);
675 }
676
677 for (Iterator i = em.getElementModel().iterator(); i.hasNext();)
678 {
679 ElementModel nestedEm = (ElementModel) i.next();
680
681 Element nestedElement = getElementElement(nestedEm);
682
683 element.appendChild(nestedElement);
684 }
685
686 if (!em.getRules().isEmpty())
687 {
688 Element rules = getRulesElement(em);
689
690 element.appendChild(rules);
691 }
692
693 return element;
694 }
695
696 private Element getAttributeElement(AttributeModel am)
697 {
698 Element attribute = _document.createElement("attribute");
699
700 attribute.setAttribute("name", am.getName());
701 if (am.isRequired())
702 attribute.setAttribute("required", "true");
703 if (am.isUnique())
704 attribute.setAttribute("unique", "true");
705 if (!am.getTranslator().equals("smart"))
706 attribute.setAttribute("translator", am.getTranslator());
707
708 attribute.appendChild(_document.createTextNode(am.getAnnotation()));
709
710 return attribute;
711 }
712
713 private String qualify(String id)
714 {
715 return IdUtils.qualify(_md.getModuleId(), id);
716 }
717
718 private DocumentBuilder getBuilder()
719 {
720 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
721
722 factory.setIgnoringComments(true);
723
724 try
725 {
726 return factory.newDocumentBuilder();
727 }
728 catch (ParserConfigurationException e)
729 {
730 throw new ApplicationRuntimeException(e);
731 }
732 }
733
734 public static Document createDefaultRegistryDocument()
735 {
736 ClassResolver resolver = new DefaultClassResolver();
737 ModuleDescriptorProvider provider = new XmlModuleDescriptorProvider(resolver);
738
739 RegistrySerializer serializer = new RegistrySerializer();
740
741 serializer.addModuleDescriptorProvider(provider);
742
743 return serializer.createRegistryDocument();
744 }
745 }