Clover coverage report - Code Coverage for hivemind release 1.1-beta-2
Coverage timestamp: Tue Jun 28 2005 10:28:23 EDT
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  269 OCCURS_MAP.put("0..1", Occurances.OPTIONAL);
 174  269 OCCURS_MAP.put("1", Occurances.REQUIRED);
 175  269 OCCURS_MAP.put("1..n", Occurances.ONE_PLUS);
 176  269 OCCURS_MAP.put("0..n", Occurances.UNBOUNDED);
 177  269 OCCURS_MAP.put("none", Occurances.NONE);
 178    }
 179   
 180    private final Map VISIBILITY_MAP = new HashMap();
 181   
 182    {
 183  269 VISIBILITY_MAP.put("public", Visibility.PUBLIC);
 184  269 VISIBILITY_MAP.put("private", Visibility.PRIVATE);
 185    }
 186   
 187  269 public DescriptorParser(ErrorHandler errorHandler)
 188    {
 189  269 _errorHandler = errorHandler;
 190   
 191  269 initializeFromPropertiesFile();
 192    }
 193   
 194  41999 public void begin(String elementName, Map attributes)
 195    {
 196  41999 _attributes = attributes;
 197   
 198  41999 switch (getState())
 199    {
 200  281 case STATE_START:
 201   
 202  281 beginStart(elementName);
 203  281 break;
 204   
 205  4749 case STATE_MODULE:
 206   
 207  4749 beginModule(elementName);
 208  4749 break;
 209   
 210  754 case STATE_CONFIGURATION_POINT:
 211   
 212  754 beginConfigurationPoint(elementName);
 213  754 break;
 214   
 215  3112 case STATE_CONTRIBUTION:
 216   
 217  3112 beginContribution(elementName);
 218  3112 break;
 219   
 220  1186 case STATE_LWDOM:
 221   
 222  1186 beginLWDom(elementName);
 223  1186 break;
 224   
 225  2776 case STATE_SERVICE_POINT:
 226   
 227  2776 beginServicePoint(elementName);
 228  2776 break;
 229   
 230  18 case STATE_IMPLEMENTATION:
 231   
 232  18 beginImplementation(elementName);
 233  18 break;
 234   
 235  1348 case STATE_SCHEMA:
 236   
 237  1348 beginSchema(elementName);
 238  1347 break;
 239   
 240  11554 case STATE_ELEMENT:
 241   
 242  11554 beginElement(elementName);
 243  11553 break;
 244   
 245  14044 case STATE_RULES:
 246   
 247  14044 beginRules(elementName);
 248  14043 break;
 249   
 250  1298 case STATE_COLLECT_SERVICE_PARAMETERS:
 251   
 252  1298 beginCollectServiceParameters(elementName);
 253  1298 break;
 254   
 255  879 case STATE_CONVERSION:
 256   
 257  879 beginConversion(elementName);
 258  879 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  1298 private void beginCollectServiceParameters(String elementName)
 275    {
 276  1298 ElementImpl element = buildLWDomElement(elementName);
 277   
 278  1298 AbstractServiceInvocationDescriptor sid = (AbstractServiceInvocationDescriptor) peekObject();
 279   
 280  1298 sid.addParameter(element);
 281   
 282  1298 push(elementName, element, STATE_LWDOM, false);
 283    }
 284   
 285    /**
 286    * Invoked when a new element starts within STATE_CONFIGURATION_POINT.
 287    */
 288  754 private void beginConfigurationPoint(String elementName)
 289    {
 290  754 if (elementName.equals("schema"))
 291    {
 292  754 enterEmbeddedConfigurationPointSchema(elementName);
 293  754 return;
 294    }
 295   
 296  0 unexpectedElement(elementName);
 297    }
 298   
 299  3112 private void beginContribution(String elementName)
 300    {
 301    // This is where things get tricky, the point where we outgrew Jakarta Digester.
 302   
 303  3112 ElementImpl element = buildLWDomElement(elementName);
 304   
 305  3112 ContributionDescriptor ed = (ContributionDescriptor) peekObject();
 306  3112 ed.addElement(element);
 307   
 308  3112 push(elementName, element, STATE_LWDOM, false);
 309    }
 310   
 311  879 private void beginConversion(String elementName)
 312    {
 313  879 if (elementName.equals("map"))
 314    {
 315  879 ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 316   
 317  879 AttributeMappingDescriptor amd = new AttributeMappingDescriptor();
 318   
 319  879 push(elementName, amd, STATE_NO_CONTENT);
 320   
 321  879 checkAttributes();
 322   
 323  879 amd.setAttributeName(getAttribute("attribute"));
 324  879 amd.setPropertyName(getAttribute("property"));
 325   
 326  879 cd.addAttributeMapping(amd);
 327   
 328  879 return;
 329    }
 330   
 331  0 unexpectedElement(elementName);
 332    }
 333   
 334  11554 private void beginElement(String elementName)
 335    {
 336  11554 if (elementName.equals("attribute"))
 337    {
 338  4988 enterAttribute(elementName);
 339  4988 return;
 340    }
 341   
 342  6566 if (elementName.equals("conversion"))
 343    {
 344  514 enterConversion(elementName);
 345  514 return;
 346    }
 347   
 348  6052 if (elementName.equals("rules"))
 349    {
 350  3436 enterRules(elementName);
 351  3436 return;
 352    }
 353   
 354    // <element> is recursive ... possible, but tricky, if using Digester.
 355   
 356  2616 if (elementName.equals("element"))
 357    {
 358  2615 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 359   
 360  2615 elementModel.addElementModel(enterElement(elementName));
 361  2615 return;
 362    }
 363   
 364  1 unexpectedElement(elementName);
 365    }
 366   
 367  2667 private void beginImplementation(String elementName)
 368    {
 369   
 370  2667 if (elementName.equals("create-instance"))
 371    {
 372  1183 enterCreateInstance(elementName);
 373  1183 return;
 374    }
 375   
 376  1484 if (elementName.equals("invoke-factory"))
 377    {
 378  1418 enterInvokeFactory(elementName);
 379  1418 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  1186 private void beginLWDom(String elementName)
 392    {
 393  1186 ElementImpl element = buildLWDomElement(elementName);
 394   
 395  1186 ElementImpl parent = (ElementImpl) peekObject();
 396  1186 parent.addElement(element);
 397   
 398  1186 push(elementName, element, STATE_LWDOM, false);
 399    }
 400   
 401    /**
 402    * Invoked when a new element occurs while in STATE_MODULE.
 403    */
 404  4749 private void beginModule(String elementName)
 405    {
 406  4749 if (elementName.equals("configuration-point"))
 407    {
 408  1070 enterConfigurationPoint(elementName);
 409   
 410  1070 return;
 411    }
 412   
 413  3679 if (elementName.equals("contribution"))
 414    {
 415  703 enterContribution(elementName);
 416  703 return;
 417    }
 418   
 419  2976 if (elementName.equals("service-point"))
 420    {
 421  2619 enterServicePoint(elementName);
 422   
 423  2619 return;
 424    }
 425   
 426  357 if (elementName.equals("implementation"))
 427    {
 428  16 enterImplementation(elementName);
 429   
 430  16 return;
 431    }
 432   
 433  341 if (elementName.equals("schema"))
 434    {
 435  328 enterSchema(elementName);
 436  328 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  14044 private void beginRules(String elementName)
 457    {
 458   
 459  14044 if (elementName.equals("create-object"))
 460    {
 461  3798 enterCreateObject(elementName);
 462  3798 return;
 463    }
 464   
 465  10246 if (elementName.equals("invoke-parent"))
 466    {
 467  4169 enterInvokeParent(elementName);
 468  4169 return;
 469    }
 470   
 471  6077 if (elementName.equals("read-attribute"))
 472    {
 473  2957 enterReadAttribute(elementName);
 474  2957 return;
 475    }
 476   
 477  3120 if (elementName.equals("read-content"))
 478    {
 479  1019 enterReadContent(elementName);
 480  1019 return;
 481    }
 482   
 483  2101 if (elementName.equals("set-module"))
 484    {
 485  10 enterSetModule(elementName);
 486  10 return;
 487    }
 488   
 489  2091 if (elementName.equals("set-property"))
 490    {
 491  1703 enterSetProperty(elementName);
 492  1703 return;
 493    }
 494   
 495  388 if (elementName.equals("push-attribute"))
 496    {
 497  373 enterPushAttribute(elementName);
 498  373 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  1348 private void beginSchema(String elementName)
 524    {
 525  1348 if (elementName.equals("element"))
 526    {
 527  1348 SchemaImpl schema = (SchemaImpl) peekObject();
 528   
 529  1348 schema.addElementModel(enterElement(elementName));
 530  1347 return;
 531    }
 532   
 533  0 unexpectedElement(elementName);
 534    }
 535   
 536  2776 private void beginServicePoint(String elementName)
 537    {
 538  2776 if (elementName.equals("parameters-schema"))
 539    {
 540  127 enterParametersSchema(elementName);
 541  127 return;
 542    }
 543   
 544    // <service-point> allows an super-set of <implementation>.
 545   
 546  2649 beginImplementation(elementName);
 547    }
 548   
 549    /**
 550    * begin outermost element, expect "module".
 551    */
 552  281 private void beginStart(String elementName)
 553    {
 554  281 if (!elementName.equals("module"))
 555  0 throw new ApplicationRuntimeException(ParseMessages.notModule(
 556    elementName,
 557    getLocation()), getLocation(), null);
 558   
 559  281 ModuleDescriptor md = new ModuleDescriptor(_resolver, _errorHandler);
 560   
 561  281 push(elementName, md, STATE_MODULE);
 562   
 563  281 checkAttributes();
 564   
 565  281 md.setModuleId(getValidatedAttribute("id", MODULE_ID_PATTERN, "module-id-format"));
 566  281 md.setVersion(getValidatedAttribute("version", VERSION_PATTERN, "version-format"));
 567   
 568  281 String packageName = getAttribute("package");
 569  281 if (packageName == null)
 570  153 packageName = md.getModuleId();
 571   
 572  281 md.setPackageName(packageName);
 573   
 574    // And, this is what we ultimately return from the parse.
 575   
 576  281 _moduleDescriptor = md;
 577    }
 578   
 579  36402 protected void push(String elementName, Object object, int state)
 580    {
 581  36402 if (object instanceof AnnotationHolder)
 582  18285 super.push(elementName, object, state, false);
 583    else
 584  18117 super.push(elementName, object, state, true);
 585    }
 586   
 587  5596 private ElementImpl buildLWDomElement(String elementName)
 588    {
 589  5596 ElementImpl result = new ElementImpl();
 590  5596 result.setElementName(elementName);
 591   
 592  5596 Iterator i = _attributes.entrySet().iterator();
 593  5596 while (i.hasNext())
 594    {
 595  9581 Map.Entry entry = (Map.Entry) i.next();
 596   
 597  9581 String name = (String) entry.getKey();
 598  9581 String value = (String) entry.getValue();
 599   
 600  9581 Attribute a = new AttributeImpl(name, value);
 601   
 602  9581 result.addAttribute(a);
 603    }
 604   
 605  5596 return result;
 606    }
 607   
 608  32212 private void checkAttributes()
 609    {
 610  32212 checkAttributes(peekElementName());
 611    }
 612   
 613    /**
 614    * Checks that only known attributes are specified. Checks that all required attribute are
 615    * specified.
 616    */
 617  32966 private void checkAttributes(String elementName)
 618    {
 619  32966 Iterator i = _attributes.keySet().iterator();
 620   
 621  32966 ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 622   
 623    // A few elements have no attributes at all.
 624   
 625  32966 if (epi == null)
 626    {
 627  262 epi = new ElementParseInfo();
 628  262 _elementParseInfo.put(elementName, epi);
 629    }
 630   
 631    // First, check that each attribute is in the set of expected attributes.
 632   
 633  32966 while (i.hasNext())
 634    {
 635  49945 String name = (String) i.next();
 636   
 637  49945 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  32966 i = epi.getRequiredNames();
 648  32966 while (i.hasNext())
 649    {
 650  36486 String name = (String) i.next();
 651   
 652  36486 if (!_attributes.containsKey(name))
 653  1 throw new ApplicationRuntimeException(ParseMessages.requiredAttribute(
 654    name,
 655    getElementPath(),
 656    getLocation()));
 657    }
 658   
 659    }
 660   
 661  41987 public void end(String elementName)
 662    {
 663  41987 switch (getState())
 664    {
 665  5596 case STATE_LWDOM:
 666   
 667  5596 endLWDom();
 668  5596 break;
 669   
 670  514 case STATE_CONVERSION:
 671   
 672  514 endConversion();
 673  514 break;
 674   
 675  1206 case STATE_SCHEMA:
 676   
 677  1206 endSchema();
 678  1206 break;
 679   
 680  34671 default:
 681   
 682  34671 String content = peekContent();
 683   
 684  34671 if (content != null && (peekObject() instanceof AnnotationHolder))
 685  16729 ((AnnotationHolder) peekObject()).setAnnotation(content);
 686   
 687  34671 break;
 688    }
 689   
 690    // Pop the top item off the stack.
 691   
 692  41987 pop();
 693    }
 694   
 695  1206 private void endSchema()
 696    {
 697  1206 SchemaImpl schema = (SchemaImpl) peekObject();
 698   
 699  1206 schema.setAnnotation(peekContent());
 700   
 701  1206 try
 702    {
 703  1206 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  514 private void endConversion()
 713    {
 714  514 ConversionDescriptor cd = (ConversionDescriptor) peekObject();
 715   
 716  514 cd.addRulesForModel();
 717    }
 718   
 719  5596 private void endLWDom()
 720    {
 721  5596 ElementImpl element = (ElementImpl) peekObject();
 722  5596 element.setContent(peekContent());
 723    }
 724   
 725  4988 private void enterAttribute(String elementName)
 726    {
 727  4988 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 728   
 729  4988 AttributeModelImpl attributeModel = new AttributeModelImpl();
 730   
 731  4988 push(elementName, attributeModel, STATE_NO_CONTENT);
 732   
 733  4988 checkAttributes();
 734   
 735  4988 attributeModel.setName(getAttribute("name"));
 736  4988 attributeModel.setRequired(getBooleanAttribute("required", false));
 737  4988 attributeModel.setUnique(getBooleanAttribute("unique", false));
 738  4988 attributeModel.setTranslator(getAttribute("translator", "smart"));
 739   
 740  4988 elementModel.addAttributeModel(attributeModel);
 741    }
 742   
 743  1070 private void enterConfigurationPoint(String elementName)
 744    {
 745  1070 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 746   
 747  1070 ConfigurationPointDescriptor cpd = new ConfigurationPointDescriptor();
 748   
 749  1070 push(elementName, cpd, STATE_CONFIGURATION_POINT);
 750   
 751  1070 checkAttributes();
 752   
 753  1070 cpd.setId(getValidatedAttribute("id", ID_PATTERN, "id-format"));
 754   
 755  1070 Occurances count = (Occurances) getEnumAttribute("occurs", OCCURS_MAP);
 756   
 757  1070 if (count != null)
 758  24 cpd.setCount(count);
 759   
 760  1070 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 761   
 762  1070 if (visibility != null)
 763  3 cpd.setVisibility(visibility);
 764   
 765  1070 cpd.setContributionsSchemaId(getAttribute("schema-id"));
 766   
 767  1070 md.addConfigurationPoint(cpd);
 768    }
 769   
 770  703 private void enterContribution(String elementName)
 771    {
 772  703 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 773   
 774  703 ContributionDescriptor cd = new ContributionDescriptor();
 775   
 776  703 push(elementName, cd, STATE_CONTRIBUTION);
 777   
 778  703 checkAttributes();
 779   
 780  703 cd.setConfigurationId(getAttribute("configuration-id"));
 781  703 cd.setConditionalExpression(getAttribute("if"));
 782   
 783  703 md.addContribution(cd);
 784    }
 785   
 786  514 private void enterConversion(String elementName)
 787    {
 788  514 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 789   
 790  514 ConversionDescriptor cd = new ConversionDescriptor(_errorHandler, elementModel);
 791   
 792  514 push(elementName, cd, STATE_CONVERSION);
 793   
 794  514 checkAttributes();
 795   
 796  514 cd.setClassName(getAttribute("class"));
 797   
 798  514 String methodName = getAttribute("parent-method");
 799   
 800  514 if (methodName != null)
 801  1 cd.setParentMethodName(methodName);
 802   
 803  514 elementModel.addRule(cd);
 804    }
 805   
 806  1183 private void enterCreateInstance(String elementName)
 807    {
 808  1183 AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 809  1183 CreateInstanceDescriptor cid = new CreateInstanceDescriptor();
 810   
 811  1183 push(elementName, cid, STATE_CREATE_INSTANCE);
 812   
 813  1183 checkAttributes();
 814   
 815  1183 cid.setInstanceClassName(getAttribute("class"));
 816   
 817  1183 String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 818   
 819  1183 cid.setServiceModel(model);
 820   
 821  1183 sd.setInstanceBuilder(cid);
 822   
 823    }
 824   
 825  3798 private void enterCreateObject(String elementName)
 826    {
 827  3798 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 828  3798 CreateObjectRule rule = new CreateObjectRule();
 829  3798 push(elementName, rule, STATE_NO_CONTENT);
 830   
 831  3798 checkAttributes();
 832   
 833  3798 rule.setClassName(getAttribute("class"));
 834   
 835  3798 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  3963 private ElementModel enterElement(String elementName)
 860    {
 861  3963 ElementModelImpl result = new ElementModelImpl();
 862   
 863  3963 push(elementName, result, STATE_ELEMENT);
 864   
 865  3963 checkAttributes();
 866   
 867  3962 result.setElementName(getAttribute("name"));
 868  3962 result.setKeyAttribute(getAttribute("key-attribute"));
 869  3962 result.setContentTranslator(getAttribute("content-translator"));
 870   
 871  3962 return result;
 872    }
 873   
 874  754 private void enterEmbeddedConfigurationPointSchema(String elementName)
 875    {
 876  754 ConfigurationPointDescriptor cpd = (ConfigurationPointDescriptor) peekObject();
 877   
 878  754 SchemaImpl schema = new SchemaImpl();
 879   
 880  754 push(elementName, schema, STATE_SCHEMA);
 881   
 882  754 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  752 cpd.setContributionsSchema(schema);
 891   
 892  754 checkAttributes("schema{embedded}");
 893    }
 894   
 895  127 private void enterParametersSchema(String elementName)
 896    {
 897  127 ServicePointDescriptor spd = (ServicePointDescriptor) peekObject();
 898  127 SchemaImpl schema = new SchemaImpl();
 899   
 900  127 push(elementName, schema, STATE_SCHEMA);
 901   
 902  127 checkAttributes();
 903   
 904  127 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  125 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  1418 private void enterInvokeFactory(String elementName)
 950    {
 951  1418 AbstractServiceDescriptor sd = (AbstractServiceDescriptor) peekObject();
 952  1418 InvokeFactoryDescriptor ifd = new InvokeFactoryDescriptor();
 953   
 954  1418 push(elementName, ifd, STATE_COLLECT_SERVICE_PARAMETERS);
 955   
 956  1418 checkAttributes();
 957   
 958  1418 ifd.setFactoryServiceId(getAttribute("service-id", "hivemind.BuilderFactory"));
 959   
 960  1418 String model = getAttribute("model", DEFAULT_SERVICE_MODEL);
 961   
 962  1418 ifd.setServiceModel(model);
 963   
 964    // TODO: Check if instanceBuilder already set
 965   
 966  1418 sd.setInstanceBuilder(ifd);
 967   
 968    }
 969   
 970  4169 private void enterInvokeParent(String elementName)
 971    {
 972  4169 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 973  4169 InvokeParentRule rule = new InvokeParentRule();
 974   
 975  4169 push(elementName, rule, STATE_NO_CONTENT);
 976   
 977  4169 checkAttributes();
 978   
 979  4169 rule.setMethodName(getAttribute("method"));
 980   
 981  4169 if (_attributes.containsKey("depth"))
 982  3339 rule.setDepth(getIntAttribute("depth"));
 983   
 984  4169 elementModel.addRule(rule);
 985    }
 986   
 987  2957 private void enterReadAttribute(String elementName)
 988    {
 989  2957 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 990  2957 ReadAttributeRule rule = new ReadAttributeRule();
 991   
 992  2957 push(elementName, rule, STATE_NO_CONTENT);
 993   
 994  2957 checkAttributes();
 995   
 996  2957 rule.setPropertyName(getAttribute("property"));
 997  2957 rule.setAttributeName(getAttribute("attribute"));
 998  2957 rule.setSkipIfNull(getBooleanAttribute("skip-if-null", true));
 999  2957 rule.setTranslator(getAttribute("translator"));
 1000   
 1001  2957 elementModel.addRule(rule);
 1002    }
 1003   
 1004  1019 private void enterReadContent(String elementName)
 1005    {
 1006  1019 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1007  1019 ReadContentRule rule = new ReadContentRule();
 1008   
 1009  1019 push(elementName, rule, STATE_NO_CONTENT);
 1010   
 1011  1019 checkAttributes();
 1012   
 1013  1019 rule.setPropertyName(getAttribute("property"));
 1014   
 1015  1019 elementModel.addRule(rule);
 1016    }
 1017   
 1018  3436 private void enterRules(String elementName)
 1019    {
 1020  3436 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1021   
 1022  3436 push(elementName, elementModel, STATE_RULES);
 1023   
 1024    }
 1025   
 1026  328 private void enterSchema(String elementName)
 1027    {
 1028  328 SchemaImpl schema = new SchemaImpl();
 1029   
 1030  328 push(elementName, schema, STATE_SCHEMA);
 1031   
 1032  328 checkAttributes();
 1033   
 1034  328 String id = getValidatedAttribute("id", ID_PATTERN, "id-format");
 1035   
 1036  328 schema.setId(id);
 1037   
 1038  328 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 1039   
 1040  328 if (visibility != null)
 1041  1 schema.setVisibility(visibility);
 1042   
 1043  328 _moduleDescriptor.addSchema(schema);
 1044    }
 1045   
 1046  2619 private void enterServicePoint(String elementName)
 1047    {
 1048  2619 ModuleDescriptor md = (ModuleDescriptor) peekObject();
 1049   
 1050  2619 ServicePointDescriptor spd = new ServicePointDescriptor();
 1051   
 1052  2619 push(elementName, spd, STATE_SERVICE_POINT);
 1053   
 1054  2619 checkAttributes();
 1055   
 1056  2619 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  2619 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  2619 String interfaceName = IdUtils.qualify(
 1066    _moduleDescriptor.getPackageName(),
 1067    interfaceAttribute);
 1068   
 1069  2619 spd.setId(id);
 1070   
 1071  2619 spd.setInterfaceClassName(interfaceName);
 1072   
 1073  2619 spd.setParametersSchemaId(getAttribute("parameters-schema-id"));
 1074   
 1075  2619 Occurances count = (Occurances) getEnumAttribute("parameters-occurs", OCCURS_MAP);
 1076   
 1077  2619 if (count != null)
 1078  121 spd.setParametersCount(count);
 1079   
 1080  2619 Visibility visibility = (Visibility) getEnumAttribute("visibility", VISIBILITY_MAP);
 1081   
 1082  2619 if (visibility != null)
 1083  1092 spd.setVisibility(visibility);
 1084   
 1085  2619 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  1703 private void enterSetProperty(String elementName)
 1117    {
 1118  1703 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1119   
 1120  1703 SetPropertyRule rule = new SetPropertyRule();
 1121   
 1122  1703 push(elementName, rule, STATE_NO_CONTENT);
 1123   
 1124  1703 checkAttributes();
 1125   
 1126  1703 rule.setPropertyName(getAttribute("property"));
 1127  1703 rule.setValue(getAttribute("value"));
 1128   
 1129  1703 elementModel.addRule(rule);
 1130    }
 1131   
 1132  373 private void enterPushAttribute(String elementName)
 1133    {
 1134  373 ElementModelImpl elementModel = (ElementModelImpl) peekObject();
 1135   
 1136  373 PushAttributeRule rule = new PushAttributeRule();
 1137   
 1138  373 push(elementName, rule, STATE_NO_CONTENT);
 1139   
 1140  373 checkAttributes();
 1141   
 1142  373 rule.setAttributeName(getAttribute("attribute"));
 1143   
 1144  373 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  76755 private String getAttribute(String name)
 1194    {
 1195  76755 return (String) _attributes.get(name);
 1196    }
 1197   
 1198  11626 private String getAttribute(String name, String defaultValue)
 1199    {
 1200  11626 String result = (String) _attributes.get(name);
 1201   
 1202  11626 if (result == null)
 1203  6958 result = defaultValue;
 1204   
 1205  11626 return result;
 1206    }
 1207   
 1208  4579 private String getValidatedAttribute(String name, String pattern, String formatKey)
 1209    {
 1210  4579 String result = getAttribute(name);
 1211   
 1212  4579 if (!validateFormat(result, pattern))
 1213  3 _errorHandler.error(LOG, ParseMessages.invalidAttributeFormat(
 1214    name,
 1215    result,
 1216    getElementPath(),
 1217    formatKey), getLocation(), null);
 1218   
 1219  4579 return result;
 1220    }
 1221   
 1222  4579 private boolean validateFormat(String input, String pattern)
 1223    {
 1224  4579 if (_compiler == null)
 1225    {
 1226  268 _compiler = new Perl5Compiler();
 1227  268 _matcher = new Perl5Matcher();
 1228  268 _compiledPatterns = new HashMap();
 1229    }
 1230   
 1231  4579 Pattern compiled = (Pattern) _compiledPatterns.get(pattern);
 1232  4579 if (compiled == null)
 1233    {
 1234   
 1235  796 try
 1236    {
 1237  796 compiled = _compiler.compile(pattern);
 1238    }
 1239    catch (MalformedPatternException ex)
 1240    {
 1241  0 throw new ApplicationRuntimeException(ex);
 1242    }
 1243   
 1244  796 _compiledPatterns.put(pattern, compiled);
 1245    }
 1246   
 1247  4579 return _matcher.matches(input, compiled);
 1248    }
 1249   
 1250  12933 private boolean getBooleanAttribute(String name, boolean defaultValue)
 1251    {
 1252  12933 String value = getAttribute(name);
 1253   
 1254  12933 if (value == null)
 1255  9495 return defaultValue;
 1256   
 1257  3438 if (value.equals("true"))
 1258  2938 return true;
 1259   
 1260  500 if (value.equals("false"))
 1261  500 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  7706 private Object getEnumAttribute(String name, Map translations)
 1292    {
 1293  7706 String value = getAttribute(name);
 1294   
 1295  7706 if (value == null)
 1296  6465 return null;
 1297   
 1298  1241 Object result = translations.get(value);
 1299   
 1300  1241 if (result == null)
 1301  0 _errorHandler.error(LOG, ParseMessages.invalidAttributeValue(
 1302    value,
 1303    name,
 1304    getElementPath()), getLocation(), null);
 1305   
 1306  1241 return result;
 1307    }
 1308   
 1309  3339 private int getIntAttribute(String name)
 1310    {
 1311  3339 String value = getAttribute(name);
 1312   
 1313  3339 try
 1314    {
 1315  3339 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  269 private void initializeFromProperties(Properties p)
 1329    {
 1330  269 Enumeration e = p.propertyNames();
 1331   
 1332  269 while (e.hasMoreElements())
 1333    {
 1334  14526 String key = (String) e.nextElement();
 1335  14526 String value = p.getProperty(key);
 1336   
 1337  14526 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  269 private void initializeFromPropertiesFile()
 1346    {
 1347  269 Properties p = new Properties();
 1348   
 1349  269 try
 1350    {
 1351   
 1352  269 InputStream propertiesIn = getClass()
 1353    .getResourceAsStream("DescriptorParser.properties");
 1354  269 InputStream bufferedIn = new BufferedInputStream(propertiesIn);
 1355   
 1356  269 p.load(bufferedIn);
 1357   
 1358  269 bufferedIn.close();
 1359    }
 1360    catch (IOException ex)
 1361    {
 1362  0 _errorHandler.error(LOG, ParseMessages.unableToInitialize(ex), null, ex);
 1363    }
 1364   
 1365  269 initializeFromProperties(p);
 1366    }
 1367   
 1368  14526 private void initializeFromProperty(String key, String value)
 1369    {
 1370  14526 if (key.startsWith("required."))
 1371    {
 1372  14526 initializeRequired(key, value);
 1373  14526 return;
 1374    }
 1375   
 1376    }
 1377   
 1378  14526 private void initializeRequired(String key, String value)
 1379    {
 1380  14526 boolean required = value.equals("true");
 1381   
 1382  14526 int lastdotx = key.lastIndexOf('.');
 1383   
 1384  14526 String elementName = key.substring(9, lastdotx);
 1385  14526 String attributeName = key.substring(lastdotx + 1);
 1386   
 1387  14526 ElementParseInfo epi = (ElementParseInfo) _elementParseInfo.get(elementName);
 1388   
 1389  14526 if (epi == null)
 1390    {
 1391  6456 epi = new ElementParseInfo();
 1392  6456 _elementParseInfo.put(elementName, epi);
 1393    }
 1394   
 1395  14526 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  283 public void initialize(Resource resource, ClassResolver resolver)
 1417    {
 1418  283 initializeParser(resource, STATE_START);
 1419   
 1420  283 _resolver = resolver;
 1421    }
 1422   
 1423    /** @since 1.1 */
 1424  278 public ModuleDescriptor getModuleDescriptor()
 1425    {
 1426  278 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    }