0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.schema2beansdev;
0043:
0044: import java.util.*;
0045: import java.io.*;
0046:
0047: import org.netbeans.modules.schema2beans.*;
0048: import org.netbeans.modules.schema2beansdev.metadd.*;
0049: import org.netbeans.modules.schema2beansdev.beangraph.*;
0050: import org.netbeans.modules.schema2beansdev.gen.*;
0051:
0052: /**
0053: * This class implements the Document Definition handler in order to build
0054: * the internal tree representation of the DD DTD.
0055: */
0056: public class BeanBuilder {
0057: private static final String UNIQUE_PREFIX = "My";
0058: protected GenBeans.Config config;
0059: protected CodeGeneratorFactory codeGenFactory;
0060: protected BeanElement rootElement;
0061: protected String genDir;
0062: protected String packagePath;
0063: protected String packageName = null;
0064: protected TreeParser parser;
0065: protected Map constNameMap = null; // LinkedHashMap<String, String>
0066:
0067: protected Map illegalClassNames = new HashMap();
0068:
0069: class BeanElement {
0070: GraphNode node;
0071: String beanName;
0072:
0073: int type;
0074: String classType;
0075: private boolean typeSetExternally = false;
0076:
0077: boolean isRoot;
0078: boolean isAbstract;
0079:
0080: private boolean canBeEmpty = false;
0081:
0082: private Map usedTypes;
0083: private int nonAttributePropertyCount = 0;
0084:
0085: BeanElement(GraphNode node) {
0086: this .node = node;
0087: }
0088:
0089: void initialize(boolean isRoot) {
0090: // Make up a bean name: xxx-yyy has to be XxxYyy
0091: this .beanName = Common.convertName(this .node.getName());
0092:
0093: //
0094: // As each node ends up as a property, we have to find out the
0095: // type of the property. The default value is Common.TYPE_BEAN.
0096: //
0097: this .type = Common.TYPE_BEAN;
0098: this .isRoot = isRoot;
0099:
0100: calculateType();
0101: }
0102:
0103: public GraphNode getGraphNode() {
0104: return this .node;
0105: }
0106:
0107: /**
0108: * Call this to change whether or not we will actually generate
0109: * this as a bean. Should we create it or not?
0110: * Users need to call this method instead of node.setCreated directly,
0111: * because some of this object's state depends on that value.
0112: */
0113: public void setNodeCreated(boolean value) {
0114: node.setCreated(value);
0115: calculateType();
0116: }
0117:
0118: protected void calculateType() {
0119: // If we arn't going to create it, then it must not be a bean.
0120: if (!node.isCreated())
0121: this .type = Common.TYPE_STRING;
0122: GraphNode[] nodes = node.getNodes();
0123: // If it is the root, then it must be a bean.
0124: if (nodes.length == 1 && !isRoot) {
0125: if (Common.DTD_STRING.equals(nodes[0].getName()))
0126: this .type = Common.TYPE_STRING;
0127: else {
0128: if (Common.DTD_EMPTY.equals(nodes[0].getName())) {
0129: this .type = Common.TYPE_BOOLEAN;
0130: this .canBeEmpty = true;
0131: }
0132: }
0133: }
0134: }
0135:
0136: void setCanBeEmpty(boolean value) {
0137: canBeEmpty = value;
0138: if (canBeEmpty) {
0139: //type = Common.TYPE_BOOLEAN;
0140: }
0141: }
0142:
0143: /**
0144: * setName allows you to change the name of the generated class.
0145: */
0146: public void setName(String name) {
0147: this .beanName = name;
0148: }
0149:
0150: public String getName() {
0151: return this .beanName;
0152: }
0153:
0154: public String getDTDName() {
0155: return this .node.getName();
0156: }
0157:
0158: public void setDTDName(String dtdName) {
0159: node.setName(dtdName);
0160: }
0161:
0162: public String getNamespace() {
0163: return node.getNamespace();
0164: }
0165:
0166: public boolean isBean() {
0167: return Common.isBean(this .type);
0168: }
0169:
0170: public boolean isBoolean() {
0171: return Common.isBoolean(this .type);
0172: }
0173:
0174: public boolean isRoot() {
0175: return this .isRoot;
0176: }
0177:
0178: public String typeToString() {
0179: switch (this .type) {
0180: case Common.TYPE_STRING:
0181: return Common.CLASS_STRING;
0182: case Common.TYPE_BOOLEAN:
0183: return Common.CLASS_BOOLEAN;
0184: default:
0185: return this .beanName;
0186: }
0187: }
0188:
0189: public String getClassType() {
0190: if (classType == null)
0191: return typeToString();
0192: return classType;
0193: }
0194:
0195: public String getFullClassType() {
0196: String result = getClassType();
0197: if (packageName == null)
0198: return result;
0199: if (isBean() && node.isCreated())
0200: return packageName + "." + result;
0201: return result;
0202: }
0203:
0204: public void setClassType(String ct) {
0205: classType = ct;
0206: }
0207:
0208: public boolean isTypeSetExternally() {
0209: return typeSetExternally;
0210: }
0211:
0212: public void setTypeSetExternally(boolean value) {
0213: typeSetExternally = value;
0214: }
0215:
0216: public String toString() {
0217: return this .beanName
0218: + ((this .type == Common.TYPE_STRING) ? " \t(String)"
0219: : "\t(Bean)"); // NOI18N
0220: }
0221:
0222: public void setUsedTypes(Map usedTypes) {
0223: this .usedTypes = usedTypes;
0224: }
0225:
0226: public boolean isUsedType(String type) {
0227: return usedTypes.containsKey(type);
0228: }
0229:
0230: public boolean getCanBeEmpty() {
0231: return canBeEmpty;
0232: }
0233:
0234: public String getOutputFileName() {
0235: if (isBean())
0236: return getClassType();
0237: else
0238: return getName();
0239: }
0240:
0241: public BeanElement getExtension() {
0242: if (node.getExtension() == null
0243: || !node.getExtension().isCreated())
0244: return null;
0245: return (BeanElement) node.getExtension().getObject();
0246: }
0247:
0248: public void setNonAttributePropertyCount(int value) {
0249: nonAttributePropertyCount = value;
0250: }
0251:
0252: public int getNonAttributePropertyCount() {
0253: return nonAttributePropertyCount;
0254: }
0255: }
0256:
0257: class Finder {
0258: private String findExpr, byExpr;
0259: private boolean listFindExpr;
0260:
0261: public Finder(String findExpr, String byExpr,
0262: boolean listFindExpr) {
0263: this .findExpr = findExpr;
0264: this .byExpr = byExpr;
0265: this .listFindExpr = listFindExpr;
0266: }
0267:
0268: public String getFindExpr() {
0269: return findExpr;
0270: }
0271:
0272: public String getByExpr() {
0273: return byExpr;
0274: }
0275:
0276: public boolean isListFindExpr() {
0277: return listFindExpr;
0278: }
0279:
0280: public String toString() {
0281: if (listFindExpr)
0282: return "Finder list " + findExpr + " by " + byExpr;
0283: else
0284: return "Finder " + findExpr + " by " + byExpr;
0285: }
0286: }
0287:
0288: BeanBuilder(TreeParser parser, GenBeans.Config config,
0289: CodeGeneratorFactory cgf) {
0290: this .parser = parser;
0291: this .config = config;
0292: this .codeGenFactory = cgf;
0293:
0294: // Since java.lang is implicitly imported, we have to make sure to
0295: // not generate a class with that collides with java.lang.
0296: illegalClassNames.put("Object", null);
0297: illegalClassNames.put("Thread", null);
0298: illegalClassNames.put("Compiler", null);
0299: illegalClassNames.put("Class", null);
0300: illegalClassNames.put("ClassLoader", null);
0301: //illegalClassNames.put("Process", null);
0302: illegalClassNames.put("Package", null);
0303: illegalClassNames.put("String", null);
0304: illegalClassNames.put("Boolean", null);
0305: illegalClassNames.put("Integer", null);
0306: illegalClassNames.put("Long", null);
0307: illegalClassNames.put("Short", null);
0308: illegalClassNames.put("Double", null);
0309: illegalClassNames.put("Float", null);
0310: illegalClassNames.put("Byte", null);
0311: illegalClassNames.put("Character", null);
0312: illegalClassNames.put("int", null);
0313: illegalClassNames.put("char", null);
0314: illegalClassNames.put("byte", null);
0315: illegalClassNames.put("short", null);
0316: illegalClassNames.put("long", null);
0317: illegalClassNames.put("double", null);
0318: illegalClassNames.put("float", null);
0319: illegalClassNames.put("boolean", null);
0320: illegalClassNames.put("void", null);
0321: }
0322:
0323: /**
0324: * Parse the attributes of the bean
0325: *
0326: * usedNames helps us to not generate multiple properties with the
0327: * same name. The key is the name of the property and the entry
0328: * is a BeanElement (name = BeanElement.getName()). Currently,
0329: * the storage of the BeanElement is not used, and null should be
0330: * valid for properties that are defined without a BeanElement.
0331: */
0332: private void buildProperties(GraphLink l, CodeGeneratorClass bc,
0333: int nestedLevel, int groupInstance, boolean ored,
0334: MetaElement e, MetaDD mdd, Map usedNames) {
0335: while (l != null) {
0336: if (config.isTraceGen())
0337: config.messageOut.println("buildProperties: l=" + l
0338: + " l.name=" + l.name + " l.element="
0339: + l.element + " l.getSibling()="
0340: + l.getSibling() + " groupInstance="
0341: + groupInstance);
0342: if (l.element != null) {
0343: BeanElement be = (BeanElement) l.element.getObject();
0344:
0345: if (be == null) {
0346: // This can happen if there are no properties associated
0347: // with this bean (like if the root element has no
0348: // children elements).
0349: config.messageOut.println("Warning: be was null");
0350: continue;
0351: }
0352:
0353: //
0354: // The group prop was set on the parent of the children.
0355: // Set it on each property directly for building the class.
0356: //
0357: if (l.getParent() != null)
0358: ored = ored || l.getParent().isSequenceOr();
0359: //System.out.println("ored="+ored);
0360:
0361: String name;
0362: String dtdName;
0363: String namespace;
0364: String constName;
0365: if (l.name != null) {
0366: name = Common.convertName(l.name);
0367: dtdName = l.getSchemaName();
0368: namespace = l.getNamespace();
0369: } else {
0370: name = be.getName();
0371: dtdName = be.getDTDName();
0372: namespace = be.getNamespace();
0373: }
0374: MetaElement propertyME = getMetaElement(mdd, dtdName);
0375: if (propertyME != null
0376: && propertyME.getBeanName() != null) {
0377: name = propertyME.getBeanName();
0378: if (config.isTraceGen())
0379: config.messageOut
0380: .println("buildProperties: property in "
0381: + e.getBeanName()
0382: + " has been renamed to "
0383: + name);
0384: }
0385: constName = Common.constName(dtdName);
0386: if ("#PCDATA".equals(dtdName)) {
0387: // text node
0388: //config.messageOut.println("Hit #PCDATA");
0389: name = "pcdata";
0390: constName = "PCDATA";
0391: }
0392: if (usedNames.containsKey(name)) {
0393: int uniqNum = 2;
0394: String baseName = name;
0395: while (usedNames.containsKey(name = baseName
0396: + uniqNum))
0397: uniqNum++;
0398: constName = constName + uniqNum;
0399: if (l.name != null) {
0400: //l.name = l.name + uniqNum;
0401: } else {
0402: be.setName(name);
0403: MetaElement origE = getMetaElement(mdd, dtdName);
0404: if (origE != null) {
0405: MetaElement newE = new MetaElement(origE);
0406: mdd.addMetaElement(newE);
0407: }
0408: }
0409: config.messageOut.println(Common.getMessage(
0410: "RenamedProperty_msg", baseName, name, e
0411: .getBeanName()));
0412: }
0413: usedNames.put(name, be);
0414: if (config.isTraceGen())
0415: config.messageOut.println("buildProperties: name="
0416: + name + " constName=" + constName
0417: + " dtdName=" + dtdName
0418: + " graphlink.name=" + l.name
0419: + " be.getClassType=" + be.getClassType());
0420: AttrProp[] attrs = be.node.getAttributes();
0421: List extraData = new ArrayList(l.extraData);
0422: if (!be.node.getExtraData().isEmpty()) {
0423: extraData.addAll(be.node.getExtraData());
0424: //System.out.println("**** be.node="+be.node+" extraData="+extraData);
0425: }
0426: //System.out.println("extraData="+extraData);
0427: if (propertyME != null
0428: && propertyME.sizeKnownValue() > 0) {
0429: for (int valNum = 0, size = propertyME
0430: .sizeKnownValue(); valNum < size; ++valNum) {
0431: String knownValue = propertyME
0432: .getKnownValue(valNum);
0433: extraData.add(new KnownValueEnumeration(
0434: knownValue));
0435: }
0436: }
0437: constNameMap.put(constName, dtdName);
0438: int type = be.type;
0439: String classType = be.getClassType();
0440: //
0441: // Look to see if we need to make a primitive type into an
0442: // Object type, but don't do it, if the user has set the
0443: // type (like from mdd file).
0444: //
0445: if (!be.isTypeSetExternally()
0446: && (ored || l.isNillable())) {
0447: if (JavaUtil.isPrimitiveType(classType)) {
0448: classType = JavaUtil.toObjectType(classType);
0449: type = Common.wrapperToType(classType);
0450: if (type == Common.NONE)
0451: type = Common.TYPE_STRING;
0452: if (config.isTraceGen())
0453: config.messageOut
0454: .println("Promoting primitive type to object type for "
0455: + name
0456: + " classType="
0457: + classType
0458: + " type="
0459: + type);
0460: }
0461: }
0462: AbstractCodeGeneratorClass.Property prop = bc
0463: .addProperty(name, dtdName, namespace,
0464: l.element, l, classType, nestedLevel, l
0465: .getElementInstance(),
0466: groupInstance, type, ored, attrs,
0467: constName, l.getDefaultValue(), true,
0468: extraData, l.isUnion());
0469: prop.setCanBeEmpty(be.getCanBeEmpty());
0470: prop.setNillable(l.isNillable());
0471: prop.setBeanElement(be);
0472: l.setObject(prop);
0473: if (e != null) {
0474: // Need to check that name is not already in there.
0475: MetaProperty[] metaProperties = e.getMetaProperty();
0476: boolean found = false;
0477: for (int i = 0; i < metaProperties.length; ++i) {
0478: if (name
0479: .equals(metaProperties[i].getBeanName())) {
0480: found = true;
0481: break;
0482: }
0483: }
0484: if (!found) {
0485: MetaProperty mp = new MetaProperty();
0486: mp.setBeanName(name);
0487: e.addMetaProperty(mp);
0488: }
0489: }
0490:
0491: //
0492: // Take care of the case where a subnode is a leaf node
0493: // and it has attributes too. In which case, that subnode's
0494: // attributes, become our own.
0495: //
0496: if (!Common.isBean(be.type)
0497: && config.isAttributesAsProperties()) {
0498: addAttrProps(bc, attrs, name, usedNames, l
0499: .getElementInstance(), false);
0500: }
0501: }
0502:
0503: //
0504: // As we go one level deeper, the current link has
0505: // the instance property of the group of children.
0506: //
0507: int childGroupInstance = Common.widestInstance(
0508: groupInstance, l.getGroupInstance());
0509: buildProperties(l.getFirstChild(), bc, nestedLevel + 1,
0510: childGroupInstance, ored, e, mdd, usedNames);
0511:
0512: l = l.getSibling();
0513: }
0514: }
0515:
0516: protected void addAttrProps(CodeGeneratorClass bc,
0517: AttrProp[] attrs, String propertyName, Map usedNames,
0518: int groupInstance, boolean directChild) {
0519: if (attrs != null) {
0520: for (int i = 0; i < attrs.length; ++i) {
0521: addAttrProp(bc, attrs[i], propertyName, usedNames,
0522: groupInstance, directChild);
0523: }
0524: }
0525: }
0526:
0527: protected void addAttrProp(CodeGeneratorClass bc, AttrProp attr,
0528: String propertyName, Map usedNames, int groupInstance,
0529: boolean directChild) {
0530: String name;
0531: if (directChild)
0532: name = Common.convertName(attr.getName());
0533: else
0534: name = Common.convertName(propertyName + "_"
0535: + attr.getName());
0536: if (usedNames.containsKey(name)) {
0537: int uniqNum = 2;
0538: String baseName = name;
0539: while (usedNames.containsKey(name = baseName + uniqNum))
0540: uniqNum++;
0541: attr.setName(name);
0542: config.messageOut.println(Common
0543: .getMessage("RenamedProperty_msg", baseName, name,
0544: propertyName));
0545: }
0546: usedNames.put(name, attr);
0547:
0548: String javaType = attr.getJavaType();
0549: int type;
0550: if (javaType == null) {
0551: type = Common.TYPE_STRING;
0552: javaType = "java.lang.String"; // NOI18N
0553: } else {
0554: type = Common.wrapperToType(javaType);
0555: if (type == Common.NONE)
0556: type = Common.TYPE_STRING;
0557: }
0558: //System.out.println("addAttrProp: attr="+attr+" attr.javaType="+javaType);
0559: List extraData = attr.getExtraData();
0560: String namespace = attr.getNamespace();
0561: bc.addProperty(name, attr.getDtdName(), namespace, null, null,
0562: javaType, 0, attr.getInstance(), groupInstance, type,
0563: false, null, Common.constName(name),
0564: attr.getDefaultValue(), directChild, extraData, false)
0565: .setAttrProp(attr);
0566: }
0567:
0568: protected void addCommentsProcessing(CodeGeneratorClass bc) {
0569: bc.addProperty("Comments", "comment", null, null, null,
0570: "java.lang.String", 0, Common.TYPE_0_N, 0,
0571: Common.TYPE_COMMENT, false, null, "COMMENTS", null,
0572: true, Collections.EMPTY_LIST, false);
0573: }
0574:
0575: protected static class KnownValueEnumeration implements
0576: DataEnumRestriction {
0577: private String knownValue;
0578:
0579: protected KnownValueEnumeration(String value) {
0580: knownValue = value;
0581: }
0582:
0583: public void genRestriction(Writer out, String type)
0584: throws IOException {
0585: out.write(JavaUtil.instanceFrom(type, knownValue));
0586: }
0587: }
0588:
0589: // Called by GenBeans
0590: void process() throws IOException {
0591: Map generators = new LinkedHashMap(); // Map<BeanElement, CodeGeneratorClass>
0592: prepareBeans(generators);
0593: doGeneration(generators);
0594: }
0595:
0596: void prepareBeans(Map generators) throws IOException {
0597: GraphNode root = parser.getRoot();
0598: GraphNode[] list = parser.getNodes();
0599: String rootDir;
0600: BeanElement be;
0601: MetaDD mdd = config.getMetaDD();
0602:
0603: if (root == null)
0604: throw new IllegalStateException(Common
0605: .getMessage("DTDObjectGraphIsNull_msg"));
0606:
0607: constNameMap = new LinkedHashMap();
0608:
0609: for (int i = 0; i < list.length; i++) {
0610: GraphNode node = list[i];
0611: /*
0612: config.messageOut.println("list["+i+"]="+node+" alias="+node.getAlias());
0613: GraphLink link = node.getGraphLink();
0614: while (link != null) {
0615: config.messageOut.println("link="+link+" link.name="+link.name+" link.element="+link.element);
0616: link = link.sibling;
0617: }
0618: */
0619: be = new BeanElement(node);
0620: be.initialize(node == root);
0621: node.setObject(be);
0622: }
0623:
0624: if (config.getRootDir() == null)
0625: rootDir = "."; // NOI18N
0626: else
0627: rootDir = config.getRootDir().toString();
0628: packagePath = config.getPackagePath();
0629:
0630: rootElement = (BeanElement) root.getObject();
0631:
0632: // No package specified, use the docroot as the default value
0633: if (packagePath == null) { // NOI18N
0634: packagePath = rootElement.getName().toLowerCase();
0635: }
0636:
0637: if (rootDir.equals("")) // NOI18N
0638: genDir = packagePath;
0639: else {
0640: if (!rootDir.equals("/")) { // NOI18N
0641: if (packagePath == null || packagePath.equals(""))
0642: genDir = rootDir; // NOI18N
0643: else
0644: genDir = rootDir + "/" + packagePath; // NOI18N
0645: } else
0646: genDir = "/" + packagePath; // NOI18N
0647: }
0648: packageName = null;
0649: if (packagePath != null)
0650: packageName = packagePath.replace('/', '.');
0651:
0652: if (config.isDoGeneration()
0653: && config.getOutputStreamProvider() instanceof GenBeans.DefaultOutputStreamProvider) {
0654: File dir = new File(genDir);
0655:
0656: if (dir.exists() && !dir.isDirectory()) {
0657: throw new Schema2BeansRuntimeException(Common
0658: .getMessage("CantCreateDirIsFile_msg", dir));
0659: } else {
0660: if (!dir.exists()) {
0661: if (dir.mkdirs()) {
0662: if (!config.isQuiet())
0663: config.messageOut.println(Common
0664: .getMessage("MSG_CreatedDirectory",
0665: dir)); // NOI18N
0666: }
0667: }
0668: }
0669: }
0670:
0671: //
0672: // Bring in any previously generated types.
0673: //
0674: setSchemaType(list);
0675:
0676: String commonInterface = config.getGenerateCommonInterface();
0677: if (commonInterface != null) {
0678: illegalClassNames.put(commonInterface,
0679: "Common Bean Interface");
0680: if (packageName != null && !"".equals(packageName))
0681: commonInterface = packageName + "." + commonInterface;
0682: }
0683: boolean doGeneration = !config.isCheckUpToDate();
0684: //
0685: // Build the internal representation of the bean classes
0686: //
0687: for (int i = 0; i < list.length; i++) {
0688: MetaElement e = null;
0689: StringBuffer str;
0690: GraphNode graphNode = list[i];
0691:
0692: String suggestedJavaType = graphNode.getJavaType();
0693: //config.messageOut.println("graphNode="+graphNode+" suggestedJavaType="+suggestedJavaType);
0694:
0695: be = (BeanElement) graphNode.getObject();
0696: if (be == null)
0697: continue;
0698:
0699: // The user has provided us with some data in their own .mdd
0700: e = getMetaElement(mdd, be.getDTDName(), graphNode
0701: .getNamespace());
0702: if (e == null) {
0703: e = new MetaElement();
0704: e.setBeanName(be.getName());
0705: e.setDtdName(be.getDTDName());
0706: e.setNamespace(graphNode.getNamespace());
0707:
0708: mdd.addMetaElement(e);
0709: }
0710: if (e.isCanBeEmpty()) {
0711: be.setCanBeEmpty(true);
0712: }
0713:
0714: //config.messageOut.println("process: e="+e+" be.getName="+ ((be != null) ? be.getName() : null));
0715: // Figure out what java type to use.
0716: // Make sure that if the user specifies a bean-name that
0717: // we use it for the name of this bean.
0718: if (e.getBeanName() != null && !e.getBeanName().equals("")) {
0719: be.setClassType(e.getBeanName());
0720: be.setName(e.getBeanName());
0721: }
0722: if (e.getWrapperClass() != null) {
0723: suggestedJavaType = e.getWrapperClass();
0724: // This is a user defined wrapper class, so we are not
0725: // creating this guy.
0726: //be.setNodeCreated(false); Do not call as the user could have set the wrapper-class for a bean.
0727: graphNode.setCreated(false);
0728: be.setTypeSetExternally(true);
0729: } else if (suggestedJavaType != null) {
0730: e.setWrapperClass(suggestedJavaType);
0731: } else if (be != rootElement && Common.isScalar(be.type)) {
0732: e.setWrapperClass(Common.wrapperClass(be.type));
0733: suggestedJavaType = e.getWrapperClass();
0734: } else if (be != rootElement && !Common.isBean(be.type)) {
0735: e.setWrapperClass(be.typeToString());
0736: suggestedJavaType = e.getWrapperClass();
0737: }
0738: //config.messageOut.println("e.getBeanName="+e.getBeanName());
0739: if (suggestedJavaType != null) {
0740: int proposedType = Common
0741: .wrapperToType(suggestedJavaType);
0742: if (proposedType != Common.NONE)
0743: be.type = proposedType;
0744: be.setClassType(suggestedJavaType);
0745: //config.messageOut.println("Setting class type to "+suggestedJavaType);
0746: }
0747: if (graphNode.getExtendedProperty("can-be-empty") != null) {
0748: be.setCanBeEmpty(true);
0749: }
0750: if (be.isBean()) {
0751: //System.out.println("be.getClassType()="+be.getClassType()+" illegalClassNames[]="+illegalClassNames.get(be.getClassType()));
0752: while (illegalClassNames.containsKey(be.getClassType())) {
0753: String prefix;
0754: if (graphNode.getNamespace() != null) {
0755: prefix = Common.convertName(graphNode
0756: .getNamespace());
0757: } else {
0758: prefix = UNIQUE_PREFIX;
0759: }
0760: be.setClassType(prefix + be.getClassType());
0761: be.setName(prefix + be.getName());
0762: e.setBeanName(prefix + e.getBeanName());
0763: if (config.isTraceGen())
0764: config.messageOut
0765: .println("Made class name change to "
0766: + be.getClassType());
0767: }
0768: // Make sure no one else wants to use this name.
0769: illegalClassNames.put(be.getClassType(), be);
0770:
0771: if (graphNode.getExtension() != null) {
0772: GraphNode extensionNode = graphNode.getExtension();
0773: /*
0774: config.messageOut.println("Node with extension: "+be);
0775: config.messageOut.println("extensionNode="+extensionNode);
0776: config.messageOut.println("extensionNode.created="+extensionNode.isCreated());
0777: config.messageOut.println("extensionNode.object="+extensionNode.getObject());
0778: */
0779: if (extensionNode.isCreated()) {
0780: BeanElement extensionBE = (BeanElement) extensionNode
0781: .getObject();
0782: String extendsName = extensionBE
0783: .getFullClassType();
0784: e.setExtends(extendsName);
0785: addToBeanInterfaceExtends(e, extendsName
0786: + "Interface");
0787: }
0788: }
0789:
0790: if (config.isExtendBaseBean()) {
0791: if (e.getExtends() == null)
0792: e
0793: .setExtends("org.netbeans.modules.schema2beans.BaseBean");
0794: }
0795: if (graphNode.getExtendedProperty("extends") != null
0796: && e.getExtends() == null) {
0797: e.setExtends((String) graphNode
0798: .getExtendedProperty("extends"));
0799: }
0800: if (graphNode.getExtendedProperty("implements") != null
0801: && e.getImplements() == null) {
0802: e.setImplements((String) graphNode
0803: .getExtendedProperty("implements"));
0804: }
0805: if (config.isGenerateInterfaces()) {
0806: String interfaceName;
0807: if (graphNode.getJavaType() == null) {
0808: interfaceName = be.getName() + "Interface";
0809: if (packageName != null
0810: && !"".equals(packageName))
0811: interfaceName = packageName + "."
0812: + interfaceName;
0813: } else {
0814: interfaceName = graphNode.getJavaType()
0815: + "Interface";
0816: }
0817: addToImplements(e, interfaceName);
0818: }
0819: if (commonInterface != null) {
0820: if (graphNode.getJavaType() == null) {
0821: addToImplements(e, commonInterface);
0822: }
0823: }
0824: if (config.isExtendBaseBean()) {
0825: addToImplements(e,
0826: "org.netbeans.modules.schema2beans.Bean");
0827: }
0828: if (config.isCheckUpToDate()) {
0829: String outputFileName = be.getOutputFileName();
0830: if (config.getOutputStreamProvider().isOlderThan(
0831: genDir, outputFileName, "java",
0832: config.getNewestSourceTime())) {
0833: doGeneration = true;
0834: }
0835: }
0836: }
0837: }
0838:
0839: if (!doGeneration) {
0840: config.messageOut.println(Common
0841: .getMessage("MSG_SkippingGenerationDueToTime"));
0842: return;
0843: }
0844:
0845: //
0846: // Build up all of the properties
0847: //
0848: Map usedTypes = new HashMap();
0849: for (int i = 0; i < list.length; i++) {
0850: MetaElement e = null;
0851: be = (BeanElement) list[i].getObject();
0852: //config.messageOut.println("i="+i+" be="+be);
0853: if (be == null)
0854: continue;
0855:
0856: GraphNode graphNode = be.getGraphNode();
0857: if (be.isBean() || be == rootElement) {
0858: if (config.isTraceGen())
0859: config.messageOut
0860: .println("Building properties for " + be);
0861: be.isAbstract = graphNode.isAbstract();
0862:
0863: e = getMetaElement(mdd, be.getDTDName(), graphNode
0864: .getNamespace());
0865: Map usedNames = new HashMap();
0866:
0867: CodeGeneratorClass bc = codeGenFactory
0868: .newCodeGeneratorClass(be, config);
0869: bc.setPackageName(packageName);
0870: bc.setIndent(config.getIndent());
0871: bc.setRootBeanElement(rootElement);
0872: bc.setDefaultNamespace(parser.getDefaultNamespace());
0873: bc.setInvalidPropertyNames(usedNames);
0874: if (config.isProcessComments()) {
0875: addCommentsProcessing(bc);
0876: }
0877: if (parser instanceof HasPrefixGuesser)
0878: bc.setPrefixGuesser(((HasPrefixGuesser) parser)
0879: .getPrefixGuesser());
0880: if (config.isAttributesAsProperties())
0881: addAttrProps(bc, be.node.getAttributes(), be
0882: .getName(), usedNames, Common.TYPE_1, true);
0883: if (be.isBean()) {
0884: GraphLink l = graphNode.getGraphLink();
0885: if (l != null) {
0886: int groupInstance = l.getGroupInstance();
0887: buildProperties(l, bc, 0, groupInstance, false,
0888: e, mdd, usedNames);
0889: int nonAttributePropertyCount = 0;
0890: List props = bc.getPropertyList();
0891: for (Iterator it = props.iterator(); it
0892: .hasNext();) {
0893: AbstractCodeGeneratorClass.Property prop = (AbstractCodeGeneratorClass.Property) it
0894: .next();
0895: if (prop.isAttribute())
0896: continue;
0897: ++nonAttributePropertyCount;
0898: }
0899: //config.messageOut.println("HIT be "+be+" count "+nonAttributePropertyCount);
0900: be.setNonAttributePropertyCount(be
0901: .getNonAttributePropertyCount()
0902: + nonAttributePropertyCount);
0903: }
0904: }
0905:
0906: //
0907: // Only if we created it do we want to keep the code generator
0908: // and use it in a following step.
0909: //
0910: if (graphNode.isCreated())
0911: generators.put(be, bc);
0912: }
0913: usedTypes.put(be.getClassType(), be);
0914: }
0915: /*
0916: for (Iterator it = usedTypes.keySet().iterator(); it.hasNext(); ) {
0917: String type = (String) it.next();
0918: System.out.println("Used type: "+type);
0919: }
0920: */
0921: rootElement.setUsedTypes(usedTypes);
0922:
0923: processFinders(rootElement.node);
0924:
0925: if (config.getWriteBeanGraphFile() != null) {
0926: // The bean graph itself is not part of the bean generation,
0927: // which is why it's in prepareBeans().
0928: File beanGraphFile = config.getWriteBeanGraphFile();
0929: File parentDir = beanGraphFile.getParentFile();
0930: if (parentDir != null && !parentDir.exists()) {
0931: if (parentDir.mkdirs()) {
0932: if (!config.isQuiet())
0933: config.messageOut.println(Common.getMessage(
0934: "MSG_CreatedDirectory", parentDir)); // NOI18N
0935: }
0936: }
0937: OutputStream out = new WriteIfDifferentOutputStream(
0938: beanGraphFile);
0939: BeanGraph bg = generateBeanGraph(list);
0940: bg.write(out);
0941: close(out);
0942: }
0943: }
0944:
0945: void doGeneration(Map generators) throws IOException {
0946: BeanElement be;
0947: MetaDD mdd = config.getMetaDD();
0948: if (config.isDoGeneration()) {
0949: List generatedMethods = new LinkedList(); // List<Collection<JavaWriter.Method>>
0950: // And generate the files
0951: for (Iterator it = generators.keySet().iterator(); it
0952: .hasNext();) {
0953: be = (BeanElement) it.next();
0954: CodeGeneratorClass bc = (CodeGeneratorClass) generators
0955: .get(be);
0956: String outputFileName = be.getOutputFileName();
0957:
0958: MetaElement metaElement = getMetaElement(mdd, be
0959: .getDTDName(), be.node.getNamespace());
0960: if (metaElement.isSkipGeneration()) {
0961: config.messageOut
0962: .println("Skipping generation of class "
0963: + be.beanName
0964: + " (as specified in the mdd file)"); // NOI18N
0965: continue;
0966: }
0967:
0968: //
0969: // The bean class has now everything it needs to
0970: // generate its content (name, package, attributes, ...)
0971: //
0972: try {
0973: OutputStream out;
0974: out = config.getOutputStreamProvider().getStream(
0975: genDir, outputFileName, "java"); // NOI18N
0976: bc.generate(out, mdd);
0977: close(out);
0978: out = null; // Try to encourage the GC
0979: Collection beansMethods = bc.getGeneratedMethods();
0980: generatedMethods.add(beansMethods);
0981:
0982: if (config.isGenerateDelegator()) {
0983: GraphNode graphNode = be.getGraphNode();
0984: MetaElement e = getMetaElement(mdd, be
0985: .getDTDName(), graphNode.getNamespace());
0986: String delegatorClassName;
0987: if (e != null && e.getDelegatorName() != null)
0988: delegatorClassName = e.getDelegatorName();
0989: else {
0990: delegatorClassName = outputFileName
0991: + "Delegator";
0992: if (e != null)
0993: e.setDelegatorName(delegatorClassName);
0994: }
0995: String delegatorPackageName = packageName;
0996: String dir = genDir;
0997: if (config.getDelegateDir() != null) {
0998: dir = config.getDelegateDir()
0999: .getAbsolutePath();
1000: if (config.getDelegatePackage() == null) {
1001: if (packagePath != null
1002: && !packagePath.equals(""))
1003: dir = dir + "/" + packagePath; // NOI18N
1004: } else {
1005: delegatorPackageName = config
1006: .getDelegatePackage();
1007: dir = dir
1008: + "/"
1009: + delegatorPackageName.replace(
1010: '.', '/'); // NOI18N
1011: }
1012: }
1013: out = config.getOutputStreamProvider()
1014: .getStream(dir, delegatorClassName,
1015: "java"); // NOI18N
1016: bc.generateDelegator(out, mdd,
1017: delegatorClassName,
1018: delegatorPackageName);
1019: close(out);
1020: out = null; // Try to encourage the GC
1021: }
1022: if (config.isGenerateInterfaces()) {
1023: List beanInfoMethods = new ArrayList(
1024: beansMethods.size()); // List<JavaWriter.Method>
1025: for (Iterator mit = beansMethods.iterator(); mit
1026: .hasNext();) {
1027: JavaWriter.Method method = (JavaWriter.Method) mit
1028: .next();
1029: if (method.isStatic()
1030: || method.isConstructor()
1031: || !method.isPublic())
1032: continue;
1033: if (!method.isBeanInfo())
1034: continue;
1035: //System.out.println("\tFound bean info: "+method.getNameParameters());
1036: beanInfoMethods.add(method);
1037: }
1038: String interfaceName = outputFileName
1039: + "Interface"; // NOI18N
1040: GraphNode graphNode = be.getGraphNode();
1041: MetaElement me = getMetaElement(mdd, be
1042: .getDTDName(), graphNode.getNamespace());
1043: generateInterface(
1044: genDir,
1045: packageName,
1046: interfaceName,
1047: beanInfoMethods,
1048: "This interface has all of the bean info accessor methods.",
1049: me.getBeanInterfaceExtends());
1050: }
1051: } catch (IOException ioe) {
1052: config.messageOut
1053: .println("Failed to generate bean class: "
1054: + outputFileName); // NOI18N
1055: TraceLogger.error(ioe);
1056: throw ioe;
1057: } catch (IllegalStateException ise) {
1058: config.messageOut
1059: .println("Failed to generate bean class "
1060: + outputFileName); // NOI18N
1061: TraceLogger.error(ise);
1062: throw ise;
1063: }
1064: }
1065:
1066: if (config.getGenerateCommonInterface() != null
1067: && generatedMethods.size() > 0) {
1068: Map commonGeneratedMethods = new HashMap(); // Map<String, JavaWriter.Method>
1069: Iterator it = generatedMethods.iterator();
1070: Collection methods = (Collection) it.next();
1071: // Put all of the methods into our map
1072: for (Iterator mit = methods.iterator(); mit.hasNext();) {
1073: JavaWriter.Method method = (JavaWriter.Method) mit
1074: .next();
1075: if (method.isStatic() || method.isConstructor()
1076: || !method.isPublic()
1077: || method.isUnsupported())
1078: continue;
1079: commonGeneratedMethods.put(method
1080: .getNameParameters(), method);
1081: }
1082: // Now go thru the other classes, and remove any methods that we do
1083: // not find.
1084: while (it.hasNext()) {
1085: //System.out.println("---- Next bean");
1086: methods = (Collection) it.next();
1087: Map toKeep = new HashMap(); // Map<String, JavaWriter.Method>
1088: for (Iterator mit = methods.iterator(); mit
1089: .hasNext();) {
1090: JavaWriter.Method method = (JavaWriter.Method) mit
1091: .next();
1092: String nameParameters = method
1093: .getNameParameters();
1094: if (commonGeneratedMethods
1095: .containsKey(nameParameters)) {
1096: //System.out.println("Keeping "+nameParameters);
1097: toKeep.put(nameParameters,
1098: commonGeneratedMethods
1099: .get(nameParameters));
1100: }
1101: }
1102: commonGeneratedMethods = toKeep;
1103: }
1104: //System.out.println("Common Methods:");
1105: List sortedMethodNames = new ArrayList(
1106: commonGeneratedMethods.keySet());
1107: Collections.sort(sortedMethodNames);
1108: List sortedMethods = new ArrayList(sortedMethodNames
1109: .size());
1110: for (Iterator sortedMethodNamesIterator = sortedMethodNames
1111: .iterator(); sortedMethodNamesIterator
1112: .hasNext();) {
1113: sortedMethods.add(commonGeneratedMethods
1114: .get(sortedMethodNamesIterator.next()));
1115: }
1116: generateInterface(
1117: genDir,
1118: packageName,
1119: config.getGenerateCommonInterface(),
1120: sortedMethods,
1121: "This interface is the intersection of all generated methods.",
1122: null);
1123: }
1124: if (config.getDumpBeanTree() != null) {
1125: Writer out = new FileWriter(config.getDumpBeanTree());
1126: CodeGeneratorClass bc = (CodeGeneratorClass) generators
1127: .get(rootElement);
1128: bc.dumpBeanTree(out, "", config.getIndent());
1129: close(out);
1130: }
1131: if (config.isGenerateTagsFile()) {
1132: String tagsClassName = "Tags";
1133: while (illegalClassNames.containsKey(tagsClassName)) {
1134: tagsClassName = UNIQUE_PREFIX + tagsClassName;
1135: }
1136: OutputStream out = config.getOutputStreamProvider()
1137: .getStream(genDir, tagsClassName, "java"); // NOI18N
1138: generateTagsFile(out, packageName, tagsClassName);
1139: close(out);
1140: }
1141: }
1142: if (config.getGenerateDotGraph() != null) {
1143: Writer out = new FileWriter(config.getGenerateDotGraph());
1144: generateDotGraph(out, rootElement.getGraphNode());
1145: close(out);
1146: }
1147:
1148: if (!config.isQuiet())
1149: config.messageOut.println(Common.getMessage(
1150: "MSG_GenerationSummary", rootElement.getDTDName(),
1151: rootElement.getClassType()));
1152: }
1153:
1154: protected void processFinders(GraphNode rootGraphNode) {
1155: for (int i = 0, size = config.sizeFinder(); i < size; ++i) {
1156: String finderExpr = config.getFinder(i);
1157: processFinder(rootGraphNode, finderExpr);
1158: }
1159: MetaDD mdd = config.getMetaDD();
1160: for (Iterator it = mdd.fetchFinderList().iterator(); it
1161: .hasNext();) {
1162: String finderExpr = (String) it.next();
1163: processFinder(rootGraphNode, finderExpr);
1164: }
1165: }
1166:
1167: protected void processFinder(GraphNode rootGraphNode,
1168: String finderExpr) {
1169: String rootName = rootGraphNode.getName();
1170: //System.out.println("finderExpr="+finderExpr);
1171: //
1172: // Parse finder expression: on _ find _ by _"
1173: //
1174: String onExpr = null;
1175: String findExpr = null;
1176: boolean isListFindExpr = false;
1177: String byExpr = null;
1178: StringTokenizer st = new StringTokenizer(finderExpr);
1179: while (st.hasMoreTokens()) {
1180: String token = st.nextToken().intern();
1181: if (token == "on")
1182: onExpr = st.nextToken();
1183: else if (token == "find") {
1184: findExpr = st.nextToken();
1185: isListFindExpr = false;
1186: } else if (token == "findall") {
1187: findExpr = st.nextToken();
1188: isListFindExpr = true;
1189: } else if (token == "by")
1190: byExpr = st.nextToken();
1191: else
1192: throw new IllegalArgumentException(Common.getMessage(
1193: "MSG_BadTokenInFinder", token));
1194: }
1195: if (onExpr == null)
1196: throw new IllegalArgumentException(Common.getMessage(
1197: "MSG_MissingOnExpression", finderExpr));
1198:
1199: if (onExpr.startsWith("/" + rootName)) {
1200: onExpr = onExpr.substring(rootName.length() + 1, onExpr
1201: .length());
1202: if (onExpr.startsWith("/"))
1203: onExpr = onExpr.substring(1, onExpr.length());
1204: }
1205: //System.out.println("onExpr="+onExpr);
1206: GraphNode onNode = null;
1207: if (onExpr.equals("")) {
1208: // It's on the root
1209: onNode = rootGraphNode;
1210: } else {
1211: GraphLink gl = null;
1212: for (Iterator it = rootGraphNode.getGraphLink()
1213: .xPathIterator(onExpr); it.hasNext();) {
1214: gl = (GraphLink) it.next();
1215: if (gl == null)
1216: break;
1217: }
1218: if (gl == null)
1219: throw new IllegalArgumentException(Common.getMessage(
1220: "MSG_UnableToFindExpressionFromFinder",
1221: finderExpr));
1222: onNode = gl.element;
1223: }
1224: //System.out.println("onNode="+onNode);
1225: onNode.addExtraDataIncludeAlias(new Finder(findExpr, byExpr,
1226: isListFindExpr));
1227: }
1228:
1229: protected void setSchemaType(GraphNode[] list) {
1230: Map nodeMap = new HashMap(list.length * 4);
1231: for (int i = 0; i < list.length; ++i) {
1232: nodeMap.put(list[i].getNameWithNamespace(), list[i]);
1233: }
1234: GraphNode emptyGraphNode = null;
1235: for (Iterator it = config.readBeanGraphs(); it.hasNext();) {
1236: org.netbeans.modules.schema2beansdev.beangraph.BeanGraph bg = (org.netbeans.modules.schema2beansdev.beangraph.BeanGraph) it
1237: .next();
1238: for (int i = 0; i < bg.sizeSchemaTypeMapping(); ++i) {
1239: org.netbeans.modules.schema2beansdev.beangraph.SchemaTypeMappingType stm = bg
1240: .getSchemaTypeMapping(i);
1241: String key;
1242: if (stm.getSchemaTypeNamespace() == null)
1243: key = stm.getSchemaTypeName();
1244: else
1245: key = "{" + stm.getSchemaTypeNamespace() + "}"
1246: + stm.getSchemaTypeName();
1247: if (nodeMap.containsKey(key)) {
1248: GraphNode node = (GraphNode) nodeMap.get(key);
1249: //System.out.println("Found match from beangraph: node="+node);
1250: node.setJavaType(stm.getJavaType());
1251: node.setCreated(false);
1252: if (stm.isCanBeEmpty()) {
1253: node.setExtendedProperty("can-be-empty",
1254: Boolean.TRUE);
1255: }
1256: }
1257: }
1258: }
1259: }
1260:
1261: protected void generateInterface(String genDir, String packageName,
1262: String name, List methods, String comments,
1263: String extendsStatement) throws IOException {
1264: JavaWriter jw = new JavaWriter();
1265: jw.bigComment(comments + "\n\n@" + Common.GENERATED_TAG);
1266: jw.cr();
1267: if (!(packageName == null || "".equals(packageName))) {
1268: jw.writePackage(packageName);
1269: jw.cr();
1270: }
1271: jw.writeAccess(jw.PUBLIC);
1272: jw.write(" interface ");
1273: jw.write(name);
1274: jw.write(" ");
1275: if (extendsStatement != null)
1276: jw.write("extends ", extendsStatement, " ");
1277: jw.begin();
1278: for (Iterator methodsIterator = methods.iterator(); methodsIterator
1279: .hasNext();) {
1280: JavaWriter.Method method = (JavaWriter.Method) methodsIterator
1281: .next();
1282: method.writeMethod(jw);
1283: jw.eol();
1284: jw.cr();
1285: }
1286: jw.end();
1287: try {
1288: OutputStream out;
1289: out = config.getOutputStreamProvider().getStream(genDir,
1290: name, "java"); // NOI18N
1291: jw.writeTo(out);
1292: close(out);
1293: } catch (IOException ioe) {
1294: config.messageOut.println("Failed to generate interface: "
1295: + name); // NOI18N
1296: TraceLogger.error(ioe);
1297: throw ioe;
1298: }
1299: }
1300:
1301: protected BeanGraph generateBeanGraph(GraphNode[] list) {
1302: BeanGraph bg = new BeanGraph();
1303: for (int i = 0; i < list.length; ++i) {
1304: GraphNode node = list[i];
1305: BeanElement be = (BeanElement) node.getObject();
1306: SchemaTypeMappingType stm = new SchemaTypeMappingType(node
1307: .getName(), be.getFullClassType());
1308: stm.setRoot(be.isRoot());
1309: stm.setBean(be.isBean());
1310: stm.setCanBeEmpty(be.getCanBeEmpty());
1311: stm.setSchemaTypeNamespace(node.getNamespace());
1312: bg.addSchemaTypeMapping(stm);
1313: }
1314: return bg;
1315: }
1316:
1317: /**
1318: * Generate a .dot file for the dot or dotty program to run with.
1319: * This is primarily useful for debugging the graph that the schema parser
1320: * created for us. See http://www.graphviz.org
1321: */
1322: protected void generateDotGraph(Writer out, GraphNode node)
1323: throws IOException {
1324: out.write("digraph \"" + node.getName() + "\" {\n");
1325: out.write("\t\"" + node.getName() + "\" [shape=box]\n");
1326: out.write("\t\"" + node.getName() + "\" -> \""
1327: + node.getGraphLink() + "\";\n");
1328: generateDotGraph(out, node.getGraphLink(), new HashMap());
1329: out.write("}\n");
1330: }
1331:
1332: protected void generateDotGraph(Writer out, List children,
1333: Map doneLinks) throws IOException {
1334: for (Iterator it = children.iterator(); it.hasNext();) {
1335: GraphLink l = (GraphLink) it.next();
1336: generateDotGraph(out, l, doneLinks);
1337: }
1338: }
1339:
1340: protected void generateDotGraph(Writer out, GraphLink l,
1341: Map doneLinks) throws IOException {
1342: if (l == null)
1343: return;
1344: doneLinks.put(l, null);
1345: out.write("\t\"" + l + "\" [label=\"" + dotGraphLabel(l)
1346: + "\"];\n");
1347: GraphNode node = l.element;
1348: if (node != null) {
1349: BeanBuilder.BeanElement be = (BeanBuilder.BeanElement) node
1350: .getObject();
1351: if (be == null)
1352: return;
1353:
1354: String type = be.getClassType();
1355: out.write("\t\"" + node + "\" [label=\""
1356: + dotGraphLabel(node) + "\", shape=box];\n");
1357: out
1358: .write("\t\""
1359: + l
1360: + "\" -> \""
1361: + node
1362: + "\" [label=\"type of property\", color=darkgreen];\n");
1363: if ("#PCDATA".equals(l.name) && "String".equals(type)) {
1364: return;
1365: }
1366: AttrProp[] attrs = node.getAttributes();
1367: for (int i = 0; i < attrs.length; ++i) {
1368: String attrName = node.getName() + " attribute "
1369: + attrs[i].getName();
1370: out
1371: .write("\t\"" + attrName + "\" [label=\""
1372: + dotGraphLabel(attrs[i])
1373: + "\", shape=egg];\n");
1374: out.write("\t\"" + node + "\" -> \"" + attrName
1375: + "\" [label=\"attribute\", color=magenta];\n");
1376: }
1377:
1378: GraphLink hasAttr = node.getGraphLink();
1379: if (hasAttr != null) {
1380: if (node.getMarked() == false) {
1381: if ((config.isTraceDot() || hasData(hasAttr))
1382: && !doneLinks.containsKey(hasAttr)) {
1383: out
1384: .write("\t\""
1385: + node
1386: + "\" -> \""
1387: + hasAttr
1388: + "\" [label=\"has attr\", color=purple];\n");
1389: node.setMarked(true);
1390: generateDotGraph(out, hasAttr, doneLinks);
1391: node.setMarked(false);
1392: }
1393: }
1394: }
1395: }
1396:
1397: List children = l.getChildren();
1398: for (Iterator childIt = children.iterator(); childIt.hasNext();) {
1399: GraphLink child = (GraphLink) childIt.next();
1400: out.write("\t\"" + l + "\" -> \"" + child
1401: + "\" [label=child, color=blue];\n");
1402: }
1403: generateDotGraph(out, children, doneLinks);
1404:
1405: /*
1406: GraphLink sibling = l.getSibling();
1407: if (sibling != null) {
1408: while (!config.isTraceDot() && sibling.name == null &&
1409: sibling.getFirstChild() == null &&
1410: sibling.getSibling() != null)
1411: sibling = sibling.getSibling();
1412: out.write("\t\""+l+"\" -> \""+sibling+"\" [label=sibling, color=red];\n");
1413: }
1414: */
1415: }
1416:
1417: private String dotGraphLabel(GraphLink l) {
1418: if (config.isTraceDot()) {
1419: String elementInstance = TreeBuilder.instanceToString(l
1420: .getElementInstance(), true);
1421: String groupInstance = TreeBuilder.instanceToString(l
1422: .getGroupInstance(), true);
1423: String result = "GraphLink@"
1424: + Integer.toHexString(l.hashCode());
1425: if (l.name == null)
1426: result += " (grouping)";
1427: else
1428: result += ":" + l.name;
1429: result += "\\n";
1430: if (!"".equals(elementInstance))
1431: result += " element: " + elementInstance;
1432: if (!"".equals(groupInstance))
1433: result += " group: " + groupInstance;
1434: if (l.isSequenceAnd())
1435: result += " ,";
1436: if (l.isSequenceOr())
1437: result += " |";
1438: return result;
1439: } else if (l.name == null)
1440: return "GraphLink";
1441: else
1442: return "property: " + l.name;
1443: }
1444:
1445: private String dotGraphLabel(GraphNode node) {
1446: String result;
1447: if (config.isTraceDot())
1448: result = "GraphNode@"
1449: + Integer.toHexString(node.hashCode()) + ":"
1450: + node.toString();
1451: else
1452: result = node.getName();
1453: if (node.getJavaType() != null)
1454: result += ":" + node.getJavaType();
1455: return result;
1456: }
1457:
1458: private String dotGraphLabel(AttrProp attr) {
1459: return attr.toString();
1460: }
1461:
1462: private boolean hasData(GraphLink l) {
1463: for (; l != null; l = l.getSibling()) {
1464: if (l.name != null)
1465: return true;
1466: if (l.element != null) {
1467: return true;
1468: }
1469: if (l.getFirstChild() != null)
1470: if (hasData(l.getFirstChild()))
1471: return true;
1472: }
1473: return false;
1474: }
1475:
1476: protected void generateTagsFile(OutputStream out,
1477: String packageName, String className) throws IOException {
1478: JavaWriter jw = new JavaWriter();
1479: jw
1480: .bigComment("This class has all element and attribute names as constants.\n\n@"
1481: + Common.GENERATED_TAG);
1482: jw.cr();
1483: jw.writePackage(packageName);
1484: jw.cr();
1485:
1486: jw.writeClassDecl(className, null, null, jw.PUBLIC);
1487: jw.select(jw.DECL_SECTION);
1488:
1489: for (Iterator it = constNameMap.keySet().iterator(); it
1490: .hasNext();) {
1491: String constName = (String) it.next();
1492: String dtdName = (String) constNameMap.get(constName);
1493: jw.write("public final static String ", constName, " = ");
1494: jw.writeEol("\"", dtdName, "\"");
1495: }
1496: jw.cr();
1497:
1498: jw.select(jw.CONSTRUCTOR_SECTION);
1499: jw.comment("This class is not to be instantiated.");
1500: jw.beginConstructor(className, "", null, jw.PRIVATE);
1501: jw.end();
1502:
1503: jw.writeTo(out);
1504: }
1505:
1506: /**
1507: * Search in the MetaDD @mdd for @dtdName
1508: */
1509: private MetaElement getMetaElement(MetaDD mdd, String dtdName) {
1510: return getMetaElement(mdd, dtdName, null);
1511: }
1512:
1513: private MetaElement getMetaElement(MetaDD mdd, String dtdName,
1514: String namespace) {
1515: if (mdd == null)
1516: return null;
1517: int size = mdd.sizeMetaElement();
1518: for (int i = 0; i < size; i++) {
1519: MetaElement e = mdd.getMetaElement(i);
1520: if (e == null)
1521: continue;
1522: if (namespace != null
1523: && !namespace.equals(e.getNamespace()))
1524: continue;
1525: if (e.getDtdName().equals(dtdName))
1526: return e;
1527: }
1528: return null;
1529: }
1530:
1531: private void addToImplements(MetaElement e, String interfce) {
1532: String implList = e.getImplements();
1533: if (implList == null) {
1534: e.setImplements(interfce);
1535: return;
1536: }
1537: //
1538: // Check to see if we already have this one.
1539: //
1540: implList = implList.trim();
1541: int pos = implList.indexOf(',');
1542: while (pos >= 0) {
1543: String impl = implList.substring(0, pos);
1544: impl = impl.trim();
1545: if (impl.equals(interfce))
1546: return;
1547: implList = implList.substring(pos + 1, implList.length());
1548: implList = implList.trim();
1549: pos = implList.indexOf(',');
1550: }
1551: if (implList.equals(interfce))
1552: return;
1553:
1554: //
1555: // It's a new interface, add it on in.
1556: //
1557: e.setImplements(e.getImplements() + ", " + interfce);
1558: }
1559:
1560: private void addToBeanInterfaceExtends(MetaElement e,
1561: String interfce) {
1562: String implList = e.getBeanInterfaceExtends();
1563: if (implList == null) {
1564: e.setBeanInterfaceExtends(interfce);
1565: return;
1566: }
1567: //
1568: // Check to see if we already have this one.
1569: //
1570: implList = implList.trim();
1571: int pos = implList.indexOf(',');
1572: while (pos >= 0) {
1573: String impl = implList.substring(0, pos);
1574: impl = impl.trim();
1575: if (impl.equals(interfce))
1576: return;
1577: implList = implList.substring(pos + 1, implList.length());
1578: implList = implList.trim();
1579: pos = implList.indexOf(',');
1580: }
1581: if (implList.equals(interfce))
1582: return;
1583:
1584: //
1585: // It's a new interface, add it on in.
1586: //
1587: e.setBeanInterfaceExtends(e.getBeanInterfaceExtends() + ", "
1588: + interfce);
1589: }
1590:
1591: protected void close(OutputStream out) throws java.io.IOException {
1592: out.close();
1593: if (!config.isQuiet()
1594: && config.isTraceGen()
1595: && out instanceof org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream) {
1596: org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream widos = (org.netbeans.modules.schema2beansdev.gen.WriteIfDifferentOutputStream) out;
1597: if (!widos.isChanged())
1598: config.messageOut.println(Common
1599: .getMessage("MSG_DidNotChangeFile"));
1600: }
1601: }
1602:
1603: protected void close(Writer out) throws java.io.IOException {
1604: out.close();
1605: }
1606: }
|