001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.uml.core.support.umlutils;
043:
044: import java.util.List;
045: import java.util.Hashtable;
046: import java.util.Vector;
047:
048: import org.dom4j.Document;
049: import org.dom4j.Node;
050:
051: import org.netbeans.modules.uml.core.coreapplication.CoreProductManager;
052: import org.netbeans.modules.uml.core.coreapplication.ICoreProduct;
053: import org.netbeans.modules.uml.core.metamodel.core.foundation.IConfigManager;
054: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
055: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguage;
056: import org.netbeans.modules.uml.core.support.umlsupport.XMLManip;
057:
058: /**
059: * @author sumitabhk
060: *
061: */
062: public class PropertyDefinitionFilter implements
063: IPropertyDefinitionFilter {
064: private String m_FilterFile = null;
065: private Hashtable<String, Document> m_LoadedDocs = new Hashtable<String, Document>();
066:
067: /**
068: *
069: */
070: public PropertyDefinitionFilter() {
071: super ();
072: m_FilterFile = "";
073: }
074:
075: /**
076: * Apply language specific filters to the passed in property element structure.
077: * This may remove some property elements, rename some, change their values, etc.
078: *
079: * The filters that are used will be based on the element on this property element.
080: *
081: * @param pEle[in] The property element to apply the filter to
082: *
083: * @return HRESULT
084: */
085: public long filterPropertyElement(IPropertyElement pEle) {
086: Object obj = pEle.getElement();
087: if (obj != null) {
088: // is it a model element
089: if (obj instanceof IElement) {
090: IElement pElement = (IElement) obj;
091:
092: // from the element we should be able to tell what language it is
093: ILanguage lang = getActiveLanguage(pElement);
094: if (lang != null) {
095: // get the language name
096: String langName = lang.getName();
097: if (langName.length() > 0) {
098: filterPropertyElement(pEle, langName);
099: }
100: }
101: }
102: }
103: return 0;
104: }
105:
106: /**
107: * Apply language specific filters to the passed in property element structure.
108: * This may remove some property elements, rename some, change their values, etc.
109: *
110: * The filters that are used will be based on the passed in language
111: *
112: * @param pEle[in] The property element to apply the filter to
113: * @param sLang[in] The language to use as the filter
114: *
115: * @return HRESULT
116: *
117: */
118: private void filterPropertyElement(IPropertyElement pEle,
119: String langName) {
120: // what filter file should we use
121: String file = getFilterFile();
122: if (file.length() > 0) {
123: // get the dom document for this file
124: Document doc = getDOMDocument(file);
125: if (doc != null) {
126: // get the node in the filter structure that matches this language
127: Node pLangNode = getLanguageFilterNode(doc, langName);
128: if (pLangNode != null) {
129: Object pDisp = pEle.getElement();
130: // is it a model element
131: if (pDisp != null && pDisp instanceof IElement) {
132: IElement pElement = (IElement) pDisp;
133:
134: // get all filter nodes that apply to the model element
135: // that we have
136: List list = getElementFilterNodes(pLangNode,
137: pElement);
138: if (list != null) {
139: for (int i = 0; i < list.size(); i++) {
140: Node pEleNode = (Node) list.get(i);
141:
142: // process anything that should be removed from the structure
143: processRemove(pEle, pEleNode);
144: // process anything that needs to be changed
145: processModify(pEle, pEleNode);
146: }
147: }
148: }
149: }
150: }
151: }
152: }
153:
154: /**
155: * caching reference to parsed file locally in the instance hash,
156: * so the lifecycle of the reference follow that of the instance
157: */
158: public Document getDOMDocument(String fileName) {
159: Document doc = null;
160: if (fileName != null && fileName.length() > 0) {
161: doc = m_LoadedDocs.get(fileName);
162: if (doc == null) {
163: doc = XMLManip.getDOMDocument(fileName);
164: m_LoadedDocs.put(fileName, doc);
165: }
166: }
167: return doc;
168: }
169:
170: /**
171: * Find the nodes in the passed in xml node that represent property elements that need to
172: * be changed in the current property element
173: *
174: *
175: * @param pEle[in] The current property element
176: * @param pNode[in] The node that houses any "modify" nodes
177: *
178: * @return HRESULT
179: *
180: */
181: private void processModify(IPropertyElement pEle, Node pEleNode) {
182: // find all of the filter op nodes of type "modify"
183: String pattern = "FilterOp[@name = \'modify\']";
184: List nodeList = pEleNode.selectNodes(pattern);
185:
186: if (nodeList != null) {
187: int count = nodeList.size();
188: for (int i = 0; i < count; i++) {
189: Node pModifyNode = (Node) nodeList.get(i);
190:
191: // get the attribute on this filter op node of type xpath
192: // this represents the name of the property element
193: String pattern2 = "@xpath";
194: Node nameNode = pModifyNode.selectSingleNode(pattern2);
195: if (nameNode != null) {
196: // have the "name" of the property element that needs to be changed
197: String name = nameNode.getText();
198:
199: //
200: // loop through the sub elements of the passed in element
201: // and when we find a match on name, change it
202: //
203: Vector<IPropertyElement> subElems = pEle
204: .getSubElements();
205: if (subElems != null) {
206: int eleCount = subElems.size();
207: for (int j = 0; j < eleCount; j++) {
208: IPropertyElement subEle = subElems
209: .elementAt(j);
210: String defName = subEle.getName();
211: if (defName != null && defName.equals(name)) {
212: // right now the only change that we are doing is changing
213: // the picklist values, which are housed on the property definition
214: // so reset that
215: IPropertyDefinition pDef = subEle
216: .getPropertyDefinition();
217: if (pDef != null) {
218: String pattern3 = "@values";
219: Node valueNode = pModifyNode
220: .selectSingleNode(pattern3);
221: if (valueNode != null) {
222: String value = valueNode
223: .getText();
224: if (value != null) {
225: pDef.setValidValues(value);
226: }
227: }
228: }
229: break;
230: }
231: }
232: }
233: }
234: }
235: }
236: }
237:
238: /**
239: * Find the nodes in the passed in xml node that represent property elements that need to
240: * be removed from the current property element
241: *
242: *
243: * @param pEle[in] The current property element
244: * @param pNode[in] The node that houses any "remove" nodes
245: *
246: * @return HRESULT
247: *
248: */
249: private void processRemove(IPropertyElement pEle, Node pEleNode) {
250: // find all of the filter op nodes of type "remove"
251: String pattern = "FilterOp[@name = \'remove\']";
252:
253: List list = pEleNode.selectNodes(pattern);
254: if (list != null) {
255: int count = list.size();
256: for (int i = 0; i < count; i++) {
257: Node pRemoveNode = (Node) list.get(i);
258:
259: // get the attribute on this filter op node of type xpath
260: // this represents the name of the property element
261: String pattern2 = "@xpath";
262:
263: Node pNameNode = pRemoveNode.selectSingleNode(pattern2);
264: if (pNameNode != null) {
265: // have the "name" of the property element that needs to be removed
266: String name = pNameNode.getText();
267:
268: //
269: // loop through the sub elements of the passed in element
270: // and when we find a match on name, remove it
271: //
272: Vector<IPropertyElement> subEles = pEle
273: .getSubElements();
274: if (subEles != null) {
275: int subCount = subEles.size();
276: for (int j = 0; j < subCount; j++) {
277: IPropertyElement elem = subEles
278: .elementAt(j);
279: String defName = elem.getName();
280: if (defName.equals(name)) {
281: subEles.remove(j);
282: break;
283: }
284: }
285: }
286: }
287: }
288: }
289: }
290:
291: /* (non-Javadoc)
292: * @see org.netbeans.modules.uml.core.support.umlutils.IPropertyDefinitionFilter#filterPropertyElementBasedOnLanguage(org.netbeans.modules.uml.core.support.umlutils.IPropertyElement, java.lang.String)
293: */
294: public long filterPropertyElementBasedOnLanguage(
295: IPropertyElement pEle, String sLang) {
296: // TODO Auto-generated method stub
297: return 0;
298: }
299:
300: /* (non-Javadoc)
301: * @see org.netbeans.modules.uml.core.support.umlutils.IPropertyDefinitionFilter#filterPropertyElementBasedOnModelElement(org.netbeans.modules.uml.core.support.umlutils.IPropertyElement, org.netbeans.modules.uml.core.metamodel.core.foundation.IElement)
302: */
303: public long filterPropertyElementBasedOnModelElement(
304: IPropertyElement pEle, IElement pElement) {
305: // TODO Auto-generated method stub
306: return 0;
307: }
308:
309: /**
310: * Gets the xml file that defines the property definition filters
311: *
312: * @param pVal
313: *
314: * @return HRESULT
315: *
316: */
317: public String getFilterFile() {
318: String file = null;
319: if (m_FilterFile.length() > 0) {
320: file = m_FilterFile;
321: } else {
322: // no file specified, so use the one in the config location
323: // will eventually go to preferences to get this, but for now just hardcode
324: ICoreProduct prod = CoreProductManager.instance()
325: .getCoreProduct();
326: if (prod != null) {
327: IConfigManager conMan = prod.getConfigManager();
328: if (conMan != null) {
329: String home = conMan.getDefaultConfigLocation();
330: file = home;
331: file += "PropertyDefinitionFilters.etc";
332: }
333: }
334: }
335: return file;
336: }
337:
338: /**
339: * Sets the xml file that defines the property definition filters
340: *
341: * @param newVal
342: *
343: * @return HRESULT
344: *
345: */
346: public void setFilterFile(String value) {
347: m_FilterFile = value;
348: }
349:
350: /* (non-Javadoc)
351: * @see org.netbeans.modules.uml.core.support.umlutils.IPropertyDefinitionFilter#filterPropertyElementBasedOnFilterName(org.netbeans.modules.uml.core.support.umlutils.IPropertyElement, java.lang.String)
352: */
353: public long filterPropertyElementBasedOnFilterName(
354: IPropertyElement pEle, String sName) {
355: // TODO Auto-generated method stub
356: return 0;
357: }
358:
359: /**
360: * Retrieves a model elements associated language. If the model element
361: * is associated to more than one language then the first language is the
362: * active language.
363: *
364: * @param pElement [in] The element being processed.
365: * @param pVal [out] The active language for the element.
366: */
367: private ILanguage getActiveLanguage(IElement pElement) {
368: ILanguage retLang = null;
369: // Find the first language that is supported by the element. If the
370: // is not supporting any languages (Should never happen) get the
371: // default langauge.
372: ETList<ILanguage> langs = pElement.getLanguages();
373: // if (langs != null && langs.length > 0)
374: if (langs != null && langs.size() > 0) {
375: retLang = langs.get(0);
376: }
377: return retLang;
378: }
379:
380: /**
381: * Gets a node from the xml document based on its name (language)
382: *
383: *
384: * @param pDoc[in] The xml document to search
385: * @param sLang[in] The language string to look for
386: * @param pNode[out] The found language xml node
387: *
388: * @return HRESULT
389: *
390: */
391: private Node getLanguageFilterNode(Document doc, String langName) {
392: // find the node that matches the passed in language
393: String pattern = "//Filter[@name = \'";
394: pattern += langName;
395: pattern += "\']";
396: Node n = doc.selectSingleNode(pattern);
397: return n;
398: }
399:
400: /**
401: * Get all of the xml nodes that apply to the passed in element
402: *
403: *
404: * @param pNode[in] The xml node whose children need to be searched
405: * @param pElement[in] The model element to process
406: * @param pFrag[in] The xml fragment housing the nodes that match the criteria for the element
407: *
408: * @return HRESULT
409: *
410: */
411: private List getElementFilterNodes(Node pLangNode, IElement pElement) {
412: List newList = new Vector();
413: // find all of the filter element nodes
414: String pattern = "FilterElement";
415: List list = pLangNode.selectNodes(pattern);
416: if (list != null) {
417: for (int i = 0; i < list.size(); i++) {
418: Node node = (Node) list.get(i);
419:
420: // get the attribute on the node that is the type attribute
421: // this will be the progID that the model element must support in order for the
422: // filter element node to apply to the model element
423: String pattern2 = "@type";
424: Node pTypeNode = node.selectSingleNode(pattern2);
425: if (pTypeNode != null) {
426: String uuid = pTypeNode.getText();
427: if (uuid.length() > 0) {
428: try {
429: Class clazz = Class.forName(uuid);
430: if (clazz.isInstance(pElement)) {
431: newList.add(node);
432: }
433: } catch (Exception e) {
434: }
435: }
436: }
437: }
438: }
439: return newList;
440: }
441:
442: }
|