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.compapp.casaeditor.nodes;
043:
044: import java.util.Collections;
045: import java.util.Comparator;
046: import java.util.HashMap;
047: import java.util.HashSet;
048: import java.util.List;
049: import java.util.Map;
050: import java.util.Set;
051: import java.util.logging.Logger;
052: import javax.xml.namespace.QName;
053: import org.netbeans.modules.compapp.casaeditor.model.casa.CasaComponent;
054: import org.netbeans.modules.compapp.casaeditor.model.casa.CasaComponentFactory;
055: import org.netbeans.modules.compapp.casaeditor.model.casa.CasaExtensibilityElement;
056: import org.netbeans.modules.compapp.casaeditor.model.casa.CasaWrapperModel;
057: import org.netbeans.modules.compapp.casaeditor.properties.PropertyUtils;
058: import org.netbeans.modules.compapp.projects.jbi.api.JbiChoiceExtensionElement;
059: import org.netbeans.modules.compapp.projects.jbi.api.JbiExtensionAttribute;
060: import org.netbeans.modules.compapp.projects.jbi.api.JbiExtensionElement;
061: import org.netbeans.modules.compapp.projects.jbi.api.JbiExtensionInfo;
062: import org.netbeans.modules.compapp.projects.jbi.api.JbiInstalledExtensionInfo;
063: import org.openide.nodes.Sheet;
064: import org.w3c.dom.Document;
065: import org.w3c.dom.Element;
066:
067: /**
068: * Helper class to set up property sheet for CASA conriguraton extensions.
069: *
070: * @author jqian
071: */
072: public class ExtensionPropertyHelper {
073:
074: private static Logger logger = Logger
075: .getLogger("org.netbeans.modules.compapp.casaeditor.nodes.ExtensionPropertyHelper"); // NOI18N
076:
077: private static String EXTENSION_TARGET_ALL = "all"; // NOI18N
078:
079: /**
080: * Sets up property sheet for a CASA extension point component's
081: * extensibility elements.
082: *
083: * @param node a CASA node
084: * @param casaExtPoint a CASA component which is an extension point,
085: * for example, casa:connection
086: * @param sheet the overall property sheet
087: * @param extensionType the type of the extension,
088: * e.x., "endpoint" or "connection"
089: * @param extensionTarget target of the extension,
090: * e.x., "sun-http-binding" or "all"
091: */
092: public static void setupExtensionPropertySheet(CasaNode node,
093: CasaComponent casaExtPoint, Sheet sheet,
094: String extensionType, String extensionTarget) {
095:
096: JbiInstalledExtensionInfo installedExtInfo = JbiInstalledExtensionInfo
097: .getInstalledExtensionInfo();
098:
099: Document document = casaExtPoint.getPeer().getOwnerDocument();
100:
101: // Assumptions:
102: // * Each extension (subtree) in the CASA model is either complete or
103: // doesn't exist at all.
104:
105: Set<QName> existingTopEEQNames = new HashSet<QName>();
106:
107: // 1. for top level extensibility elements existing in the CASA model
108: for (CasaExtensibilityElement ee : casaExtPoint
109: .getExtensibilityElements()) {
110: // ee: <config:application-config name="FOO"/>
111: QName eeQName = ee.getQName();
112:
113: existingTopEEQNames.add(eeQName);
114:
115: String eeNamespace = eeQName.getNamespaceURI();
116: String eeLocalName = eeQName.getLocalPart();
117:
118: List<JbiExtensionInfo> extInfoList = installedExtInfo
119: .getJbiExtensionList();
120: Collections.sort(extInfoList,
121: new Comparator<JbiExtensionInfo>() {
122: public int compare(JbiExtensionInfo o1,
123: JbiExtensionInfo o2) {
124: return o1.getName().compareTo(o2.getName());
125: }
126: });
127:
128: for (JbiExtensionInfo extInfo : extInfoList) {
129: if (!(extInfo.getNameSpace().equals(eeNamespace))
130: || !(extensionType.equals(extInfo.getType()))) {
131: continue;
132: }
133:
134: String extInfoTarget = extInfo.getTarget();
135: if (!(extensionTarget.equals(extInfoTarget))
136: && !(EXTENSION_TARGET_ALL.equals(extInfoTarget))) {
137: continue;
138: }
139:
140: String namespace = extInfo.getNameSpace();
141:
142: for (JbiExtensionElement extElement : extInfo
143: .getElements()) {
144: if (extElement.getName().equals(eeLocalName)) {
145: Sheet.Set extPropertySet = node.getPropertySet(
146: sheet, extInfo.getName());
147: createExistingProperties(node, document,
148: extElement, extPropertySet,
149: casaExtPoint, ee, ee, namespace);
150: break;
151: }
152: }
153: }
154: }
155:
156: // 2. for top level extensibility elements that do not exist
157: // in the CASA model yet
158: for (JbiExtensionInfo extInfo : installedExtInfo
159: .getJbiExtensionList()) {
160: logger.fine(extInfo.toString());
161:
162: if (!(extensionType.equals(extInfo.getType()))) {
163: continue;
164: }
165:
166: String extInfoTarget = extInfo.getTarget();
167: if (!(extensionTarget.equals(extInfoTarget))
168: && !(EXTENSION_TARGET_ALL.equals(extInfoTarget))) {
169: continue;
170: }
171:
172: // For each extension, create a new property sheet
173: Sheet.Set extPropertySet = node.getPropertySet(sheet,
174: extInfo.getName());
175:
176: String namespace = extInfo.getNameSpace();
177:
178: for (JbiExtensionElement extElement : extInfo.getElements()) {
179: QName qname = new QName(namespace, extElement.getName());
180: if (!existingTopEEQNames.contains(qname)) {
181: // extElement doesn't have a corresponding CASA
182: // extensibility element yet
183: createNonExistingProperties(node, document,
184: extElement, extPropertySet, casaExtPoint,
185: null, null, namespace, true);
186: }
187: }
188: }
189: }
190:
191: /**
192: * Creates a CASA extensibility element for the given
193: * <code>JbiExtensionElement</code> instance; installs attribute properties
194: * and choice properties into the node's property sheet.
195: *
196: * @param node
197: * @param document
198: * @param extElement
199: * @param extSheetSet
200: * @param casaExtPoint
201: * @param firstEE
202: * @param lastEE
203: * @param namespace
204: * @param install whether to install properties for attributes of the
205: * current or descendent JbiExtensionElements into
206: * the property sheet
207: *
208: * @return a newly constructed extensibility element
209: */
210: private static CasaExtensibilityElement createNonExistingProperties(
211: CasaNode node, Document document,
212: JbiExtensionElement extElement, Sheet.Set extSheetSet,
213: CasaComponent casaExtPoint,
214: CasaExtensibilityElement firstEE,
215: CasaExtensibilityElement lastEE, String namespace,
216: boolean install) {
217:
218: CasaWrapperModel casaModel = (CasaWrapperModel) casaExtPoint
219: .getModel();
220: CasaComponentFactory casaFactory = casaModel.getFactory();
221:
222: String extElementName = extElement.getName();
223: String extElementDescription = extElement.getDescription();
224: Element domElement = document.createElementNS(namespace,
225: extElementName);
226:
227: CasaExtensibilityElement newEE = (CasaExtensibilityElement) casaFactory
228: .create(domElement, casaExtPoint);
229:
230: if (firstEE == null) {
231: firstEE = newEE;
232: }
233:
234: if (lastEE != null) {
235: lastEE.addAnyElement(newEE, lastEE.getAnyElements().size());
236: }
237: lastEE = newEE;
238:
239: if (extElement instanceof JbiChoiceExtensionElement) {
240: // Note that multi-level choice element is not supported for now.
241:
242: JbiChoiceExtensionElement choiceExtElement = (JbiChoiceExtensionElement) extElement;
243: String defaultChoice = choiceExtElement.getDefaultChoice();
244:
245: // Build choice map.
246: Map<String, CasaExtensibilityElement> choiceMap = new HashMap<String, CasaExtensibilityElement>();
247: for (JbiExtensionElement childElement : extElement
248: .getElements()) {
249: CasaExtensibilityElement childEE = createNonExistingProperties(
250: node, document, childElement, extSheetSet,
251: lastEE, null, null, namespace, false);
252: choiceMap.put(childElement.getName(), childEE);
253: }
254:
255: // Add an artificial property for the choice extension element.
256: PropertyUtils.installChoiceExtensionProperty(extSheetSet,
257: node, casaExtPoint, firstEE, lastEE,
258: CasaNode.ALWAYS_WRITABLE_PROPERTY, String.class,
259: extElementName, extElementName,
260: extElementDescription, choiceMap, defaultChoice);
261:
262: } else {
263: // Add properties for attributes of the current extenstion element.
264: List<JbiExtensionAttribute> attributes = extElement
265: .getAttributes();
266: if (attributes != null) {
267: for (JbiExtensionAttribute attr : extElement
268: .getAttributes()) {
269: String attrName = attr.getName();
270: String attrType = attr.getType();
271: String attrDescription = attr.getDescription();
272: boolean codeGen = attr.getCodeGen();
273:
274: if (codeGen) {
275: lastEE.setAttribute(attrName, ""); // NOI18N
276: }
277:
278: if (install) {
279: PropertyUtils.installExtensionProperty(
280: extSheetSet, node, casaExtPoint,
281: firstEE, lastEE,
282: CasaNode.ALWAYS_WRITABLE_PROPERTY,
283: attrType, attrName, attrName,
284: attrDescription);
285: }
286: }
287: }
288:
289: // Add properties for child extension elements.
290: List<JbiExtensionElement> childExtElements = extElement
291: .getElements();
292: if (childExtElements != null) {
293: for (JbiExtensionElement childElement : childExtElements) {
294: createNonExistingProperties(node, document,
295: childElement, extSheetSet, casaExtPoint,
296: firstEE, lastEE, namespace, true);
297: }
298: }
299: }
300:
301: return newEE;
302: }
303:
304: private static void createExistingProperties(CasaNode node,
305: Document document, JbiExtensionElement extElement,
306: Sheet.Set extSheetSet, CasaComponent casaExtPoint,
307: CasaExtensibilityElement firstEE,
308: CasaExtensibilityElement lastEE, String namespace) {
309:
310: // Add a property for choice extension element.
311: if (extElement instanceof JbiChoiceExtensionElement) {
312:
313: JbiChoiceExtensionElement choiceExtElement = (JbiChoiceExtensionElement) extElement;
314: String defaultChoice = choiceExtElement.getDefaultChoice();
315:
316: String elementName = extElement.getName();
317: String elementDescription = extElement.getDescription();
318:
319: List<CasaExtensibilityElement> currentChildren = lastEE
320: .getExtensibilityElements();
321: if (currentChildren != null && currentChildren.size() > 0) {
322: assert currentChildren != null
323: && currentChildren.size() == 1;
324: CasaExtensibilityElement currentChild = currentChildren
325: .get(0);
326: String currentChildName = currentChild.getQName()
327: .getLocalPart();
328:
329: // Build choice map.
330: Map<String, CasaExtensibilityElement> choiceMap = new HashMap<String, CasaExtensibilityElement>();
331: List<JbiExtensionElement> childExtElements = extElement
332: .getElements();
333: if (childExtElements != null) {
334: // Add potential children
335: for (JbiExtensionElement childElement : childExtElements) {
336: String childElementName = childElement
337: .getName();
338: if (!childElementName.equals(currentChildName)) {
339: CasaExtensibilityElement childEE = createNonExistingProperties(
340: node, document, childElement,
341: extSheetSet, casaExtPoint, null,
342: null, namespace, false);
343: choiceMap.put(childElementName, childEE);
344: }
345: }
346:
347: // Add current child
348: CasaExtensibilityElement clonedExistingChildEE = (CasaExtensibilityElement) currentChild
349: .copy(lastEE);
350: choiceMap.put(currentChildName,
351: clonedExistingChildEE);
352: }
353:
354: // Add an artificial property for the choice extension element.
355: PropertyUtils.installChoiceExtensionProperty(
356: extSheetSet, node, casaExtPoint, firstEE,
357: lastEE, CasaNode.ALWAYS_WRITABLE_PROPERTY,
358: String.class, elementName, elementName,
359: elementDescription, choiceMap, defaultChoice);
360: }
361: }
362:
363: // Add properties for attributes of the current extenstion element.
364: List<JbiExtensionAttribute> attributes = extElement
365: .getAttributes();
366: if (attributes != null) {
367: for (JbiExtensionAttribute attr : attributes) {
368: String attrName = attr.getName();
369: String attrType = attr.getType();
370: String attrDescription = attr.getDescription();
371: PropertyUtils.installExtensionProperty(extSheetSet,
372: node, casaExtPoint, firstEE, lastEE,
373: CasaNode.ALWAYS_WRITABLE_PROPERTY, attrType,
374: attrName, attrName, attrDescription);
375: }
376: }
377:
378: // Add properties for child extension elements.
379: List<JbiExtensionElement> childExtElements = extElement
380: .getElements();
381: if (childExtElements != null) {
382: for (CasaExtensibilityElement ee : lastEE
383: .getExtensibilityElements()) {
384: String eeName = ee.getPeer().getNodeName();
385: boolean found = false;
386: for (JbiExtensionElement childExtElement : childExtElements) {
387: if (eeName.equals(childExtElement.getName())) {
388: createExistingProperties(node, document,
389: childExtElement, extSheetSet,
390: casaExtPoint, firstEE, ee, namespace);
391: found = true;
392: break;
393: }
394: }
395: assert found;
396: }
397: }
398: }
399: }
|