| 1 23 24 package org.objectweb.jorm.xml2mi.lib; 25 26 import org.apache.tools.ant.types.DTDLocation; 27 import org.objectweb.jorm.api.PException; 28 import org.objectweb.jorm.metainfo.api.Class; 29 import org.objectweb.jorm.metainfo.api.Package; 30 import org.objectweb.jorm.metainfo.api.Manager; 31 import org.objectweb.jorm.metainfo.api.MetaObject; 32 import org.objectweb.jorm.metainfo.api.CompositeName; 33 import org.objectweb.jorm.metainfo.api.ClassProject; 34 import org.objectweb.jorm.metainfo.api.NameDef; 35 import org.objectweb.jorm.metainfo.api.ScalarField; 36 import org.objectweb.jorm.metainfo.api.GenClassRef; 37 import org.objectweb.jorm.metainfo.api.ClassRef; 38 import org.objectweb.jorm.metainfo.api.Reference; 39 import org.objectweb.jorm.metainfo.api.NameRef; 40 import org.objectweb.jorm.metainfo.api.Mapping; 41 import org.objectweb.jorm.metainfo.api.PrimitiveElement; 42 import org.objectweb.jorm.metainfo.api.TypedElement; 43 import org.objectweb.jorm.metainfo.api.ClassMapping; 44 import org.objectweb.jorm.metainfo.api.ParentClassMapping; 45 import org.objectweb.jorm.metainfo.api.IdentifierMapping; 46 import org.objectweb.jorm.type.api.PType; 47 import org.objectweb.jorm.type.api.PTypeSpace; 48 import org.objectweb.jorm.util.api.Loggable; 49 import org.objectweb.jorm.util.io.api.PathExplorer; 50 import org.objectweb.jorm.util.io.lib.DirJavaExplorer; 51 import org.objectweb.jorm.xml2mi.api.MappingParser; 52 import org.objectweb.jorm.xml2mi.api.Parser; 53 import org.objectweb.util.monolog.api.BasicLevel; 54 import org.objectweb.util.monolog.api.Logger; 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 import org.w3c.dom.Node ; 58 import org.w3c.dom.NodeList ; 59 import org.xml.sax.SAXException ; 60 61 import java.io.InputStream ; 62 import java.util.Map ; 63 import java.util.HashMap ; 64 import java.util.Hashtable ; 65 import java.util.List ; 66 import java.util.ArrayList ; 67 import java.util.Collection ; 68 import java.util.Iterator ; 69 import java.util.Properties ; 70 import java.util.Set ; 71 import java.util.HashSet ; 72 73 79 public class BasicDomParser 80 extends ParserHelper 81 implements Parser, Loggable { 82 86 private Manager metaInfoManager; 87 88 91 private Map mappingParsers = new HashMap (); 92 93 96 private SAXParserHelper parser; 97 100 private PathExplorer pathExplorer; 101 102 103 106 private Exception parserException = null; 107 108 109 112 private boolean genDep = false; 113 114 private DTDResolver resolver = null; 115 116 private List parsedMO = null; 117 private List undefinedMO = null; 118 119 124 private Map idvalue2genclassref; 125 126 128 134 public void init(boolean dtdVerify, ArrayList dtds) { 135 Properties p = new Properties (); 136 for (Iterator iter = dtds.iterator(); iter.hasNext();) { 137 DTDLocation element = (DTDLocation) iter.next(); 138 p.setProperty(element.getPublicId(), element.getLocation()); 139 } 140 try { 141 parser = new SAXParserHelper(p, logger, null, dtdVerify); 142 } catch (SAXException e) { 143 logger.log(BasicLevel.ERROR, "Error during the parser initialization", e); 144 } 145 parsedMO = new ArrayList (); 146 undefinedMO = new ArrayList (); 147 motable = new Hashtable (); 148 mappingParsers = new HashMap (); 149 idvalue2genclassref = new HashMap (); 150 } 151 152 157 public void addMappingParser(String mapperName, 158 MappingParser mappingParser) throws PException { 159 if (mappingParser == null) { 160 throw new PException("<" + mapperName + 161 "> MappingParser has not been created."); 162 } 163 if (getLogger().isLoggable(BasicLevel.DEBUG)) { 164 getLogger().log(BasicLevel.DEBUG, 165 "Add a MappingParser (" + mapperName + 166 ") for the current Parser"); 167 } 168 if (!mappingParsers.containsKey(mapperName)) { 169 mappingParsers.put(mapperName, mappingParser); 170 } 171 } 172 173 178 public MappingParser getMappingParser(String mapperName) { 179 MappingParser mappingParser = (MappingParser) mappingParsers.get(mapperName); 180 return mappingParser; 181 } 182 183 192 public Collection parse(Iterator files) throws PException { 193 Collection res = new ArrayList (); 194 while (files.hasNext()) { 195 String filename = (String ) files.next(); 196 MetaObject mo = (MetaObject) motable.get(filename); 197 if (mo == null) { 198 mo = parse(filename); 199 if (mo != null) { 200 motable.put(filename, mo); 201 } 202 } 203 res.add(mo); 204 } 205 while (!undefinedMO.isEmpty()) { 206 MetaObject mo = (MetaObject) undefinedMO.remove(0); 207 String fqname = null; 208 if (mo instanceof Class ) { 209 fqname = ((Class ) mo).getFQName(); 210 } else if (mo instanceof CompositeName) { 211 fqname = ((CompositeName) mo).getFQName(); 212 } else { 213 throw new PException("Unknown meta object: " + mo); 214 } 215 fqname = fqname.replace('.', fileSeparator.charAt(0)) + ".pd"; 216 parse(fqname); 217 motable.put(fqname, mo); 218 } 219 220 Set handledImplicitMappings = new HashSet (); 222 for (Iterator itMO = res.iterator(); itMO.hasNext();) { 223 MetaObject metaObject = (MetaObject) itMO.next(); 224 if (metaObject instanceof Class ) { 225 Class clazz = (Class ) metaObject; 226 addImplicitMappings(clazz, handledImplicitMappings); 227 } 228 } 229 for (Iterator itMO = res.iterator(); itMO.hasNext();) { 231 MetaObject metaObject = (MetaObject) itMO.next(); 232 if (metaObject instanceof Class ) { 233 Class clazz = (Class ) metaObject; 234 addImplicitDependencies(clazz); 235 } 236 } 237 238 239 Set filenames = motable.keySet(); 240 if (! filenames.isEmpty()) { 241 for (Iterator iter = filenames.iterator(); iter.hasNext();) { 242 String filename = (String ) iter.next(); 243 logger.log(BasicLevel.DEBUG, 244 "BasicDomParser filename in motable " + filename); 245 } 247 } 248 249 logger.log(BasicLevel.DEBUG, 250 "BasicDomParser size of motable " + motable.size()); 251 252 logger.log(BasicLevel.DEBUG, 253 "BasicDomParser size of res " + res.size()); 254 255 return res; 256 } 257 258 268 public MetaObject parse(String file) throws PException { 269 logger.log(BasicLevel.INFO, "Parsing the file " + file + "..."); 270 boolean debug = logger.isLoggable(BasicLevel.DEBUG); 271 if (debug) 272 logger.log(BasicLevel.DEBUG, "try to get input stream from <" 273 + file + ">"); 274 InputStream is = pathExplorer.getInputStream(file); 275 if (is == null) { 276 throw new PException("The file '" + file + 277 "' has not been found in the following classpath \"" 278 + pathExplorer.getClassPath() + "\""); 279 } else if (debug) 280 logger.log(BasicLevel.DEBUG, "File " + file + " found"); 281 Document doc; 282 try { 283 doc = parser.parse(is); 284 } catch (Exception e) { 285 parserException = e; 286 throw new PException(e, "there is a problem (exception) during the parsing of <" 287 + file + "> from the SAX module (SAXNotRecognized)"); 288 } 289 if (debug) 290 logger.log(BasicLevel.DEBUG, "Parsing done."); 291 return (doc.getDocumentElement() != null 293 ? build(doc, file) 294 : null); 295 } 296 297 303 public void setMetaInfoManager(Manager mim) { 304 this.metaInfoManager = mim; 305 } 306 307 312 public void setPathExplorer(PathExplorer pathexpl) { 313 pathExplorer = pathexpl; 314 if (pathExplorer == null) { 315 pathExplorer = new DirJavaExplorer(); 316 } 317 logger.log(BasicLevel.DEBUG, "jorm classpath=" + pathExplorer.getClassPath()); 318 } 319 320 325 public void setGenDep(boolean gendep) { 326 genDep = gendep; 327 } 328 329 334 public boolean isGenDep() { 335 return genDep; 336 } 337 338 343 public Exception getParserException() { 344 return parserException; 345 } 346 347 351 358 private MetaObject build(Document doc, String name) throws PException { 359 if (logger.isLoggable(BasicLevel.DEBUG)) 360 logger.log(BasicLevel.DEBUG, 361 "build the meta information for <" + name + "> description file"); 362 Package schema = null; 363 Class clazz = null; 364 CompositeName aname = null; 365 NodeList nodes = doc.getDocumentElement().getChildNodes(); 366 for (int i = 0; i < nodes.getLength(); i++) { 367 Node node = nodes.item(i); 368 String nodeName = node.getNodeName(); 369 if (nodeName.equals("package")) { 370 if (logger.isLoggable(BasicLevel.DEBUG)) { 371 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 372 logger.log(BasicLevel.DEBUG, "package name =<" + 373 node.getFirstChild().getNodeValue() + ">"); 374 } 375 schema = metaInfoManager.createPackage(node.getFirstChild().getNodeValue()); 376 if (logger.isLoggable(BasicLevel.DEBUG)) 377 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 378 } else if (nodeName.equals("class")) { 379 String className = ((Element) node).getAttribute("name"); 380 int index = name.lastIndexOf(fileSeparator); 382 int endIdx = name.lastIndexOf("."); 383 if (endIdx <= index) 384 endIdx = name.length(); 385 String sub = name.substring(index + 1, endIdx); 386 if (!sub.equals(className)) 387 logger.log(BasicLevel.WARN, "Be careful, the name of the class" + 388 " is different from the name of the file : " + 389 sub + " and " + className + 390 "(" + className + " is used)"); 391 392 if (logger.isLoggable(BasicLevel.DEBUG)) 393 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 394 395 String isAbstractString = ((Element) node).getAttribute("abstract").toLowerCase(); 396 if (schema == null) { 397 schema = metaInfoManager.createPackage(""); 398 } 399 clazz = schema.createClass(className); 400 if (!parsedMO.contains(clazz)) { 401 parsedMO.add(clazz); 403 undefinedMO.remove(clazz); 404 boolean abstractClass = (isAbstractString != null && isAbstractString.equals("true")); 406 clazz.setAbstract(abstractClass); 407 if (logger.isLoggable(BasicLevel.DEBUG)) { 408 logger.log(BasicLevel.DEBUG, "isAbstractString:<" + isAbstractString +">"); 409 logger.log(BasicLevel.DEBUG, "Boolean.getBoolean(" + isAbstractString + "):" + Boolean.getBoolean(isAbstractString)); 411 logger.log(BasicLevel.DEBUG, "abstractClass:<" + abstractClass + ">"); 412 logger.log(BasicLevel.DEBUG, "class FQName:<" + clazz.getFQName() + "> isabstract:<" + clazz.isAbstract() +">"); 413 } 414 processClass(clazz, (Element) node); 415 } 416 if (logger.isLoggable(BasicLevel.DEBUG)) 417 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 418 } else if (nodeName.equals("mapping")) { 419 if (logger.isLoggable(BasicLevel.DEBUG)) 420 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 421 String projectName = ((Element) node).getAttribute("project-name"); 422 if (clazz == null) { 423 logger.log(BasicLevel.DEBUG, "the class definition is missing!"); 424 break; 425 } else { 426 if (logger.isLoggable(BasicLevel.DEBUG)) 427 logger.log(BasicLevel.DEBUG, "project-name =<" + projectName + ">"); 428 ClassProject classProject = clazz.createClassProject(projectName); 429 parseMapping((Element) node, classProject); 430 } 431 if (logger.isLoggable(BasicLevel.DEBUG)) 432 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 433 } else if (nodeName.equals("composite-name")) { 434 String CN_name = ((Element) node).getAttribute("name"); 435 int index = name.lastIndexOf(fileSeparator); 437 String sub = name.substring(index + 1, name.length() - 3); 438 439 if (sub.compareTo(CN_name) != 0) 440 logger.log(BasicLevel.WARN, "Be careful, the name of the composite name" + 441 " is different from the name of the file : " + 442 name + " and " + CN_name + 443 "(" + CN_name + " is used)"); 444 445 if (logger.isLoggable(BasicLevel.DEBUG)) 446 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 447 448 if (schema == null) { 449 schema = metaInfoManager.createPackage(""); 450 } 451 aname = schema.createCompositeName(CN_name); 452 if (!parsedMO.contains(aname)) { 453 parsedMO.add(aname); 454 undefinedMO.remove(aname); 455 processCompositeName(aname, (Element) node); 457 } 458 if (logger.isLoggable(BasicLevel.DEBUG)) 459 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 460 return aname; 461 } 462 } 463 return clazz; 464 } 465 466 private void processCompositeName(CompositeName compositeName, 467 Element compositeNameElem) { 468 469 NodeList children = compositeNameElem.getChildNodes(); 470 for (int i = 0; i < children.getLength(); i++) { 471 Node child = children.item(i); 472 String childName = child.getNodeName(); 473 474 if (childName.equals("scalar-field")) { 475 if (logger.isLoggable(BasicLevel.DEBUG)) 476 logger.log(BasicLevel.DEBUG, "begin =<" + childName + ">"); 477 478 processScalarField(compositeName, (Element) child); 479 480 if (logger.isLoggable(BasicLevel.DEBUG)) 481 logger.log(BasicLevel.DEBUG, "end =<" + childName + ">"); 482 } else if (childName.equals("extension")) { 483 if (logger.isLoggable(BasicLevel.DEBUG)) 486 logger.log(BasicLevel.DEBUG, "begin =<" + childName + ">"); 487 488 String CN_name = ((Element) child).getAttribute("Name"); 489 CompositeName parentCN = metaInfoManager.getCompositeName(CN_name); 490 if (parentCN == null) { 491 parentCN = metaInfoManager.createCompositeName(CN_name); 492 undefinedMO.add(parentCN); 493 } 494 compositeName.addInheritedCompositeName(parentCN); 495 if (logger.isLoggable(BasicLevel.DEBUG)) 496 logger.log(BasicLevel.DEBUG, "end =<" + childName + ">"); 497 } 498 } 499 } 500 501 502 512 private void processClass(Class clazz, Element classElem) throws PException { 513 514 NodeList children = classElem.getChildNodes(); 515 516 for (int i = 0; i < children.getLength(); i++) { 517 Node child = children.item(i); 518 String nodeName = child.getNodeName(); 519 if (nodeName.equals("field")) { 520 if (logger.isLoggable(BasicLevel.DEBUG)) 521 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 522 processField(clazz, (Element) child); 523 if (logger.isLoggable(BasicLevel.DEBUG)) 524 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 525 } else if (nodeName.equals("scalar-field")) { 526 if (logger.isLoggable(BasicLevel.DEBUG)) 527 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 528 processScalarField(clazz, (Element) child); 529 if (logger.isLoggable(BasicLevel.DEBUG)) 530 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 531 } else if (nodeName.equals("constant-value")) { 532 if (logger.isLoggable(BasicLevel.DEBUG)) 533 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 534 processConstantValue(clazz, (Element) child); 535 if (logger.isLoggable(BasicLevel.DEBUG)) 536 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 537 } else if (nodeName.equals("extension")) { 538 String fqcn = ((Element) child).getAttribute("name"); 539 if (logger.isLoggable(BasicLevel.DEBUG)) { 540 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 541 logger.log(BasicLevel.DEBUG, "name of the extension=<" + fqcn + ">"); 544 } 545 Class inheritedClass = metaInfoManager.getClass(fqcn); 547 if (inheritedClass == null) { 549 552 fqcn = fqcn.replace('.', fileSeparator.charAt(0)) + ".pd"; 553 inheritedClass = (Class ) parse(fqcn); 554 motable.put(fqcn, inheritedClass); 555 } 556 clazz.addSuperClass(inheritedClass); 557 if (logger.isLoggable(BasicLevel.DEBUG)) 558 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 559 } else if (nodeName.equals("name-def")) { 560 564 if (logger.isLoggable(BasicLevel.DEBUG)) 565 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 566 NameDef nameDef = clazz.createNameDef(); 567 processNameDef(nameDef, ((Element) child)); 568 if (logger.isLoggable(BasicLevel.DEBUG)) 569 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 570 571 } else if (nodeName.equals("name-def-filter")) { 572 if (logger.isLoggable(BasicLevel.DEBUG)) 573 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 574 String filter = ((Element) child).getAttribute("filter"); 575 NameDef nd = getIdNameDef(clazz, ((Element) child).getAttribute("link-end")); 576 clazz.setInheritanceFilter(nd, filter); 577 if (logger.isLoggable(BasicLevel.DEBUG)) 578 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 579 580 } else if (nodeName.equals("name-def-key")) { 581 if (logger.isLoggable(BasicLevel.DEBUG)) 582 logger.log(BasicLevel.DEBUG, "begin =<" + nodeName + ">"); 583 String key = ((Element) child).getAttribute("key"); 584 NameDef nd = getIdNameDef(clazz, ((Element) child).getAttribute("link-end")); 585 clazz.setInheritanceNamingKey(nd, key); 586 if (logger.isLoggable(BasicLevel.DEBUG)) 587 logger.log(BasicLevel.DEBUG, "end =<" + nodeName + ">"); 588 } 589 } 590 } 591 592 602 private void processScalarField(MetaObject mo, Element scalarFieldElem) { 603 606 String scalarFieldName = scalarFieldElem.getAttribute("name"); 607 NodeList children = scalarFieldElem.getChildNodes(); 608 ScalarField scalarField = null; 609 for (int j = 0; j < children.getLength(); j++) { 610 Node child = children.item(j); 611 String childName = child.getNodeName(); 612 if (logger.isLoggable(BasicLevel.DEBUG)) 613 logger.log(BasicLevel.DEBUG, "begin =<" + childName + ">"); 614 if (childName.equals("scalar-type")) { 615 String type = ((Element) child).getAttribute("type"); 616 if (mo instanceof Class ) { 617 scalarField = ((Class ) mo).createHiddenField( 618 scalarFieldName, getPType(type), 619 Integer.parseInt(((Element) child).getAttribute("size")), 620 Integer.parseInt(((Element) child).getAttribute("scale"))); 621 } else if (mo instanceof GenClassRef) { 622 scalarField = ((GenClassRef) mo).createHiddenField( 623 scalarFieldName, getPType(type), 624 Integer.parseInt(((Element) child).getAttribute("size")), 625 Integer.parseInt(((Element) child).getAttribute("scale"))); 626 } else if (mo instanceof CompositeName) { 627 scalarField = ((CompositeName) mo).createCompositeNameField( 628 scalarFieldName, getPType(type), 629 Integer.parseInt(((Element) child).getAttribute("size")), 630 Integer.parseInt(((Element) child).getAttribute("scale"))); 631 } 632 } else if (childName.equals("null-value")) { 633 String value = ((Element) child).getAttribute("value"); 634 scalarField.setNullValue(value); 635 } 636 if (logger.isLoggable(BasicLevel.DEBUG)) 637 logger.log(BasicLevel.DEBUG, "end =<" + childName + ">"); 638 } 639 scalarField.setIsAutoCalculated(Boolean.valueOf( 640 scalarFieldElem.getAttribute("auto-calculated")).booleanValue()); 641 String status = scalarFieldElem.getAttribute("status"); 642 if (status == null || status.equals("variable-persistent")) { 643 |