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-2007 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.uml.core.support.umlutils;
0043:
0044: import org.netbeans.modules.uml.core.metamodel.core.constructs.PartFacade;
0045: import java.lang.reflect.Method;
0046: import java.util.HashSet;
0047: import java.util.Hashtable;
0048: import java.util.Vector;
0049: import org.dom4j.Attribute;
0050: import org.dom4j.Document;
0051: import org.dom4j.Node;
0052: import java.util.List;
0053: import org.netbeans.modules.uml.common.ETSystem;
0054: import org.netbeans.modules.uml.core.coreapplication.ICoreProduct;
0055: import org.netbeans.modules.uml.core.metamodel.core.constructs.IPartFacade;
0056: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
0057: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IAssociation;
0058: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IParameterableElement;
0059: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IUMLBinding;
0060: import org.netbeans.modules.uml.core.support.umlsupport.ProductRetriever;
0061: import org.netbeans.modules.uml.core.support.umlsupport.XMLManip;
0062:
0063: /**
0064: * <p>Title: </p>
0065: * <p>Description: </p>
0066: * <p>Copyright: Copyright (c) 2003</p>
0067: * <p>Company: </p>
0068: * @author not attributable
0069: * @version 1.0
0070: */
0071:
0072: public class PropertyDefinitionFactory implements
0073: IPropertyDefinitionFactory {
0074:
0075: private String m_definitionFile = null;
0076: private Document m_Doc = null;
0077: private Object m_ModelElement = null;
0078: private Hashtable<String, IPropertyDefinition> m_DefinitionMap = new Hashtable<String, IPropertyDefinition>();
0079: private HashSet<String> m_NoDefinitionSet = new HashSet<String>();
0080: private Hashtable<String, Node> m_NodeMap = new Hashtable<String, Node>();
0081: private Hashtable<String, Node> m_NamedNodeMap = new Hashtable<String, Node>();
0082:
0083: //typedef std::map < UINT, CComPtr< IFunction > > IDMap;
0084: private Hashtable m_IDMap = new Hashtable();
0085:
0086: //typedef std::map < CComBSTR, IDMap > FunctionMap;
0087: private Hashtable m_FunctionMap = new Hashtable();
0088:
0089: public PropertyDefinitionFactory() {
0090: }
0091:
0092: /**
0093: * Retrieve or create the proper property definition for the passed-in element type.
0094: *
0095: * @param[in] eleStr The element type
0096: * @param[in] pDisp The model element (used to build the function maps for the IDispatch for faster
0097: * lookup when doing get/set/insert/deletes. Also used to get the help description)
0098: * @param[out] pVal The property definition that has been created or found
0099: *
0100: * @return HRESULT
0101: *
0102: */
0103: public IPropertyDefinition getPropertyDefinitionForElement(
0104: String eleName, Object pDisp) {
0105: IPropertyDefinition propDef = null;
0106: if (eleName == null || eleName.length() == 0) {
0107: // have to special case part facade
0108: if (pDisp instanceof IPartFacade) {
0109: IPartFacade pPart = (IPartFacade) pDisp;
0110:
0111: // actually only need to special case a part facade representing a use case
0112: // unfortunately this information is on a parameterable element, not the part
0113: // facade
0114: if (pPart instanceof IParameterableElement) {
0115: IParameterableElement pParamEle = (IParameterableElement) pPart;
0116: eleName = "PartFacade";
0117: String type = pParamEle.getTypeConstraint();
0118: if (type != null && type.length() > 0) {
0119: eleName += type;
0120: }
0121: }
0122: } else if (pDisp instanceof IUMLBinding) {
0123: eleName = "UMLBinding";
0124: }
0125:
0126: // haven't found it yet, so now use element type
0127: if (eleName == null || eleName.length() == 0) {
0128: if (pDisp instanceof IElement) {
0129: IElement pUMLEle = (IElement) pDisp;
0130: eleName = pUMLEle.getElementType();
0131: }
0132: }
0133: }
0134: propDef = getFromDefinitionMap(eleName);
0135:
0136: if (propDef == null) {
0137: //buildFunctionMap(pDisp);
0138:
0139: //This member variable creates a leak. For instance
0140: // Open a workspace and then close it right away. View
0141: // the memory detector addin and you'll have 2 workspaces
0142: // still in memory (one is design center). Then set a break in
0143: // FinalRelease of Workspace you'll see that this
0144: // being released does a final release of the IWorkspace.
0145: //factory
0146: //m_ModelElement = pDisp;
0147:
0148: propDef = createDefinition(eleName);
0149: if (propDef != null) {
0150: addToDefinitionMap(eleName, propDef);
0151: }
0152: }
0153: setAppropriateDisplayName(propDef, pDisp);
0154: return propDef;
0155: }
0156:
0157: private void setAppropriateDisplayName(IPropertyDefinition propDef,
0158: Object pDisp) {
0159: String expandedType = null;
0160: if (pDisp instanceof IAssociation) {
0161: expandedType = ((IElement) pDisp).getExpandedElementType();
0162: if (expandedType != null
0163: && expandedType.trim().length() > 0) {
0164: propDef.setDisplayName(expandedType.replace('_', ' '));
0165: }
0166: } else if (pDisp instanceof PartFacade) {
0167: expandedType = ((IElement) pDisp).getExpandedElementType();
0168: if (expandedType != null) {
0169: expandedType = expandedType.toLowerCase();
0170: if (expandedType.equals("partfacade_class")) {
0171: propDef.setDisplayName("PSK_PE_CLASSPARTICIPANT");
0172: } else if (expandedType.equals("partfacade_interface")) {
0173: propDef
0174: .setDisplayName("PSK_PE_INTERFACEPARTICIPANT");
0175: } else if (expandedType.equals("partfacade_actor")) {
0176: propDef.setDisplayName("PSK_PE_ACTORPARTICIPANT");
0177: } else if (expandedType.equals("partfacade_usecase")) {
0178: propDef.setDisplayName("PSK_PE_USECASEPARTICIPANT");
0179: }
0180: }
0181: }
0182: }
0183:
0184: /**
0185: * Transfer the information from the xml dom node to the property definition. This handles the special case
0186: * processing for when the get method returns an IDispatch. The DispatchInvokes tell us what to do with the
0187: * IDispatch that was returned.
0188: *
0189: * @param[in] pEle The xml dom node to obtain the information from
0190: * @param[in] pDef The property definition to add the information to
0191: *
0192: * @return HRESULT
0193: *
0194: */
0195: private void processOtherInvokes(Node pNode,
0196: IPropertyDefinition pDef) {
0197: // Some of the get routines return an IDispatch which may or may not need more things done
0198: // to it in order to display it in the property editor
0199: // The section in the xml file looks like:
0200: // <DispatchInvoke name="{123-456}" get="Type"/>
0201: // and tells us if the dispatch can be cast to an object represented by the name,
0202: // then invoke the get="" method on the IDispatch
0203: String pattern = "DispatchInvoke";
0204: try {
0205: if (pNode instanceof org.dom4j.Element) {
0206: org.dom4j.Element ele = (org.dom4j.Element) pNode;
0207: List list = ele.elements();
0208: if (list != null && list.size() > 0) {
0209: for (int i = 0; i < list.size(); i++) {
0210: Node node = (Node) list.get(i);
0211: if (node.getName().equals(pattern)) {
0212: Node nameNode = XMLManip.getAttribute(node,
0213: "name");
0214: Node getNode = XMLManip.getAttribute(node,
0215: "get");
0216: //Node nameNode = XPathAPI.selectSingleNode(node, "@name");
0217: //Node getNode = XPathAPI.selectSingleNode(node, "@get");
0218: String name = null;
0219: String get = null;
0220: if (nameNode != null)
0221: name = nameNode.getStringValue();
0222: if (getNode != null)
0223: get = getNode.getStringValue();
0224:
0225: pDef.addToAttrMap("castID", name);
0226: pDef.addToAttrMap("castIDGet", get);
0227: }
0228: }
0229: }
0230: }
0231: } catch (Exception e) {
0232: }
0233: }
0234:
0235: /**
0236: * Retrieve the property definition for the passed in value
0237: *
0238: * @param[in] name The element type of the definition to retrieve
0239: * @param[out] pVal The retrieved property definition
0240: *
0241: * @return HRESULT
0242: *
0243: */
0244: private IPropertyDefinition getFromDefinitionMap(String eName) {
0245: IPropertyDefinition pDef = null;
0246: try {
0247: pDef = m_DefinitionMap.get(eName);
0248: } catch (Exception e) {
0249: }
0250: return pDef;
0251: }
0252:
0253: private Node getFromNodeMap(String eName) {
0254: Node pNode = null;
0255: try {
0256: pNode = m_NodeMap.get(eName);
0257: } catch (Exception e) {
0258: }
0259: return pNode;
0260: }
0261:
0262: private Node getFromNamedNodeMap(String eName) {
0263: Node pNode = null;
0264: try {
0265: pNode = m_NamedNodeMap.get(eName);
0266: } catch (Exception e) {
0267: }
0268: return pNode;
0269: }
0270:
0271: /**
0272: * Add the passed in property definition to the factory map
0273: *
0274: * @param[in] name The element type
0275: * @param[in] pVal The property definition to add to the map
0276: *
0277: * @return HRESULT
0278: *
0279: */
0280: private void addToDefinitionMap(String eName,
0281: IPropertyDefinition pDef) {
0282: if (eName.length() > 0) {
0283: m_DefinitionMap.put(eName, pDef);
0284: }
0285: }
0286:
0287: //this method is added because sub definitions references FontDefinition
0288: //multiple times and each time the XPathAPI was used to get to the node,
0289: //now we are catching the node and using it.
0290: //Keeps the Node and corresponding id in the map.
0291: private void addToNodeMap(Node node, String eName) {
0292: if (eName != null && eName.length() > 0) {
0293: m_NodeMap.put(eName, node);
0294: }
0295: }
0296:
0297: //Keeps the Node and corresponding name in the map.
0298: private void addToNamedNodeMap(Node node, String eName) {
0299: if (eName.length() > 0) {
0300: m_NamedNodeMap.put(eName, node);
0301: }
0302: }
0303:
0304: /**
0305: * Process the sub definitions of the xml node. These are predefined in the xml file.
0306: *
0307: * @param[in] parentNode The xml node to process
0308: * @param[in] parentDef The owning property definition to which any subs will be added
0309: *
0310: * @return HRESULT
0311: *
0312: */
0313: private void processSubDefinitions(Node pNode,
0314: IPropertyDefinition pDef) {
0315: if (pNode.getNodeType() == Node.ELEMENT_NODE) {
0316: org.dom4j.Element elem = (org.dom4j.Element) pNode;
0317: List list = elem.selectNodes("aDefinition");
0318: if (list != null) {
0319: int count = list.size();
0320: for (int i = 0; i < count; i++) {
0321: Node n = (Node) list.get(i);
0322: testmyProcessSubDefinitions(n, pDef);
0323: }
0324: }
0325: }
0326: }
0327:
0328: private void testmyProcessSubDefinitions(Node item,
0329: IPropertyDefinition pDef) {
0330:
0331: Node refNode = XMLManip.getAttribute(item, "pdref");
0332: //Node refNode = XPathAPI.selectSingleNode(item, "@pdref");
0333: if (refNode != null) {
0334: // if the sub definition references another definition, we need to build that one
0335: String refVal = refNode.getStringValue();
0336: if (refVal.length() > 0) {
0337: // if the sub definition is an on demand definition, we actually don't build
0338: // it at this time
0339: Node onDemNode = XMLManip
0340: .getAttribute(item, "onDemand");
0341: //Node onDemNode = XPathAPI.selectSingleNode(item, "@onDemand");
0342: if (onDemNode != null) {
0343: String onDemand = onDemNode.getStringValue();
0344: if (onDemand.equals("true")) {
0345: // build part of it because it is on demand
0346: buildOnDemandDefinition(item, pDef);
0347: } else {
0348: // not on demand, so build it
0349: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal);
0350: if (n == null) {
0351: n = findPropertyDefinitionDOMNode(refVal);
0352: }
0353: if (n != null)
0354: processSubDefinitions(n, pDef);
0355: }
0356: } else {
0357: // not on demand, so build it
0358: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal);
0359: if (n == null) {
0360: n = findPropertyDefinitionDOMNode(refVal);
0361: }
0362: if (n != null)
0363: processSubDefinitions(n, pDef);
0364: }
0365: } else {
0366: // not referencing anything else, so build straight up
0367: buildDefinition(item, pDef);
0368: }
0369: } else {
0370: // Need to special case this - the edit control which is using the definitions and
0371: // factory needs the structure to be like this:
0372: // <Params
0373: // <Param <-- No on demand, but a pdref
0374: // <Name
0375: // The property editor needs it to look like this:
0376: // <Params
0377: // <Param <-- On demand, but a pdref
0378: // so then when the user clicks on the on demand, the property editor builds the right
0379: // stuff and replaces the definition
0380: // If it is not on demand, but pdref'ed, the param node is not built because then in
0381: // the property editor, we would get
0382: // <Class
0383: // <Classifier
0384: // <NamedElement
0385: // which is why the edit control now has a pdref2 not a pdref
0386: Node refNode2 = XMLManip.getAttribute(item, "pdref2");
0387: //Node refNode2 = XPathAPI.selectSingleNode(item, "@pdref2");
0388: if (refNode2 != null) {
0389: String refVal2 = refNode2.getStringValue();
0390: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal2);
0391: if (n != null)
0392: buildDefinition(n, pDef);
0393: } else {
0394: buildDefinition(item, pDef);
0395: }
0396: }
0397: }
0398:
0399: /* private void processSubDefinitions(Node pNode, IPropertyDefinition pDef)
0400: {
0401: try {
0402: String pattern = "aDefinition";
0403: //Sumitabh check if this is XPath
0404: List list = XMLManip.selectNodeListNS(pNode, pattern);
0405: //List list = XPathAPI.selectNodeList(pNode, pattern);
0406: if (list != null && list.getLength() > 0)
0407: {
0408: for (int i=0; i<list.getLength(); i++)
0409: {
0410: Node item = list.item(i);
0411: Node refNode = XMLManip.getAttribute(item, "pdref");
0412: //Node refNode = XPathAPI.selectSingleNode(item, "@pdref");
0413: if (refNode != null)
0414: {
0415: // if the sub definition references another definition, we need to build that one
0416: String refVal = refNode.getNodeValue();
0417: if (refVal.length() > 0)
0418: {
0419: // if the sub definition is an on demand definition, we actually don't build
0420: // it at this time
0421: Node onDemNode = XMLManip.getAttribute(item, "onDemand");
0422: //Node onDemNode = XPathAPI.selectSingleNode(item, "@onDemand");
0423: if (onDemNode != null)
0424: {
0425: String onDemand = onDemNode.getNodeValue();
0426: if (onDemand.equals("true"))
0427: {
0428: // build part of it because it is on demand
0429: buildOnDemandDefinition(item, pDef);
0430: }
0431: else
0432: {
0433: // not on demand, so build it
0434: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal);
0435: if (n != null)
0436: processSubDefinitions(n, pDef);
0437: }
0438: }
0439: else
0440: {
0441: // not on demand, so build it
0442: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal);
0443: if (n != null)
0444: processSubDefinitions(n, pDef);
0445: }
0446: }
0447: else
0448: {
0449: // not referencing anything else, so build straight up
0450: buildDefinition(item, pDef);
0451: }
0452: }
0453: else
0454: {
0455: // Need to special case this - the edit control which is using the definitions and
0456: // factory needs the structure to be like this:
0457: // <Params
0458: // <Param <-- No on demand, but a pdref
0459: // <Name
0460: // The property editor needs it to look like this:
0461: // <Params
0462: // <Param <-- On demand, but a pdref
0463: // so then when the user clicks on the on demand, the property editor builds the right
0464: // stuff and replaces the definition
0465: // If it is not on demand, but pdref'ed, the param node is not built because then in
0466: // the property editor, we would get
0467: // <Class
0468: // <Classifier
0469: // <NamedElement
0470: // which is why the edit control now has a pdref2 not a pdref
0471: Node refNode2 = XMLManip.getAttribute(item, "pdref2");
0472: //Node refNode2 = XPathAPI.selectSingleNode(item, "@pdref2");
0473: if (refNode2 != null)
0474: {
0475: String refVal2 = refNode2.getNodeValue();
0476: Node n = findPropertyDefinitionDOMNodeForSubDef(refVal2);
0477: if (n != null)
0478: buildDefinition(n, pDef);
0479: }
0480: else
0481: {
0482: buildDefinition(item, pDef);
0483: }
0484: }
0485: }
0486: }
0487: } catch (Exception e)
0488: {
0489:
0490: }
0491: }*/
0492:
0493: /**
0494: * Transfer the information from the xml dom node to the property definition
0495: *
0496: * @param[in] pEle The xml dom node to obtain the information from
0497: * @param[in] parentDef The owning property definition to which to add the newly built definition to
0498: *
0499: * @return HRESULT
0500: *
0501: */
0502: private void buildDefinition(Node pNode, IPropertyDefinition pDef) {
0503: try {
0504: // we have the potential for there to be duplicate property definitions within a single "element"
0505: // because of multiple inheritance
0506: // IClass -> IClassifier -> INamespace -> INamedElement
0507: // -> IRedefinableElement -> INamedElement
0508: // -> IPackageableElement -> INamedElement
0509: // which was then giving us multiple name definitions
0510: //
0511: // this now checks its sub definitions for one matching the name, and only builds it if there is
0512: // not one present
0513: if (pNode != null) {
0514: Node pNamedNode = XMLManip.getAttribute(pNode, "name");
0515: //Node pNamedNode = XPathAPI.selectSingleNode(pNode, "@name");
0516: if (pNamedNode != null) {
0517: String name = pNamedNode.getStringValue();
0518: // Vector defs = pDef.getSubDefinitions();
0519: // if (defs != null) {
0520: IPropertyDefinition def = pDef
0521: .getSubDefinition(name);
0522: /* Enumeration enum = defs.elements();
0523: while (enum.hasMoreElements()) {
0524: Object obj = enum.nextElement();
0525: if (obj instanceof IPropertyDefinition) {
0526: IPropertyDefinition def1 = (IPropertyDefinition) obj;
0527: if (def1.getName().equals(name))
0528: {
0529: def = def1;
0530: break;
0531: }
0532: }
0533: }*/
0534: if (def == null) {
0535: def = new PropertyDefinition();
0536: setAttributes(pNode, def);
0537: pDef.addSubDefinition(def);
0538: processSubDefinitions(pNode, def);
0539: }
0540: // }
0541: }
0542: }
0543: } catch (Exception e) {
0544: }
0545: }
0546:
0547: /**
0548: * Transfer the information from the xml dom node to the property definition for a definition that
0549: * has been marked as on demand. This information is different from a node that is built right away.
0550: *
0551: * @param[in] pEle The xml node to obtain the information from
0552: * @param[in] parentDef The owning property definition to which to add the newly built definition to
0553: *
0554: * @return HRESULT
0555: *
0556: */
0557: private void buildOnDemandDefinition(Node pNode,
0558: IPropertyDefinition pDef) {
0559: IPropertyDefinition def = new PropertyDefinition();
0560: setRefAttributes(pNode, def);
0561: pDef.addSubDefinition(def);
0562: }
0563:
0564: /**
0565: * Catch all routine to build a map of attributes for this xml dom node. This will catch any
0566: * attributes that do not have get/set methods for them
0567: *
0568: * @param[in] pEle The xml node to obtain the information from
0569: * @param[in] pDef The property definition to add the information to
0570: *
0571: * @return HRESULT
0572: *
0573: */
0574: private void processAttributes(Node pNode, IPropertyDefinition pDef) {
0575: if (pNode != null && pDef != null) {
0576: try {
0577: if (pNode instanceof org.dom4j.Element) {
0578: org.dom4j.Element ele = (org.dom4j.Element) pNode;
0579: int count = ele.attributeCount();
0580: for (int i = 0; i < count; i++) {
0581: Attribute attr = ele.attribute(i);
0582: String name = attr.getName();
0583: String value = attr.getValue();
0584: pDef.addToAttrMap(name, value);
0585: }
0586:
0587: // List list = ele.elements();//attributes();
0588: // if (list != null)
0589: // {
0590: // int count = list.size();
0591: // for (int i=0; i<count; i++)
0592: // {
0593: // Attribute attr = (Attribute)list.get(i);
0594: // String name = attr.getName();
0595: // String value = attr.getValue();
0596: // pDef.addToAttrMap(name, value);
0597: // }
0598: // }
0599: }
0600: } catch (Exception e) {
0601: //e.printStackTrace();
0602: }
0603: }
0604: }
0605:
0606: /**
0607: * Transfer the information from the xml dom node to the property definition
0608: *
0609: * @param[in] pEle The xml dom node to obtain the information from
0610: * @param[in] pDef The property defintion to add the information to
0611: *
0612: * @return HRESULT
0613: *
0614: */
0615: private void setAttributes(Node pNode, IPropertyDefinition pDef) {
0616: try {
0617: if (pNode instanceof org.dom4j.Element) {
0618: org.dom4j.Element ele = (org.dom4j.Element) pNode;
0619:
0620: //update the ID
0621: Attribute idAttr = ele.attribute("id");
0622: if (idAttr != null) {
0623: String idVal = idAttr.getValue();
0624: pDef.setID(idVal);
0625: }
0626:
0627: //update the name
0628: Attribute nameAttr = ele.attribute("name");
0629: if (nameAttr != null) {
0630: String nameVal = nameAttr.getValue();
0631: pDef.setName(nameVal);
0632: }
0633:
0634: //update the display name
0635: Attribute dispAttr = ele.attribute("displayName");
0636: if (dispAttr != null) {
0637: String dispVal = dispAttr.getValue();
0638: pDef.setDisplayName(dispVal);
0639: }
0640:
0641: //update the multiplicity
0642: long mult = 1;
0643: Attribute multAttr = ele.attribute("multiplicity");
0644: if (multAttr != null) {
0645: String multVal = multAttr.getValue();
0646: if (multVal.equals("*"))
0647: mult = 2;
0648: }
0649: pDef.setMultiplicity(mult);
0650:
0651: //update the control type
0652: Attribute contAttr = ele.attribute("controlType");
0653: if (contAttr != null) {
0654: String contVal = contAttr.getValue();
0655: pDef.setControlType(contVal);
0656: }
0657:
0658: //update valid values
0659: Attribute valAttr = ele.attribute("values");
0660: if (valAttr != null) {
0661: String val = valAttr.getValue();
0662: pDef.setValidValues(val);
0663: processValues(val, pDef);
0664:
0665: //update valid values
0666: Attribute enumAttr = ele.attribute("enumValues");
0667: if (enumAttr != null) {
0668: String enumVals = enumAttr.getValue();
0669: pDef.setEnumValues(enumVals);
0670: }
0671: }
0672:
0673: //update get method name
0674: String getMethodName = null;
0675: Attribute getAttr = ele.attribute("get");
0676: if (getAttr != null) {
0677: String getVal = getAttr.getValue();
0678: pDef.setGetMethod(getVal);
0679: getMethodName = getVal;
0680: }
0681:
0682: //update set method name
0683: Attribute setAttr = ele.attribute("set");
0684: if (setAttr != null) {
0685: String setVal = setAttr.getValue();
0686: pDef.setSetMethod(setVal);
0687: }
0688:
0689: //update insert method name
0690: Attribute insAttr = ele.attribute("insert");
0691: if (insAttr != null) {
0692: String insVal = insAttr.getValue();
0693: pDef.setInsertMethod(insVal);
0694: }
0695:
0696: //update delete method name
0697: Attribute delAttr = ele.attribute("delete");
0698: if (delAttr != null) {
0699: String delVal = delAttr.getValue();
0700: pDef.setDeleteMethod(delVal);
0701: }
0702:
0703: //update create method name
0704: Attribute crtAttr = ele.attribute("create");
0705: if (crtAttr != null) {
0706: String crtVal = crtAttr.getValue();
0707: pDef.setCreateMethod(crtVal);
0708: }
0709:
0710: //update validate method name
0711: Attribute validAttr = ele.attribute("validate");
0712: if (validAttr != null) {
0713: String validVal = validAttr.getValue();
0714: pDef.setValidateMethod(validVal);
0715: }
0716:
0717: //update image name
0718: Attribute imgAttr = ele.attribute("image");
0719: if (imgAttr != null) {
0720: String imgVal = imgAttr.getValue();
0721: pDef.setImage(imgVal);
0722: }
0723:
0724: //update progID
0725: Attribute progAttr = ele.attribute("progID");
0726: if (progAttr != null) {
0727: String progVal = progAttr.getValue();
0728: pDef.setProgID(progVal);
0729: }
0730:
0731: //update help text
0732: Attribute helpAttr = ele.attribute("helpText");
0733: if (helpAttr != null) {
0734: String helpVal = helpAttr.getValue();
0735: pDef.setHelpDescription(helpVal);
0736: }
0737: // else {
0738: // if (m_ModelElement != null) {
0739: // buildHelpDocumentation(pDef, m_ModelElement, getMethodName);
0740: // }
0741: // }
0742:
0743: //update onDemand
0744: pDef.setOnDemand(false);
0745: Attribute demAttr = ele.attribute("onDemand");
0746: if (demAttr != null) {
0747: String demVal = demAttr.getValue();
0748: if (demVal.equals("true"))
0749: pDef.setOnDemand(true);
0750: }
0751:
0752: //update required
0753: pDef.setRequired(false);
0754: Attribute reqAttr = ele.attribute("required");
0755: if (reqAttr != null) {
0756: String reqVal = reqAttr.getValue();
0757: if (reqVal.equals("true"))
0758: pDef.setRequired(true);
0759: }
0760:
0761: //update force refresh
0762: pDef.setForceRefersh(false);
0763: Attribute refreshAttr = ele.attribute("forceRefresh");
0764: if (refreshAttr != null) {
0765: String refreshVal = refreshAttr.getValue();
0766: if (refreshVal.equals("true"))
0767: pDef.setForceRefersh(true);
0768: }
0769:
0770: //update defaultValue
0771: pDef.setDefaultExists(false);
0772: Attribute defAttr = ele.attribute("defaultValue");
0773: if (defAttr != null) {
0774: String defVal = defAttr.getValue();
0775: pDef.setDefaultValue(defVal);
0776: pDef.setDefaultExists(true);
0777: }
0778: }
0779:
0780: // call to build any other attributes that may not be listed here
0781: processAttributes(pNode, pDef);
0782:
0783: // new section in the xml file that states what to do with the information
0784: // we receive back from a "get" call, when that information is a IDispatch
0785: processOtherInvokes(pNode, pDef);
0786: } catch (Exception e) {
0787: //e.printStackTrace();
0788: }
0789: }
0790:
0791: /**
0792: * Transfer the information from the xml dom node to the property definition. This is a special
0793: * case if the property definition is referencing some other definition. Only certain things need
0794: * to be stored.
0795: *
0796: * @param[in] pEle The xml dom node to transfer the information from
0797: * @param[in] pDef The property definition to add the information to
0798: *
0799: * @return HRESULT
0800: *
0801: */
0802: private void setRefAttributes(Node pNode, IPropertyDefinition pDef) {
0803: try {
0804: if (pNode instanceof org.dom4j.Element) {
0805: org.dom4j.Element ele = (org.dom4j.Element) pNode;
0806:
0807: //update the ID
0808: Attribute idNode = ele.attribute("id");
0809: if (idNode != null) {
0810: String idVal = idNode.getValue();
0811: pDef.setID(idVal);
0812: }
0813:
0814: //update the name
0815: Attribute nameNode = ele.attribute("pdref");
0816: if (nameNode != null) {
0817: String nameVal = nameNode.getValue();
0818: //This is different from C++ version, as our pdref is ID
0819: org.dom4j.Element domEle = m_Doc
0820: .elementByID(nameVal);
0821: if (domEle != null) {
0822: String actualName = domEle
0823: .attributeValue("name");
0824: pDef.setName(actualName);
0825: pDef.setOnDemand(true);
0826: }
0827: }
0828:
0829: //update the control type
0830: Attribute contNode = ele.attribute("controlType");
0831: if (contNode != null) {
0832: String contVal = contNode.getValue();
0833: pDef.setControlType(contVal);
0834: }
0835:
0836: //update progID
0837: Attribute progNode = ele.attribute("progID");
0838: if (progNode != null) {
0839: String progVal = progNode.getValue();
0840: pDef.setProgID(progVal);
0841: }
0842: }
0843:
0844: // catch all to process any other attributes not listed here
0845: processAttributes(pNode, pDef);
0846: } catch (Exception e) {
0847: }
0848: }
0849:
0850: /**
0851: * Build the help string for the property definition based on the "get" function
0852: *
0853: * @param[in] pDef The property definition to add the help information to
0854: * @param[in] pDisp The IDispatch to obtain the help information from
0855: * @param[in] funcName The function whose help documentation we are getting
0856: *
0857: * @return HRESULT
0858: *
0859: */
0860: private void buildHelpDocumentation(IPropertyDefinition pDef,
0861: Object pDisp, String funcName) {
0862: if (funcName != null) {
0863: pDef.setHelpDescription(funcName);
0864: } else {
0865: // just set it to the class name.
0866: pDef.setHelpDescription(pDisp.getClass().getName());
0867: }
0868: //Sumitabh might have to get it from getElementTypeDocMap?
0869: }
0870:
0871: /**
0872: * Initialize the factory
0873: */
0874: public void initialize() {
0875:
0876: }
0877:
0878: /**
0879: * Get the Method that matches the passed-in method name and parmType list in passed pDisp.
0880: *
0881: * @param[in] pDisp The IDispatch to obtain the function information from
0882: * @param[in] memID The ID of the function that we are looking for
0883: * @param[out] pVal The IDispatch of the found function
0884: *
0885: * @return HRESULT
0886: *
0887: */
0888: public Object getFromFunctionMap(Object pDisp, String methName,
0889: String[] parmTypes) {
0890: Method func = null;
0891: try {
0892: Class clazz = pDisp.getClass();
0893: Class[] parms = null;
0894: if (parmTypes != null && parmTypes.length > 0) {
0895: parms = new Class[parmTypes.length];
0896: for (int i = 0; i < parmTypes.length; i++) {
0897: parms[i] = Class.forName(parmTypes[i]);
0898: }
0899: }
0900: func = clazz.getMethod(methName, parms);
0901: } catch (Exception e) {
0902: }
0903: return func;
0904: }
0905:
0906: /**
0907: * Retrieve documentation information from an already built map based on Object type
0908: */
0909: public void getFromElementTypeDocMap(Object pDisp, String pVal) {
0910:
0911: }
0912:
0913: /**
0914: * Gets the xml file that defines the property definitions
0915: */
0916: public String getDefinitionFile() {
0917: return m_definitionFile;
0918: }
0919:
0920: /**
0921: * Gets the xml file that defines the property definitions
0922: */
0923: public void setDefinitionFile(String value) {
0924: m_definitionFile = value;
0925: }
0926:
0927: /**
0928: * There were some cases where the property definitions are contained in a file, and we want them
0929: * all to be built at once. The property editor builds them as it needs to, the preference manager
0930: * just builds them all at once.
0931: *
0932: * The file needs to have already been set before calling this function.
0933: *
0934: * @param pVal[out] The property definitions that were built
0935: *
0936: * @return HRESULT
0937: *
0938: */
0939: public Vector<IPropertyDefinition> buildDefinitionsUsingFile() {
0940: Vector<IPropertyDefinition> vec = new Vector<IPropertyDefinition>();
0941: try {
0942: if (m_definitionFile != null
0943: && m_definitionFile.length() > 0) {
0944: ETSystem.out.println(m_definitionFile);
0945: Document doc = XMLManip
0946: .getDOMDocument(m_definitionFile);
0947: if (doc != null) {
0948: // loop through all property definitions and build them
0949: // wanted to use existing "create" code, so we just get the name
0950: // of the property definition and then ask the same mechanism that
0951: // was used for the property editor
0952: String pattern = "//PropertyDefinition";
0953: List list = doc.selectNodes(pattern);
0954: //List list = XPathAPI.selectNodeList(doc, pattern);
0955: if (list != null && list.size() > 0) {
0956:
0957: //just go through all PropertyDefinition nodes and store the name
0958: // and id in a hashtable.
0959: for (int i = 0; i < list.size(); i++) {
0960: Node node = (Node) list.get(i);
0961: if (node.getNodeType() == Node.ELEMENT_NODE) {
0962: String name = ((org.dom4j.Element) node)
0963: .attributeValue("name");
0964: String id = ((org.dom4j.Element) node)
0965: .attributeValue("id");
0966: addToNodeMap(node, id);
0967: addToNamedNodeMap(node, name);
0968: }
0969: }
0970:
0971: for (int i = 0; i < list.size(); i++) {
0972: Node node = (Node) list.get(i);
0973: Node nameNode = XMLManip.getAttribute(node,
0974: "name");
0975: //Node nameNode = XPathAPI.selectSingleNode(node, "@name");
0976: if (nameNode != null) {
0977: IPropertyDefinition def = getPropertyDefinitionForElement(
0978: nameNode.getStringValue(), null);
0979: if (def != null) {
0980: vec.add(def);
0981: }
0982: }
0983: }
0984: }
0985: }
0986: }
0987: } catch (Exception e) {
0988: e.printStackTrace();
0989: }
0990:
0991: return vec;
0992: }
0993:
0994: /**
0995: * The property definition can have several values for its "values" field: it can be
0996: * a hardcoded string ("public|private"), a string ("FormatString"), a xpath query(#//UML:Class/@name),
0997: * or an xpath query plus file (Languages.etc#//Language/@type).
0998: *
0999: * This method interprets the value and fills in the appropriate information
1000: *
1001: *
1002: * @param pVal[in] String stored in definition attribute "values"
1003: * @param pDef[in] property definition to process
1004: *
1005: * @return
1006: *
1007: */
1008: private void processValues(String pVal, IPropertyDefinition pDef) {
1009: //only do something if pVal has some value
1010: if (pVal != null && pVal.length() > 0) {
1011: // if it has a "#" in it, then this is an xpath query
1012: // it could either be a xpath query on a given file
1013: // or an empty file means perform the query on the current project
1014: int pos = pVal.indexOf("#");
1015: if (pos >= 0) {
1016: // have found a #, but now need to check if it is a protected value in a list
1017: int pos2 = pVal.indexOf("|#|");
1018: if (pos2 >= 0) {
1019: pDef.setValidValues2(pVal);
1020: } else {
1021: // this is a # in a string that should represent a file and an xpath
1022: String[] strs = pVal.split("#");
1023: if (strs != null && strs.length > 1) {
1024: String fileName = strs[0];
1025: String xpath = strs[1];
1026: if (fileName.length() > 0) {
1027: //Sumitabh use IConfigManager to get the document using home etc.
1028:
1029: String configLoc = ProductRetriever
1030: .retrieveProduct()
1031: .getConfigManager()
1032: .getDefaultConfigLocation();
1033: //m_ConMan.getDefaultConfigLocation();
1034: configLoc += fileName;
1035: Document doc = XMLManip
1036: .getDOMDocument(configLoc);
1037: if (doc != null) {
1038: try {
1039: List list = XMLManip
1040: .selectNodeList(doc, xpath);
1041: if (list != null && list.size() > 0) {
1042: String val = "";
1043: for (int i = 0; i < list.size(); i++) {
1044: Node lNode = (Node) list
1045: .get(i);
1046: if (val.length() > 0)
1047: val += "|";
1048: val += lNode
1049: .getStringValue();
1050: }
1051: pDef.setValidValues2(val);
1052: }
1053: } catch (Exception e) {
1054: }
1055: }
1056: } else {
1057: // we do not have a file, so our requirements are to search the current project
1058: // unfortunately at this time, we do not have that information
1059: // the values for the property definition will have to be built at a later time
1060: }
1061: }
1062: }
1063: } else {
1064: // the values string did not contain any xpath stuff
1065: // so check for other known values
1066: pos = pVal.indexOf("FormatString");
1067: if (pos >= 0) {
1068: // the definition has been marked to contain a format string
1069: // unfortunately at this time, we do not have that information
1070: // the values for the property definition will have to be built at a later time
1071: } else {
1072: pos = pVal.indexOf("::");
1073: if (pos >= 0) {
1074: // the definition has an object and a method stored in it that needs to be
1075: // created and then invoked in order to have the value
1076: String[] strs = pVal.split("::");
1077: if (strs != null && strs.length > 1) {
1078: //first element will be object name and second will be method name
1079: String objName = strs[0];
1080: String methName = strs[1];
1081: if (objName.length() > 0
1082: && methName.length() > 0) {
1083: Object objInstance = null;
1084: if (objName
1085: .equals("org.netbeans.modules.uml.core.metamodel.core.foundation.ConfigManager") == true) {
1086: objInstance = retrieveConfigManagerAsObject();
1087: } else if (objName
1088: .equals("org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.LanguageManager") == true) {
1089: objInstance = retrieveLanguageManagerAsObject();
1090: }
1091:
1092: //now invoke this method on this object and get the result -
1093: //these are values
1094: try {
1095: objInstance = retrieveObject(objName);
1096: // Class clazz = Class.forName(objName);
1097: // objInstance = clazz.newInstance();
1098:
1099: if (objInstance != null) {
1100: //Sumitabh need to figure out the parameters - may be we need third
1101: //parameter in pVal :: separated.
1102: Method meth = objInstance
1103: .getClass().getMethod(
1104: methName,
1105: (Class[]) null);
1106:
1107: Object obj = meth.invoke(
1108: objInstance,
1109: (Object[]) null);
1110: if (obj != null) {
1111: //if (obj.getClass().getName().equals("java.lang.String"))
1112: pDef.setValidValues(obj
1113: .toString());
1114: pDef.setValidValues2(obj
1115: .toString());
1116: }
1117: }
1118: } catch (Exception e) {
1119: //e.printStackTrace();
1120: }
1121: }
1122: }
1123: } else
1124: pDef.setValidValues2(pVal);
1125: }
1126: }
1127: }
1128: }
1129:
1130: protected Object retrieveConfigManagerAsObject() {
1131: Object retVal = null;
1132:
1133: ICoreProduct product = ProductRetriever.retrieveProduct();
1134: if (product != null) {
1135: retVal = product.getConfigManager();
1136: }
1137:
1138: return retVal;
1139: }
1140:
1141: protected Object retrieveLanguageManagerAsObject() {
1142: Object retVal = null;
1143:
1144: ICoreProduct product = ProductRetriever.retrieveProduct();
1145: if (product != null) {
1146: retVal = product.getLanguageManager();
1147: }
1148:
1149: return retVal;
1150: }
1151:
1152: protected Object retrieveObject(String objName)
1153: throws ClassNotFoundException, InstantiationException,
1154: IllegalAccessException {
1155: Object retVal = null;
1156:
1157: ICoreProduct product = ProductRetriever.retrieveProduct();
1158: if (product != null) {
1159: Class clazz = Class.forName(objName);
1160: retVal = clazz.newInstance();
1161: }
1162:
1163: return retVal;
1164: }
1165:
1166: /**
1167: * Gets the xml document that defines the property definitions
1168: */
1169: public Document getXMLDocument() {
1170: return m_Doc;
1171: }
1172:
1173: /**
1174: * Gets the xml document that defines the property definitions
1175: */
1176: public void setXMLDocument(Document value) {
1177: m_Doc = value;
1178: }
1179:
1180: /**
1181: * Retrieve or create the proper property definition for the passed-in name.
1182: *
1183: * @param[in] eleStr The name of the property definition
1184: * @param[out] pVal The property definition that has been created or found
1185: *
1186: * @return HRESULT
1187: *
1188: */
1189: public IPropertyDefinition getPropertyDefinitionByName(String name) {
1190: IPropertyDefinition def = null;
1191: if (name != null && name.length() > 0) {
1192: def = getFromDefinitionMap(name);
1193: if (def == null) {
1194: if (m_NoDefinitionSet.contains(name)) {
1195: return null;
1196: }
1197: def = createDefinition(name);
1198: }
1199: if (def != null) {
1200: addToDefinitionMap(name, def);
1201: } else {
1202: m_NoDefinitionSet.add(name);
1203: }
1204: }
1205: return def;
1206: }
1207:
1208: /**
1209: * Given a xml node, build the corresponding property definition
1210: *
1211: *
1212: * @param pNode[in] The node for which we want to build a definition
1213: * @param pDef[out] The newly created definition
1214: *
1215: * @return HRESULT
1216: *
1217: */
1218: public IPropertyDefinition buildDefinitionFromNode(Node pNode) {
1219: IPropertyDefinition def = null;
1220: if (pNode != null) {
1221: Document doc = pNode.getDocument();
1222: setXMLDocument(doc);
1223: def = new PropertyDefinition();
1224: setAttributes(pNode, def);
1225: processSubDefinitions(pNode, def);
1226: }
1227: return def;
1228: }
1229:
1230: /**
1231: * Given a xml node, build the corresponding property definition
1232: *
1233: *
1234: * @param pNode[in] The node for which we want to build a definition
1235: * @param pDef[out] The newly created definition
1236: *
1237: * @return HRESULT
1238: *
1239: */
1240: public IPropertyDefinition buildDefinitionFromString(String str) {
1241: IPropertyDefinition def = null;
1242: try {
1243: if (str != null && str.length() > 0) {
1244: Document doc = XMLManip.getDOMDocumentFromString(str);
1245: if (doc != null) {
1246: String pattern = "PropertyDefinition";
1247: List list = doc.selectNodes(pattern);
1248: if (list != null && list.size() > 0) {
1249: Node n = (Node) list.get(0);
1250: //Node n = XPathAPI.selectSingleNode(doc, pattern);
1251: if (n != null) {
1252: def = new PropertyDefinition();
1253: setAttributes(n, def);
1254: processSubDefinitions(n, def);
1255: }
1256: }
1257: }
1258: }
1259: } catch (Exception e) {
1260: }
1261: return def;
1262: }
1263:
1264: /**
1265: * Find the xml dom node that defines the passed in value. The definition file is created based on element
1266: * type.
1267: *
1268: * @param[in] name The element type
1269: * @param[out] pVal The dom node in the definition file matching the element type
1270: *
1271: * @return HRESULT
1272: *
1273: */
1274: private Node findPropertyDefinitionDOMNode(String name) {
1275: Node node = null;
1276: try {
1277: if (name != null && name.length() > 0) {
1278: if (m_NamedNodeMap != null) {
1279: node = getFromNamedNodeMap(name);
1280: }
1281: if (node == null) {
1282: if (m_Doc != null) {
1283: String pattern = "//PropertyDefinition[@name=\'";
1284: pattern += name;
1285: pattern += "\']";
1286: node = m_Doc.selectSingleNode(pattern);
1287: }
1288: }
1289: }
1290: } catch (Exception e) {
1291: }
1292: return node;
1293: }
1294:
1295: //used for building sub definitions.
1296: private Node findPropertyDefinitionDOMNodeForSubDef(String name) {
1297: Node retNode = getFromNodeMap(name);
1298: if (retNode == null) {
1299: retNode = m_Doc.elementByID(name);
1300: if (retNode != null) {
1301: addToNodeMap(retNode, name);
1302: }
1303: }
1304: return retNode;
1305: }
1306:
1307: /**
1308: * Build a property definition
1309: *
1310: * @param[in] name The element type
1311: * @param[out] pVal The property definition that was just built
1312: *
1313: * @return HRESULT
1314: *
1315: */
1316: private IPropertyDefinition createDefinition(String name) {
1317: IPropertyDefinition def = null;
1318: if (name != null && name.length() > 0) {
1319: try {
1320: if (m_definitionFile != null
1321: && m_definitionFile.length() > 0) {
1322: if (m_Doc == null) {
1323: m_Doc = XMLManip
1324: .getDOMDocument(m_definitionFile);
1325: }
1326: if (m_Doc != null) {
1327: Node domNode = findPropertyDefinitionDOMNode(name);
1328: if (domNode != null) {
1329: def = new PropertyDefinition();
1330: setAttributes(domNode, def);
1331: processSubDefinitions(domNode, def);
1332: addToNodeMap(domNode, name);
1333: }
1334: }
1335: }
1336: } catch (Exception e) {
1337: }
1338: }
1339: return def;
1340: }
1341: }
|