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.xml.xam.ui.customizer;
043:
044: import java.io.IOException;
045: import org.netbeans.modules.xml.xam.Model;
046: import org.openide.loaders.DataObject;
047: import org.openide.nodes.FilterNode;
048: import org.openide.nodes.Node;
049: import org.netbeans.modules.xml.xam.ui.ModelCookie;
050: import org.openide.ErrorManager;
051: import org.openide.filesystems.FileObject;
052: import org.openide.nodes.Node.Property;
053: import org.openide.nodes.PropertySupport.Reflection;
054: import org.openide.nodes.Sheet;
055: import org.openide.nodes.Sheet.Set;
056: import org.openide.util.NbBundle;
057:
058: /**
059: * Represents a collection of external references, or a single file.
060: *
061: * @author Ajit Bhate
062: * @author Nathan Fiedler
063: */
064: public class ExternalReferenceDataNode extends FilterNode implements
065: ExternalReferenceNode {
066: /** Name of the 'selected' property. */
067: public static final String PROP_SELECTED = "selected";
068: /** Name of the 'prefix' property. */
069: public static final String PROP_PREFIX = "prefix";
070: /** Controls the appearance of this node. */
071: private ExternalReferenceDecorator decorator;
072: /** Set of PropertySets. */
073: private Sheet sheet;
074: /** True if selected, false otherwise. */
075: private boolean selected;
076: /** The namespace prefix, if specified. */
077: private String prefix;
078:
079: /**
080: * Creates a new instance of ExternalReferenceDataNode.
081: *
082: * @param original the delegate Node.
083: * @param decorator the external reference decorator.
084: */
085: public ExternalReferenceDataNode(Node original,
086: ExternalReferenceDecorator decorator) {
087: super (original, new Children(original, decorator));
088: this .decorator = decorator;
089: }
090:
091: public boolean canRename() {
092: // Disable rename as it serves no purpose here and makes the
093: // single-click-select-toggle difficult to use.
094: return false;
095: }
096:
097: /**
098: * Indicates if this node allows setting it selected.
099: *
100: * @return true if this node can be selected, false otherwise.
101: */
102: public boolean canSelect() {
103: DataObject dobj = (DataObject) getLookup().lookup(
104: DataObject.class);
105: return dobj != null && !dobj.getPrimaryFile().isFolder()
106: && decorator.validate(this ) == null;
107: }
108:
109: /**
110: * Creates a node property of the given key (same as the column keys)
111: * and specific getter/setter methods on the given object.
112: *
113: * @param key property name (same as matching column).
114: * @param type Class of the property (e.g. String.class).
115: * @param inst object on which to reflect.
116: * @param getter name of getter method for property value.
117: * @param setter name of setter method for property value (may be null).
118: * @return new property.
119: */
120: private Node.Property createProperty(String key, Class type,
121: Object inst, String getter, String setter) {
122: Property prop = null;
123: try {
124: prop = new Reflection(inst, type, getter, setter);
125: prop.setName(key);
126: prop.setDisplayName(NbBundle.getMessage(
127: ExternalReferenceDataNode.class,
128: "CTL_ExternalReferenceCreator_Column_Name_" + key));
129: prop.setShortDescription(NbBundle.getMessage(
130: ExternalReferenceDataNode.class,
131: "CTL_ExternalReferenceCreator_Column_Desc_" + key));
132: } catch (NoSuchMethodException nsme) {
133: ErrorManager.getDefault().notify(nsme);
134: }
135: return prop;
136: }
137:
138: protected Sheet createSheet() {
139: Sheet sheet = Sheet.createDefault();
140: Set set = sheet.get(Sheet.PROPERTIES);
141: set.put(createProperty(PROP_NAME, String.class, this ,
142: "getHtmlDisplayName", null));
143: if (canSelect()) {
144: set.put(createProperty(PROP_SELECTED, Boolean.TYPE, this ,
145: "isSelected", "setSelected"));
146: Node.Property prop = createProperty(PROP_PREFIX,
147: String.class, this , "getPrefix", "setPrefix");
148: // Suppress the [...] button because it is not needed.
149: prop.setValue("suppressCustomEditor", Boolean.TRUE);
150: set.put(prop);
151: } else {
152: // Do not include this property so the checkbox is not shown.
153: //set.put(createProperty(PROP_SELECTED, Boolean.TYPE, this,
154: // "isSelected", null));
155: Node.Property prop = createProperty(PROP_PREFIX,
156: String.class, this , "getPrefix", null);
157: // Suppress the [...] button because it is not needed.
158: prop.setValue("suppressCustomEditor", Boolean.TRUE);
159: set.put(prop);
160: }
161: return sheet;
162: }
163:
164: protected final synchronized Sheet getSheet() {
165: if (sheet != null) {
166: return sheet;
167: }
168: sheet = createSheet();
169: firePropertySetsChange(null, null);
170: return sheet;
171: }
172:
173: public PropertySet[] getPropertySets() {
174: Sheet s = getSheet();
175: return s.toArray();
176: }
177:
178: public String getHtmlDisplayName() {
179: String name = getOriginal().getHtmlDisplayName();
180: if (decorator != null) {
181: if (name == null) {
182: name = getDisplayName();
183: }
184: name = decorator.getHtmlDisplayName(name, this );
185: }
186: return name;
187: }
188:
189: public String getNamespace() {
190: DataObject dobj = (DataObject) getLookup().lookup(
191: DataObject.class);
192: if (dobj != null) {
193: ModelCookie cookie = (ModelCookie) dobj
194: .getCookie(ModelCookie.class);
195: if (cookie != null) {
196: try {
197: Model model = cookie.getModel();
198: return decorator.getNamespace(model);
199: } catch (IOException ioe) {
200: return null;
201: }
202: }
203: }
204: return null;
205: }
206:
207: public Model getModel() {
208: DataObject dobj = (DataObject) getLookup().lookup(
209: DataObject.class);
210: if (dobj != null) {
211: ModelCookie cookie = (ModelCookie) dobj
212: .getCookie(ModelCookie.class);
213: if (cookie != null) {
214: try {
215: return cookie.getModel();
216: } catch (IOException ioe) {
217: return null;
218: }
219: }
220: }
221: return null;
222: }
223:
224: public String getPrefix() {
225: if (prefix == null) {
226: prefix = decorator.generatePrefix(this );
227: }
228: return prefix;
229: }
230:
231: public boolean isSelected() {
232: return selected;
233: }
234:
235: public boolean hasModel() {
236: DataObject dobj = (DataObject) getLookup().lookup(
237: DataObject.class);
238: if (dobj != null) {
239: ModelCookie cookie = (ModelCookie) dobj
240: .getCookie(ModelCookie.class);
241: // Don't check for a model, as it may not be well-formed, and
242: // this method is not checking for that, just that we should
243: // have a model in the normal case.
244: return cookie != null;
245: }
246: return false;
247: }
248:
249: public void setDisplayName(String s) {
250: super .disableDelegation(DELEGATE_GET_DISPLAY_NAME
251: | DELEGATE_SET_DISPLAY_NAME);
252: super .setDisplayName(s);
253: }
254:
255: /**
256: * Set the namespace prefix for this node.
257: *
258: * @param prefix new namespace prefix.
259: */
260: public void setPrefix(String prefix) {
261: String old = this .prefix;
262: this .prefix = prefix;
263: firePropertyChange(PROP_PREFIX, old, prefix);
264: }
265:
266: /**
267: * Mark this node as selected.
268: *
269: * @param selected true to select, false to unselect.
270: */
271: public void setSelected(boolean selected) {
272: if (!canSelect()) {
273: throw new IllegalStateException("node cannot be selected");
274: }
275: boolean old = this .selected;
276: this .selected = selected;
277: firePropertyChange(PROP_SELECTED, old, selected);
278: }
279:
280: private static class Children extends FilterNode.Children {
281: /** Controls the appearance of child nodes. */
282: private ExternalReferenceDecorator decorator;
283:
284: public Children(Node original,
285: ExternalReferenceDecorator decorator) {
286: super (original);
287: this .decorator = decorator;
288: }
289:
290: protected Node[] createNodes(Node n) {
291: DataObject dobj = (DataObject) n.getLookup().lookup(
292: DataObject.class);
293: if (dobj != null) {
294: FileObject fobj = dobj.getPrimaryFile();
295: if (fobj.isFolder()
296: && fobj.getNameExt().equals("nbproject")
297: && fobj.getFileObject("project.xml") != null) {
298: // It is the NetBeans project folder, ignore it.
299: return new Node[0];
300: }
301: ModelCookie cookie = (ModelCookie) dobj
302: .getCookie(ModelCookie.class);
303: String fname = fobj.getNameExt();
304: String ext = decorator.getDocumentType().toString();
305: if (fobj.isFolder() || cookie != null
306: && fname.endsWith(ext)) {
307: return super .createNodes(n);
308: }
309: }
310: return new Node[0];
311: }
312:
313: protected Node copyNode(Node node) {
314: return decorator.createExternalReferenceNode(node);
315: }
316: }
317: }
|