2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

Clover coverage report - Code Coverage for hivemind release 1.2.1
Coverage timestamp: Fri Feb 10 2006 16:33:43 PST
file stats: LOC: 1,438   Methods: 64
NCLOC: 923   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DescriptorParser.java 90.8% 95.9% 98.4% 95.3%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.hivemind.parse;
 16   
 17    import java.io.BufferedInputStream;
 18    import java.io.IOException;
 19    import java.io.InputStream;
 20    import java.util.Enumeration;
 21    import java.util.HashMap;
 22    import java.util.Iterator;
 23    import java.util.Map;
 24    import java.util.Properties;
 25   
 26    import org.apache.commons.logging.Log;
 27    import org.apache.commons.logging.LogFactory;
 28    import org.apache.hivemind.ApplicationRuntimeException;
 29    import org.apache.hivemind.Attribute;
 30    import org.apache.hivemind.ClassResolver;
 31    import org.apache.hivemind.ErrorHandler;
 32    import org.apache.hivemind.Occurances;
 33    import org.apache.hivemind.Resource;
 34    import org.apache.hivemind.impl.AttributeImpl;
 35    import org.apache.hivemind.impl.ElementImpl;
 36    import org.apache.hivemind.internal.Visibility;
 37    import org.apache.hivemind.schema.ElementModel;
 38    import org.apache.hivemind.schema.Rule;
 39    import org.apache.hivemind.schema.impl.AttributeModelImpl;
 40    import org.apache.hivemind.schema.impl.ElementModelImpl;
 41    import org.apache.hivemind.schema.impl.SchemaImpl;
 42    import org.apache.hivemind.schema.rules.CreateObjectRule;
 43    import org.apache.hivemind.schema.rules.InvokeParentRule;
 44    import org.apache.hivemind.schema.rules.PushAttributeRule;
 45    import org.apache.hivemind.schema.rules.PushContentRule;
 46    import org.apache.hivemind.schema.rules.ReadAttributeRule;
 47    import org.apache.hivemind.schema.rules.ReadContentRule;
 48    import org.apache.hivemind.schema.rules.SetModuleRule;
 49    import org.apache.hivemind.schema.rules.SetParentRule;
 50    import org.apache.hivemind.schema.rules.SetPropertyRule;
 51    import org.apache.hivemind.util.IdUtils;
 52    import org.apache.oro.text.regex.MalformedPatternException;
 53    import org.apache.oro.text.regex.Pattern;
 54    import org.apache.oro.text.regex.Perl5Compiler;
 55    import org.apache.oro.text.regex.Perl5Matcher;
 56   
 57    /**
 58    * Used to parse HiveMind module deployment descriptors.
 59    * <p>
 60    * TODO: The parser ignores element content except inside &lt;contribution&gt; and
 61    * &lt;invoke-factory&gt; ... it probably should forbid non-whitespace content.
 62    *
 63    * @author Howard Lewis Ship
 64    */
 65    public final class DescriptorParser extends AbstractParser
 66    {
 67    private static final String DEFAULT_SERVICE_MODEL = "singleton";
 68   
 69    private static final Log LOG = LogFactory.getLog(DescriptorParser.class);
 70   
 71    /**
 72    * States used while parsing the document. Most states correspond to a particular XML element in
 73    * the document. STATE_START is the initial state, before the &lt;module&gt; element is reached.
 74    */
 75    private static final int STATE_START = 0;
 76   
 77    private static final int STATE_MODULE = 1;
 78   
 79    // private static final int STATE_DESCRIPTION = 2;
 80    private static final int STATE_CONFIGURATION_POINT = 3;
 81   
 82    private static final int STATE_CONTRIBUTION = 4;
 83   
 84    private static final int STATE_SERVICE_POINT = 5;
 85   
 86    private static final int STATE_CREATE_INSTANCE = 6;
 87   
 88    private static final int STATE_IMPLEMENTATION = 8;
 89   
 90    /**
 91    * Used for both &lt;schema&;gt; within a &lt;extension-point&gt;, and for
 92    * &lt;parameters-schema&gt; within a &lt;service&gt;.
 93    */
 94    private static final int STATE_SCHEMA = 9;
 95   
 96    private static final int STATE_ELEMENT = 10;
 97   
 98    private static final int STATE_RULES = 11;
 99   
 100    /**
 101    * Used with &lt;invoke-factory&gt; and &lt;interceptor&gt; to collect parameters that will be
 102    * passed to the implementation or interceptor factory service.
 103    */
 104    private static final int STATE_COLLECT_SERVICE_PARAMETERS = 12;
 105   
 106    /**
 107    * Used with the &lt;conversion&gt; element (an alternative to using &lt;rules&gt;. Finds
 108    * &lt;map&gt; elements.
 109    */
 110    private static final int STATE_CONVERSION = 13;
 111   
 112    /**
 113    * Represents building Element hierarchy as a light-wieght DOM.
 114    */
 115   
 116    private static final int STATE_LWDOM = 100;
 117   
 118    /**
 119    * Special state for elements that are not allowed to contain any other elements.
 120    */
 121   
 122    private static final int STATE_NO_CONTENT = 300;
 123   
 124    private static final String SIMPLE_ID = "[a-zA-Z0-9_]+";
 125   
 126    /**
 127    * Format for configuration point ids, service point ids and schema ids. Consists of an optional
 128    * leading underscore, followed by alphanumerics and underscores. Normal naming convention is to
 129    * use a single CamelCase word, like a Java class name.
 130    */
 131    public static final String ID_PATTERN = "^" + SIMPLE_ID + "$";
 132   
 133    /**
 134    * Module ids are a sequence of simple ids seperated by periods. In practice, they look like
 135    * Java package names.
 136    */
 137    public static final String MODULE_ID_PATTERN = "^" + SIMPLE_ID + "(\\." + SIMPLE_ID + ")*$";
 138   
 139    public static final String VERSION_PATTERN = "[0-9]+(\\.[0-9]+){2}$";
 140   
 141    /**
 142    * Temporary storage of the current {@link org.xml.sax.Attributes}.
 143    */
 144    private Map _attributes = new HashMap();
 145   
 146    /**
 147    * Built from DescriptorParser.properties. Key is element name, value is an instance of
 148    * {@link ElementParseInfo}.
 149    */
 150   
 151    private Map _elementParseInfo = new HashMap();
 152   
 153    private ModuleDescriptor _moduleDescriptor;
 154   
 155    private ErrorHandler _errorHandler;
 156   
 157    private ClassResolver _resolver;
 158   
 159    private Perl5Compiler _compiler;
 160   
 161    private Perl5Matcher _matcher;
 162   
 163    private Map _compiledPatterns;
 164   
 165    /**
 166    * Map of Rule keyed on class name, used with &lt;custom&gt; rules.
 167    */
 168    private final Map _ruleMap = new HashMap();
 169   
 170    private final Map OCCURS_MAP = new HashMap();
 171   
 172    {
 173  271 OCCURS_MAP.put("0..1", Occurances.OPTIONAL);
 174  271 OCCURS_MAP.put("1", Occurances.REQUIRED);
 175  271 OCCURS_MAP.put("1..n", Occurances.ONE_PLUS);
 176  271 OCCURS_MAP.put("0..n", Occurances.UNBOUNDED);
 177  271 OCCURS_MAP.put("none", Occurances.NONE);
 178    }
 179   
 180    private final Map VISIBILITY_MAP = new HashMap();
 181   
 182    {
 183  271 VISIBILITY_MAP.put("public", Visibility.PUBLIC);
 184  271 VISIBILITY_MAP.put("private", Visibility.PRIVATE);
 185    }
 186   
 187  271 public DescriptorParser(ErrorHandler errorHandler)
 188    {
 189  271 _errorHandler = errorHandler;
 190   
 191  271 initializeFromPropertiesFile();
 192    }
 193   
 194  42086 public void begin(String elementName, Map attributes)
 195    {
 196  42086 _attributes = attributes;
 197   
 198  42086 switch (getState())
 199    {
 200  283 case STATE_START:
 201   
 202  283 beginStart(elementName);
 203  283 break;
 204   
 205  4786 case STATE_MODULE:
 206   
 207  4786 beginModule(elementName);
 208  4786 break;
 209   
 210  760 case STATE_CONFIGURATION_POINT:
 211   
 212  760 beginConfigurationPoint(elementName);
 213  760 break;
 214   
 215  3137 case STATE_CONTRIBUTION:
 216   
 217  3137 beginContribution(elementName);
 218  3137 break;
 219   
 220  1073 case STATE_LWDOM:
 221   
 222  1073 beginLWDom(elementName);
 223  1073 break;
 224   
 225  2796 case STATE_SERVICE_POINT:
 226   
 227  2796 beginServicePoint(elementName);
 228  2796 break;
 229   
 230  18 case STATE_IMPLEMENTATION:
 231   
 232  18 beginImplementation(elementName);
 233  18 break;
 234   
 235  1359 case STATE_SCHEMA:
 236   
 237  1359 beginSchema(elementName);
 238  1358 break;
 239   
 240  11646 case STATE_ELEMENT:
 241   
 242  11646 beginElement(elementName);
 243  11645 break;
 244   
 245  14157 case STATE_RULES:
 246   
 247  14157 beginRules(elementName);
 248  14156 break;
 249   
 250  1185 case STATE_COLLECT_SERVICE_PARAMETERS:
 251   
 252  1185 beginCollectServiceParameters(elementName);
 253  1185 break;
 254   
 255  886 case STATE_CONVERSION:
 256   
 257  886 beginConversion(elementName);
 258  886 break;
 259   
 260  0 default:
 261   
 262  0 unexpectedElement(elementName);
 263  0 break;
 264    }
 265    }
 266   
 267    /**
 268    * Very similar to {@link #beginContribution(String)}, in that it creates an
 269    * {@link ElementImpl}, adds it as a parameter to the
 270    * {@link AbstractServiceInvocationDescriptor}, then enters STATE_LWDOM to fill in its
 271    * attributes and content.
 272    */
 273   
 274  1185 private void beginCollectServiceParameters(String elementName)
 275    {
 276  1185 ElementImpl element = buildLWDomElement(elementName);
 277   
 278  1185 AbstractServiceInvocationDescriptor sid = (AbstractServiceInvocationDescriptor) peekObject();
 279   
 280  1185 sid.addParameter(element);
 281   
 282  1185 push(elementName, element, STATE_LWDOM, false);
 283    }
 284   
 285    /**
 286    * Invoked when a new element starts within STATE_CONFIGURATION_POINT.
 287    */
 288  760 private void beginConfigurationPoint(String elementName)
 289    {
 290  760 if (elementName.equals("schema"))
 291    {
 292  760 enterEmbeddedConfigurationPointSchema(elementName);
 293  760 return;
 294    }
 295   
 296  0 unexpectedElement(elementName);
 297    }
 298   
 299  3137 private void beginContribution(String elementName)
 300    {
 301    // This is where things get tricky, the point where we outgrew Jakarta Digester.
 302   
 303  3137 ElementImpl element = buildLWDomElement(elementName);
 304   
 305  3137 ContributionDescriptor ed = (ContributionDescriptor) peekObject();
 306  3137 ed.addElement(element);
 307   
 308  3137 push(elementName, element, STATE_LWDOM, false);
 309    }
 310   
 311  886 private void beginConversion(String elementName)
 312    {
 313  886 if (elementName.equals("map"))
 314    {
 315  886 ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 316   
 317  886 AttributeMappingDescriptor amd = new AttributeMappingDescriptor();
 318   
 319  886 push(elementName, amd, STATE_NO_CONTENT);
 320   
 321  886 checkAttributes();
 322   
 323  886 amd.setAttributeName(getAttribute("attribute"));
 324  886 amd.setPropertyName(getAttribute("property"));
 325   
 326  886 cd.addAttributeMapping(amd);
 327   
 328  886 return;
 329    }
 330   
 331  0 unexpectedElement(elementName);
 332    }
 333   
 334  11646 private void beginElement(String elementName)
 335    {
 336  11646 if (elementName.equals("attribute"))
 337    {
 338  5027 enterAttribute(elementName);
 339  5027 return;
 340    }
 341   
 342  6619 if (elementName.equals("conversion"))
 343    {
 344  518 enterConversion(elementName);
 345  518 return;
 346    }
 347   
 348  6101 if (elementName.equals("rules"))
 349    {
 350  3464 enterRules(elementName);
 351  3464 return;
 352    }
 353   
 354    // <element> is recursive ... possible, but tricky, if using Digester.
 355   
 356  2637 if (elementName.equals("element"))
 357    {
 358  2636 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 359   
 360  2636 elementModel.addElementModel(enterElement(elementName));
 361  2636 return;
 362    }
 363   
 364  1 unexpectedElement(elementName);
 365    }
 366   
 367  2686 private void beginImplementation(String elementName)
 368    {
 369   
 370  2686 if (elementName.equals("create-instance"))
 371    {
 372  1314 enterCreateInstance(elementName);
 373  1314 return;
 374    }
 375   
 376  1372 if (elementName.equals("invoke-factory"))
 377    {
 378  1306 enterInvokeFactory(elementName);
 379  1306 return;
 380    }
 381   
 382  66 if (elementName.equals("interceptor"))
 383    {
 384  66 enterInterceptor(elementName);
 385  66 return;
 386    }
 387   
 388  0 unexpectedElement(elementName);
 389    }
 390   
 391  1073 private void beginLWDom(String elementName)
 392    {
 393  1073 ElementImpl element = buildLWDomElement(elementName);
 394   
 395  1073 ElementImpl parent = (ElementImpl) peekObject();
 396  1073 parent.addElement(element);
 397   
 398  1073 push(elementName, element, STATE_LWDOM, false);
 399    }
 400   
 401    /**
 402    * Invoked when a new element occurs while in STATE_MODULE.
 403    */
 404  4786 private void beginModule(String elementName)
 405    {
 406  4786 if (elementName.equals("configuration-point"))
 407    {
 408  1079 enterConfigurationPoint(elementName);
 409   
 410  1079 return;
 411    }
 412   
 413  3707 if (elementName.equals("contribution"))
 414    {
 415  709 enterContribution(elementName);
 416  709 return;
 417    }
 418   
 419  2998 if (elementName.equals("service-point"))
 420    {
 421  2638 enterServicePoint(elementName);
 422   
 423  2638 return;
 424    }
 425   
 426  360 if (elementName.equals("implementation"))
 427    {
 428  16 enterImplementation(elementName);
 429   
 430  16 return;
 431    }
 432   
 433  344 if (elementName.equals("schema"))
 434    {
 435  331 enterSchema(elementName);
 436  331 return;
 437    }
 438   
 439  13 if (elementName.equals("sub-module"))
 440    {
 441  3 enterSubModule(elementName);
 442   
 443  3 return;
 444    }
 445   
 446  10 if (elementName.equals("dependency"))
 447    {
 448  10 enterDependency(elementName);
 449   
 450  10 return;
 451    }
 452   
 453  0 unexpectedElement(elementName);
 454    }
 455   
 456  14157 private void beginRules(String elementName)
 457    {
 458   
 459  14157 if (elementName.equals("create-object"))
 460    {
 461  3828 enterCreateObject(elementName);
 462  3828 return;
 463    }
 464   
 465  10329 if (elementName.equals("invoke-parent"))
 466    {
 467  4203 enterInvokeParent(elementName);
 468  4203 return;
 469    }
 470   
 471  6126 if (elementName.equals("read-attribute"))
 472    {
 473  2980 enterReadAttribute(elementName);
 474  2980 return;
 475    }
 476   
 477  3146 if (elementName.equals("read-content"))
 478    {
 479  1027 enterReadContent(elementName);
 480  1027 return;
 481    }
 482   
 483  2119 if (elementName.equals("set-module"))
 484    {
 485  10 enterSetModule(elementName);
 486  10 return;
 487    }
 488   
 489  2109 if (elementName.equals("set-property"))
 490    {
 491  1717 enterSetProperty(elementName);
 492  1717 return;
 493    }
 494   
 495  392 if (elementName.equals("push-attribute"))
 496    {
 497  377 enterPushAttribute(elementName);
 498  377 return;
 499    }
 500   
 501  15 if (elementName.equals("push-content"))
 502    {
 503  1 enterPushContent(elementName);
 504  1 return;
 505    }
 506   
 507  14 if (elementName.equals("set-parent"))
 508    {
 509  12 enterSetParent(elementName);
 510  12 return;
 511    }
 512   
 513  2 if (elementName.equals("custom"))
 514    {
 515  2 enterCustom(elementName);
 516   
 517  1 return;
 518    }
 519   
 520  0 unexpectedElement(elementName);
 521    }
 522   
 523  1359 private void beginSchema(String elementName)
 524    {
 525  1359 if (elementName.equals("element"))
 526    {
 527  1359 SchemaImpl schema = (SchemaImpl) peekObject();
 528   
 529  1359 schema.addElementModel(enterElement(elementName));
 530  1358 return;
 531    }
 532   
 533  0 unexpectedElement(elementName);
 534    }
 535   
 536  2796 private void beginServicePoint(String elementName)
 537    {
 538  2796 if (elementName.equals("parameters-schema"))
 539    {
 540  128 enterParametersSchema(elementName);
 541  128 return;
 542    }
 543   
 544    // <service-point> allows an super-set of <implementation>.
 545   
 546  2668 beginImplementation(elementName);
 547    }
 548   
 549    /**
 550    * begin outermost element, expect "module".
 551    */
 552  283 private void beginStart(String elementName)
 553    {
 554  283 if (!elementName.equals("module"))
 555  0 throw new ApplicationRuntimeException(ParseMessages.notModule(
 556    elementName,
 557    getLocation()), getLocation(), null);
 558   
 559  283 ModuleDescriptor md = new ModuleDescriptor(_resolver, _errorHandler);
 560   
 561  283 push(elementName, md, STATE_MODULE);
 562   
 563  283 checkAttributes();
 564   
 565  283 md.setModuleId(getValidatedAttribute("id", MODULE_ID_PATTERN, "module-id-format"));
 566  283 md.setVersion(getValidatedAttribute("version", VERSION_PATTERN, "version-format"));
 567   
 568  283 String packageName = getAttribute("package");
 569  283 if (packageName == null)
 570  144 packageName = md.getModuleId();
 571   
 572  283 md.setPackageName(packageName);
 573   
 574    // And, this is what we ultimately return from the parse.
 575   
 576  283 _moduleDescriptor = md;
 577    }
 578   
 579  36690 protected void push(String elementName, Object object, int state)
 580    {
 581  36690 if (object instanceof AnnotationHolder)
 582  18430 super.push(elementName, object, state, false);
 583    else
 584  18260 super.push(elementName, object, state, true);
 585    }
 586   
 587  5395 private ElementImpl buildLWDomElement(String elementName)
 588    {
 589  5395 ElementImpl result = new ElementImpl();
 590  5395 result.setElementName(elementName);
 591   
 592  5395 Iterator i = _attributes.entrySet().iterator();
 593  5395 while (i.hasNext())
 594    {
 595  9288 Map.Entry entry = (Map.Entry) i.next();
 596   
 597  9288 String name = (String) entry.getKey();
 598  9288 String value = (String) entry.getValue();
 599   
 600  9288 Attribute a = new AttributeImpl(name, value);
 601   
 602  9288 result.addAttribute(a);
 603    }
 604   
 605  5395 return result;
 606    }
 607   
 608  32466 private void checkAttributes()
 609    {
 610  32466 checkAttributes(peekElementName());
 611    }
 612   
 613    /**
 614    * Checks that only known attributes are specified. Checks that all required attribute are
 615    * specified.
 616    */
 617  33226 private void checkAttributes(String elementName)
 618    {
 619  33226 Iterator i = _attributes.keySet().iterator();
 620   
 621  33226 ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 622   
 623    // A few elements have no attributes at all.
 624   
 625  33226 if (epi == null)
 626    {
 627  264 epi = new ElementParseInfo();
 628  264 _elementParseInfo.put(elementName, epi);
 629    }
 630   
 631    // First, check that each attribute is in the set of expected attributes.
 632   
 633  33226 while (i.hasNext())
 634    {
 635  50592 String name = (String) i.next();
 636   
 637  50592 if (!epi.isKnown(name))
 638  1 _errorHandler.error(
 639    LOG,
 640    ParseMessages.unknownAttribute(name, getElementPath()),
 641    getLocation(),
 642    null);
 643    }
 644   
 645    // Now check that all required attributes have been specified.
 646   
 647  33226 i = epi.getRequiredNames();
 648  33226 while (i.hasNext())
 649    {
 650  36897 String name = (String) i.next();
 651   
 652  36897 if (!_attributes.containsKey(name))
 653  1 throw new ApplicationRuntimeException(ParseMessages.requiredAttribute(
 654    name,
 655    getElementPath(),
 656    getLocation()));
 657    }
 658   
 659    }
 660   
 661  42074 public void end(String elementName)
 662    {
 663  42074 switch (getState())
 664    {
 665  5395 case STATE_LWDOM:
 666   
 667  5395 endLWDom();
 668  5395 break;
 669   
 670  518 case STATE_CONVERSION:
 671   
 672  518 endConversion();
 673  518 break;
 674   
 675  1216 case STATE_SCHEMA:
 676   
 677  1216 endSchema();
 678  1216 break;
 679   
 680  34945 default:
 681   
 682  34945 String content = peekContent();
 683   
 684  34945 if (content != null && (peekObject() instanceof AnnotationHolder))
 685  16862 ((AnnotationHolder) peekObject()).setAnnotation(content);
 686   
 687  34945 break;
 688    }
 689   
 690    // Pop the top item off the stack.
 691   
 692  42074 pop();
 693    }
 694   
 695  1216 private void endSchema()
 696    {
 697  1216 SchemaImpl schema = (SchemaImpl) peekObject();
 698   
 699  1216 schema.setAnnotation(peekContent());
 700   
 701  1216 try
 702    {
 703  1216 schema.validateKeyAttributes();
 704    }
 705    catch (ApplicationRuntimeException e)
 706    {
 707  1 _errorHandler.error(LOG, ParseMessages.invalidElementKeyAttribute(schema.getId(), e), e
 708    .getLocation(), e);
 709    }
 710    }
 711   
 712  518 private void endConversion()
 713    {
 714  518 ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 715   
 716  518 cd.addRulesForModel();
 717    }
 718   
 719  5395 private void endLWDom()
 720    {
 721  5395 ElementImpl element = (ElementImpl) peekObject();
 722  5395 element.setContent(peekContent());
 723    }
 724   
 725  5027 private void enterAttribute(String elementName)
 726    {
 727  5027 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 728   
 729  5027 AttributeModelImpl attributeModel = new AttributeModelImpl();
 730   
 731  5027 push(elementName, attributeModel, STATE_NO_CONTENT);
 732   
 733  5027 checkAttributes();
 734   
 735  5027 attributeModel.setName(getAttribute("name"));
 736  5027 attributeModel.setRequired(getBooleanAttribute("required", false));
 737  5027 attributeModel.setUnique(getBooleanAttribute("unique", false));
 738  5027 attributeModel.setTranslator(getAttribute("translator", "smart"));
 739   
 740  5027 elementModel.addAttributeModel(attributeModel);
 741    }
 742   
 743  1079 private void enterConfigurationPoint(String elementName)
 744    {
 745  1079 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 746   
 747  1079 ConfigurationPointDescriptor cpd = new ConfigurationPointDescriptor();
 748   
 749  1079 push(elementName, cpd, STATE_CONFIGURATION_POINT);
 750   
 751  1079 checkAttributes();
 752   
 753  1079 cpd.setId(getValidatedAttribute("id", ID_PATTERN, "id-format"));
 754   
 755  1079 Occurances count = (Occurances) getEnumAttribute("occurs", OCCURS_MAP);
 756   
 757  1079 if (count != null)
 758  24 cpd.setCount(count);
 759   
 760  1079 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 761   
 762  1079 if (visibility != null)
 763  3 cpd.setVisibility(visibility);
 764   
 765  1079 cpd.setContributionsSchemaId(getAttribute("schema-id"));
 766   
 767  1079 md.addConfigurationPoint(cpd);
 768    }
 769   
 770  709 private void enterContribution(String elementName)
 771    {
 772  709 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 773   
 774  709 ContributionDescriptor cd = new ContributionDescriptor();
 775   
 776  709 push(elementName, cd, STATE_CONTRIBUTION);
 777   
 778  709 checkAttributes();
 779   
 780  709 cd.setConfigurationId(getAttribute("configuration-id"));
 781  709 cd.setConditionalExpression(getAttribute("if"));
 782   
 783  709 md.addContribution(cd);
 784    }
 785   
 786  518 private void enterConversion(String elementName)
 787    {
 788  518 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 789   
 790  518 ConversionDescriptor cd = new ConversionDescriptor(_errorHandler, elementModel);
 791   
 792  518 push(elementName, cd, STATE_CONVERSION);
 793   
 794  518 checkAttributes();
 795   
 796  518 cd.setClassName(getAttribute("class"));
 797   
 798  518 String methodName = getAttribute("parent-method");
 799   
 800  518 if (methodName != null)
 801  1 cd.setParentMethodName(methodName);
 802   
 803  518 elementModel.addRule(cd);
 804    }
 805   
 806  1314 private void enterCreateInstance(String elementName)
 807    {
 808  1314 AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 809  1314 CreateInstanceDescriptor cid = new CreateInstanceDescriptor();
 810   
 811  1314 push(elementName, cid, STATE_CREATE_INSTANCE);
 812   
 813  1314 checkAttributes();
 814   
 815  1314 cid.setInstanceClassName(getAttribute("class"));
 816   
 817  1314 String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 818   
 819  1314 cid.setServiceModel(model);
 820   
 821  1314 sd.setInstanceBuilder(cid);
 822   
 823    }
 824   
 825  3828 private void enterCreateObject(String elementName)
 826    {
 827  3828 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 828  3828 CreateObjectRule rule = new CreateObjectRule();
 829  3828 push(elementName, rule, STATE_NO_CONTENT);
 830   
 831  3828 checkAttributes();
 832   
 833  3828 rule.setClassName(getAttribute("class"));
 834   
 835  3828 elementModel.addRule(rule);
 836    }
 837   
 838  2 private void enterCustom(String elementName)
 839    {
 840  2 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 841   
 842    // Don't know what it is going to be, yet.
 843   
 844  2 push(elementName, null, STATE_NO_CONTENT);
 845   
 846  2 checkAttributes();
 847   
 848  2 String ruleClassName = getAttribute("class");
 849   
 850  2 Rule rule = getCustomRule(ruleClassName);
 851   
 852  1 elementModel.addRule(rule);
 853    }
 854   
 855    /**
 856    * Pushes STATE_ELEMENT onto the stack and creates and returns the {@link ElementModelImpl} it
 857    * creates.
 858    */
 859  3995 private ElementModel enterElement(String elementName)
 860    {
 861  3995 ElementModelImpl result = new ElementModelImpl();
 862   
 863  3995 push(elementName, result, STATE_ELEMENT);
 864   
 865  3995 checkAttributes();
 866   
 867  3994 result.setElementName(getAttribute("name"));
 868  3994 result.setKeyAttribute(getAttribute("key-attribute"));
 869  3994 result.setContentTranslator(getAttribute("content-translator"));
 870   
 871  3994 return result;
 872    }
 873   
 874  760 private void enterEmbeddedConfigurationPointSchema(String elementName)
 875    {
 876  760 ConfigurationPointDescriptor cpd = (ConfigurationPointDescriptor) peekObject();
 877   
 878  760 SchemaImpl schema = new SchemaImpl();
 879   
 880  760 push(elementName, schema, STATE_SCHEMA);
 881   
 882  760 if (cpd.getContributionsSchemaId() != null)
 883    {
 884  2 cpd.setContributionsSchemaId(null);
 885  2 cpd.setContributionsSchema(schema);
 886  2 _errorHandler.error(LOG, ParseMessages.multipleContributionsSchemas(cpd.getId(), schema
 887    .getLocation()), schema.getLocation(), null);
 888    }
 889    else
 890  758 cpd.setContributionsSchema(schema);
 891   
 892  760 checkAttributes("schema{embedded}");
 893    }
 894   
 895  128 private void enterParametersSchema(String elementName)
 896    {
 897  128 ServicePointDescriptor spd = (ServicePointDescriptor) peekObject();
 898  128 SchemaImpl schema = new SchemaImpl();
 899   
 900  128 push(elementName, schema, STATE_SCHEMA);
 901   
 902  128 checkAttributes();
 903   
 904  128 if (spd.getParametersSchemaId() != null)
 905    {
 906  2 spd.setParametersSchemaId(null);
 907  2 spd.setParametersSchema(schema);
 908  2 _errorHandler.error(LOG, ParseMessages.multipleParametersSchemas(spd.getId(), schema
 909    .getLocation()), schema.getLocation(), null);
 910    }
 911    else
 912  126 spd.setParametersSchema(schema);
 913    }
 914   
 915  16 private void enterImplementation(String elementName)
 916    {
 917  16 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 918   
 919  16 ImplementationDescriptor id = new ImplementationDescriptor();
 920   
 921  16 push(elementName, id, STATE_IMPLEMENTATION);
 922   
 923  16 checkAttributes();
 924   
 925  16 id.setServiceId(getAttribute("service-id"));
 926  16 id.setConditionalExpression(getAttribute("if"));
 927   
 928  16 md.addImplementation(id);
 929    }
 930   
 931  66 private void enterInterceptor(String elementName)
 932    {
 933  66 AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 934  66 InterceptorDescriptor id = new InterceptorDescriptor();
 935   
 936  66 push(elementName, id, STATE_COLLECT_SERVICE_PARAMETERS);
 937   
 938  66 checkAttributes();
 939   
 940  66 id.setFactoryServiceId(getAttribute("service-id"));
 941   
 942  66 id.setBefore(getAttribute("before"));
 943  66 id.setAfter(getAttribute("after"));
 944  66 id.setName(getAttribute("name"));
 945  66 sd.addInterceptor(id);
 946   
 947    }
 948   
 949  1306 private void enterInvokeFactory(String elementName)
 950    {
 951  1306 AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 952  1306 InvokeFactoryDescriptor ifd = new InvokeFactoryDescriptor();
 953   
 954  1306 push(elementName, ifd, STATE_COLLECT_SERVICE_PARAMETERS);
 955   
 956  1306 checkAttributes();
 957   
 958  1306 ifd.setFactoryServiceId(getAttribute("service-id", "hivemind.BuilderFactory"));
 959   
 960  1306 String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 961   
 962  1306 ifd.setServiceModel(model);
 963   
 964    // TODO: Check if instanceBuilder already set
 965   
 966  1306 sd.setInstanceBuilder(ifd);
 967   
 968    }
 969   
 970  4203 private void enterInvokeParent(String elementName)
 971    {
 972  4203 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 973  4203 InvokeParentRule rule = new InvokeParentRule();
 974   
 975  4203 push(elementName, rule, STATE_NO_CONTENT);
 976   
 977  4203 checkAttributes();
 978   
 979  4203 rule.setMethodName(getAttribute("method"));
 980   
 981  4203 if (_attributes.containsKey("depth"))
 982  3366 rule.setDepth(getIntAttribute("depth"));
 983   
 984  4203 elementModel.addRule(rule);
 985    }
 986   
 987  2980 private void enterReadAttribute(String elementName)
 988    {
 989  2980 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 990  2980 ReadAttributeRule rule = new ReadAttributeRule();
 991   
 992  2980 push(elementName, rule, STATE_NO_CONTENT);
 993   
 994  2980 checkAttributes();
 995   
 996  2980 rule.setPropertyName(getAttribute("property"));
 997  2980 rule.setAttributeName(getAttribute("attribute"));
 998  2980 rule.setSkipIfNull(getBooleanAttribute("skip-if-null", true));
 999  2980 rule.setTranslator(getAttribute("translator"));
 1000   
 1001  2980 elementModel.addRule(rule);
 1002    }
 1003   
 1004  1027 private void enterReadContent(String elementName)
 1005    {
 1006  1027 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1007  1027 ReadContentRule rule = new ReadContentRule();
 1008   
 1009  1027 push(elementName, rule, STATE_NO_CONTENT);
 1010   
 1011  1027 checkAttributes();
 1012   
 1013  1027 rule.setPropertyName(getAttribute("property"));
 1014   
 1015  1027 elementModel.addRule(rule);
 1016    }
 1017   
 1018  3464 private void enterRules(String elementName)
 1019    {
 1020  3464 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1021   
 1022  3464 push(elementName, elementModel, STATE_RULES);
 1023   
 1024    }
 1025   
 1026  331 private void enterSchema(String elementName)
 1027    {
 1028  331 SchemaImpl schema = new SchemaImpl();
 1029   
 1030  331 push(elementName, schema, STATE_SCHEMA);
 1031   
 1032  331 checkAttributes();
 1033   
 1034  331 String id = getValidatedAttribute("id", ID_PATTERN, "id-format");
 1035   
 1036  331 schema.setId(id);
 1037   
 1038  331 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 1039   
 1040  331 if (visibility != null)
 1041  1 schema.setVisibility(visibility);
 1042   
 1043  331 _moduleDescriptor.addSchema(schema);
 1044    }
 1045   
 1046  2638 private void enterServicePoint(String elementName)
 1047    {
 1048  2638 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 1049   
 1050  2638 ServicePointDescriptor spd = new ServicePointDescriptor();
 1051   
 1052  2638 push(elementName, spd, STATE_SERVICE_POINT);
 1053   
 1054  2638 checkAttributes();
 1055   
 1056  2638 String id = getValidatedAttribute("id", ID_PATTERN, "id-format");
 1057   
 1058    // Get the interface name, and default it to the service id if omitted.
 1059   
 1060  2638 String interfaceAttribute = getAttribute("interface", id);
 1061   
 1062    // Qualify the interface name with the defined package name (which will
 1063    // often implicitly or explicitly match the module id).
 1064   
 1065  2638 String interfaceName = IdUtils.qualify(
 1066    _moduleDescriptor.getPackageName(),
 1067    interfaceAttribute);
 1068   
 1069  2638 spd.setId(id);
 1070   
 1071  2638 spd.setInterfaceClassName(interfaceName);
 1072   
 1073  2638 spd.setParametersSchemaId(getAttribute("parameters-schema-id"));
 1074   
 1075  2638 Occurances count = (Occurances) getEnumAttribute("parameters-occurs", OCCURS_MAP);
 1076   
 1077  2638 if (count != null)
 1078  122 spd.setParametersCount(count);
 1079   
 1080  2638 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 1081   
 1082  2638 if (visibility != null)
 1083  1101 spd.setVisibility(visibility);
 1084   
 1085  2638 md.addServicePoint(spd);
 1086    }
 1087   
 1088  10 private void enterSetModule(String elementName)
 1089    {
 1090  10 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1091  10 SetModuleRule rule = new SetModuleRule();
 1092   
 1093  10 push(elementName, rule, STATE_NO_CONTENT);
 1094   
 1095  10 checkAttributes();
 1096   
 1097  10 rule.setPropertyName(getAttribute("property"));
 1098   
 1099  10 elementModel.addRule(rule);
 1100    }
 1101   
 1102  12 private void enterSetParent(String elementName)
 1103    {
 1104  12 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1105  12 SetParentRule rule = new SetParentRule();
 1106   
 1107  12 push(elementName, rule, STATE_NO_CONTENT);
 1108   
 1109  12 checkAttributes();
 1110   
 1111  12 rule.setPropertyName(getAttribute("property"));
 1112   
 1113  12 elementModel.addRule(rule);
 1114    }
 1115   
 1116  1717 private void enterSetProperty(String elementName)
 1117    {
 1118  1717 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1119   
 1120  1717 SetPropertyRule rule = new SetPropertyRule();
 1121   
 1122  1717 push(elementName, rule, STATE_NO_CONTENT);
 1123   
 1124  1717 checkAttributes();
 1125   
 1126  1717 rule.setPropertyName(getAttribute("property"));
 1127  1717 rule.setValue(getAttribute("value"));
 1128   
 1129  1717 elementModel.addRule(rule);
 1130    }
 1131   
 1132  377 private void enterPushAttribute(String elementName)
 1133    {
 1134  377 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1135   
 1136  377 PushAttributeRule rule = new PushAttributeRule();
 1137   
 1138  377 push(elementName, rule, STATE_NO_CONTENT);
 1139   
 1140  377 checkAttributes();
 1141   
 1142  377 rule.setAttributeName(getAttribute("attribute"));
 1143   
 1144  377 elementModel.addRule(rule);
 1145    }
 1146   
 1147  1 private void enterPushContent(String elementName)
 1148    {
 1149  1 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1150   
 1151  1 PushContentRule rule = new PushContentRule();
 1152   
 1153  1 push(elementName, rule, STATE_NO_CONTENT);
 1154   
 1155  1 checkAttributes();
 1156   
 1157  1 elementModel.addRule(rule);
 1158    }
 1159   
 1160  3 private void enterSubModule(String elementName)
 1161    {
 1162  3 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 1163   
 1164  3 SubModuleDescriptor smd = new SubModuleDescriptor();
 1165   
 1166  3 push(elementName, smd, STATE_NO_CONTENT);
 1167   
 1168  3 checkAttributes();
 1169   
 1170  3 Resource descriptor = getResource().getRelativeResource(getAttribute("descriptor"));
 1171   
 1172  3 smd.setDescriptor(descriptor);
 1173   
 1174  3 md.addSubModule(smd);
 1175    }
 1176   
 1177  10 private void enterDependency(String elementName)
 1178    {
 1179  10 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 1180   
 1181  10 DependencyDescriptor dd = new DependencyDescriptor();
 1182   
 1183  10 push(elementName, dd, STATE_NO_CONTENT);
 1184   
 1185  10 checkAttributes();
 1186   
 1187  10 dd.setModuleId(getAttribute("module-id"));
 1188  10 dd.setVersion(getAttribute("version"));
 1189   
 1190  10 md.addDependency(dd);
 1191    }
 1192   
 1193  77480 private String getAttribute(String name)
 1194    {
 1195  77480 return (String) _attributes.get(name);
 1196    }
 1197   
 1198  11591 private String getAttribute(String name, String defaultValue)
 1199    {
 1200  11591 String result = (String) _attributes.get(name);
 1201   
 1202  11591 if (result == null)
 1203  6767 result = defaultValue;
 1204   
 1205  11591 return result;
 1206    }
 1207   
 1208  4614 private String getValidatedAttribute(String name, String pattern, String formatKey)
 1209    {
 1210  4614 String result = getAttribute(name);
 1211   
 1212  4614 if (!validateFormat(result, pattern))
 1213  3 _errorHandler.error(LOG, ParseMessages.invalidAttributeFormat(
 1214    name,
 1215    result,
 1216    getElementPath(),
 1217    formatKey), getLocation(), null);
 1218   
 1219  4614 return result;
 1220    }
 1221   
 1222  4614 private boolean validateFormat(String input, String pattern)
 1223    {
 1224  4614 if (_compiler == null)
 1225    {
 1226  270 _compiler = new Perl5Compiler();
 1227  270 _matcher = new Perl5Matcher();
 1228  270 _compiledPatterns = new HashMap();
 1229    }
 1230   
 1231  4614 Pattern compiled = (Pattern) _compiledPatterns.get(pattern);
 1232  4614 if (compiled == null)
 1233    {
 1234   
 1235  802 try
 1236    {
 1237  802 compiled = _compiler.compile(pattern);
 1238    }
 1239    catch (MalformedPatternException ex)
 1240    {
 1241  0 throw new ApplicationRuntimeException(ex);
 1242    }
 1243   
 1244  802 _compiledPatterns.put(pattern, compiled);
 1245    }
 1246   
 1247  4614 return _matcher.matches(input, compiled);
 1248    }
 1249   
 1250  13034 private boolean getBooleanAttribute(String name, boolean defaultValue)
 1251    {
 1252  13034 String value = getAttribute(name);
 1253   
 1254  13034 if (value == null)
 1255  9569 return defaultValue;
 1256   
 1257  3465 if (value.equals("true"))
 1258  2961 return true;
 1259   
 1260  504 if (value.equals("false"))
 1261  504 return false;
 1262   
 1263  0 _errorHandler.error(
 1264    LOG,
 1265    ParseMessages.booleanAttribute(value, name, getElementPath()),
 1266    getLocation(),
 1267    null);
 1268   
 1269  0 return defaultValue;
 1270    }
 1271   
 1272  2 private Rule getCustomRule(String ruleClassName)
 1273    {
 1274  2 Rule result = (Rule) _ruleMap.get(ruleClassName);
 1275   
 1276  2 if (result == null)
 1277    {
 1278  2 result = instantiateRule(ruleClassName);
 1279   
 1280  1 _ruleMap.put(ruleClassName, result);
 1281    }
 1282   
 1283  1 return result;
 1284    }
 1285   
 1286    /**
 1287    * Gets the value for the attribute and uses the Map to translate it to an object value. Returns
 1288    * the object value if succesfully translated. Returns null if unsuccesful. If a value is
 1289    * provided that isn't a key of the map, and error is logged and null is returned.
 1290    */
 1291  7765 private Object getEnumAttribute(String name, Map translations)
 1292    {
 1293  7765 String value = getAttribute(name);
 1294   
 1295  7765 if (value == null)
 1296  6514 return null;
 1297   
 1298  1251 Object result = translations.get(value);
 1299   
 1300  1251 if (result == null)
 1301  0 _errorHandler.error(LOG, ParseMessages.invalidAttributeValue(
 1302    value,
 1303    name,
 1304    getElementPath()), getLocation(), null);
 1305   
 1306  1251 return result;
 1307    }
 1308   
 1309  3366 private int getIntAttribute(String name)
 1310    {
 1311  3366 String value = getAttribute(name);
 1312   
 1313  3366 try
 1314    {
 1315  3366 return Integer.parseInt(value);
 1316    }
 1317    catch (NumberFormatException ex)
 1318    {
 1319  0 _errorHandler.error(LOG, ParseMessages.invalidNumericValue(
 1320    value,
 1321    name,
 1322    getElementPath()), getLocation(), ex);
 1323   
 1324  0 return 0;
 1325    }
 1326    }
 1327   
 1328  271 private void initializeFromProperties(Properties p)
 1329    {
 1330  271 Enumeration e = p.propertyNames();
 1331   
 1332  271 while (e.hasMoreElements())
 1333    {
 1334  14634 String key = (String) e.nextElement();
 1335  14634 String value = p.getProperty(key);
 1336   
 1337  14634 initializeFromProperty(key, value);
 1338    }
 1339    }
 1340   
 1341    /**
 1342    * Invoked from the constructor to read the properties file that defines certain aspects of the
 1343    * operation of the parser.
 1344    */
 1345  271 private void initializeFromPropertiesFile()
 1346    {
 1347  271 Properties p = new Properties();
 1348   
 1349  271 try
 1350    {
 1351   
 1352  271 InputStream propertiesIn = getClass()
 1353    .getResourceAsStream("DescriptorParser.properties");
 1354  271 InputStream bufferedIn = new BufferedInputStream(propertiesIn);
 1355   
 1356  271 p.load(bufferedIn);
 1357   
 1358  271 bufferedIn.close();
 1359    }
 1360    catch (IOException ex)
 1361    {
 1362  0 _errorHandler.error(LOG, ParseMessages.unableToInitialize(ex), null, ex);
 1363    }
 1364   
 1365  271 initializeFromProperties(p);
 1366    }
 1367   
 1368  14634 private void initializeFromProperty(String key, String value)
 1369    {
 1370  14634 if (key.startsWith("required."))
 1371    {
 1372  14634 initializeRequired(key, value);
 1373  14634 return;
 1374    }
 1375   
 1376    }
 1377   
 1378  14634 private void initializeRequired(String key, String value)
 1379    {
 1380  14634 boolean required = value.equals("true");
 1381   
 1382  14634 int lastdotx = key.lastIndexOf('.');
 1383   
 1384  14634 String elementName = key.substring(9, lastdotx);
 1385  14634 String attributeName = key.substring(lastdotx + 1);
 1386   
 1387  14634 ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 1388   
 1389  14634 if (epi == null)
 1390    {
 1391  6504 epi = new ElementParseInfo();
 1392  6504 _elementParseInfo.put(elementName, epi);
 1393    }
 1394   
 1395  14634 epi.addAttribute(attributeName, required);
 1396    }
 1397   
 1398  2 private Rule instantiateRule(String ruleClassName)
 1399    {
 1400  2 try
 1401    {
 1402  2 Class ruleClass = _resolver.findClass(ruleClassName);
 1403   
 1404  1 return (Rule) ruleClass.newInstance();
 1405    }
 1406    catch (Exception ex)
 1407    {
 1408  1 throw new ApplicationRuntimeException(ParseMessages.badRuleClass(
 1409    ruleClassName,
 1410    getLocation(),
 1411    ex), getLocation(), ex);
 1412    }
 1413    }
 1414   
 1415    /** @since 1.1 */
 1416  285 public void initialize(Resource resource, ClassResolver resolver)
 1417    {
 1418  285 initializeParser(resource, STATE_START);
 1419   
 1420  285 _resolver = resolver;
 1421    }
 1422   
 1423    /** @since 1.1 */
 1424  280 public ModuleDescriptor getModuleDescriptor()
 1425    {
 1426  280 return _moduleDescriptor;
 1427    }
 1428   
 1429    /** @since 1.1 */
 1430  0 public void reset()
 1431    {
 1432  0 super.resetParser();
 1433   
 1434  0 _moduleDescriptor = null;
 1435  0 _attributes.clear();
 1436  0 _resolver = null;
 1437    }
 1438    }