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 }