KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > properties > PropertiesDataObject


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.netbeans.modules.properties;
22
23
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.io.ObjectInputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Comparator JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.TreeSet JavaDoc;
32
33 import org.openide.filesystems.FileObject;
34 import org.openide.loaders.*;
35 import org.openide.nodes.Children;
36 import org.openide.nodes.CookieSet;
37 import org.openide.nodes.Node;
38 import org.openide.util.WeakListeners;
39
40
41 /**
42  * Object that provides main functionality for properties data loader.
43  * Represents set of .properties files with same basic name (name without locale postfix).
44  *
45  * @author Ian Formanek
46  */

47 public final class PropertiesDataObject extends MultiDataObject implements CookieSet.Factory {
48
49     /** Generated Serialized Version UID. */
50     static final long serialVersionUID = 4795737295255253334L;
51     
52     /** Structural view of the dataobject */
53     private transient BundleStructure bundleStructure;
54     
55     /** Open support for this data object. Provides editable table view on bundle. */
56     private transient PropertiesOpen openSupport;
57
58     /** Lock used for synchronization of <code>openSupport</code> instance creation */
59     private final transient Object JavaDoc OPEN_SUPPORT_LOCK = new Object JavaDoc();
60
61     // Hack due having lock on secondaries, can't override handleCopy, handleMove at all.
62
/** Suffix used by copying/moving dataObject. */
63     private transient String JavaDoc pasteSuffix;
64
65
66     /**
67      * Constructs a <code>PropertiesDataObject</code> for a specified
68      * primary file.
69      *
70      * @param primaryFile primary file to creata a data object for
71      * @param loader data loader which recognized the primary file
72      * @exception org.openide.loaders.DataObjectExistsException
73      * if another <code>DataObject</code> already exists
74      * for the specified file
75      */

76     public PropertiesDataObject(final FileObject primaryFile,
77                                 final MultiFileLoader loader)
78             throws DataObjectExistsException {
79         super(primaryFile, loader);
80         // use editor support
81
initialize();
82     }
83
84     
85     /** Initializes the object. Used by construction and deserialized. */
86     private void initialize() {
87         bundleStructure = null;
88         Class JavaDoc<? extends Node.Cookie>[] arr = (Class JavaDoc<Node.Cookie>[]) new Class JavaDoc[2];
89         arr[0] = PropertiesOpen.class;
90         arr[1] = PropertiesEditorSupport.class;
91         getCookieSet().add(arr, this);
92     }
93
94     /** Implements <code>CookieSet.Factory</code> interface method. */
95     @SuppressWarnings JavaDoc("unchecked")
96     public <T extends Node.Cookie> T createCookie(Class JavaDoc<T> clazz) {
97         if(clazz.isAssignableFrom(PropertiesOpen.class)) {
98             return (T) getOpenSupport();
99         } else if(clazz.isAssignableFrom(PropertiesEditorSupport.class)) {
100             return (T) ((PropertiesFileEntry)getPrimaryEntry()).getPropertiesEditor();
101         } else {
102             return null;
103         }
104     }
105
106     // Accessibility from PropertiesOpen:
107
CookieSet getCookieSet0() {
108         return getCookieSet();
109     }
110     
111     /** Copies primary and secondary files to new folder.
112      * Overrides superclass method.
113      * @param df the new folder
114      * @return data object for the new primary
115      * @throws IOException if there was a problem copying
116      * @throws UserCancelException if the user cancelled the copy */

117     protected synchronized DataObject handleCopy(DataFolder df) throws IOException JavaDoc {
118         try {
119             pasteSuffix = createPasteSuffix(df);
120
121             return super.handleCopy(df);
122         } finally {
123             pasteSuffix = null;
124         }
125     }
126     
127     /** Moves primary and secondary files to a new folder.
128      * Overrides superclass method.
129      * @param df the new folder
130      * @return the moved primary file object
131      * @throws IOException if there was a problem moving
132      * @throws UserCancelException if the user cancelled the move */

133     protected FileObject handleMove(DataFolder df) throws IOException JavaDoc {
134         try {
135             pasteSuffix = createPasteSuffix(df);
136         
137             return super.handleMove(df);
138         } finally {
139             pasteSuffix = null;
140         }
141     }
142     
143     /** Gets suffix used by entries by copying/moving. */
144     String JavaDoc getPasteSuffix() {
145         return pasteSuffix;
146     }
147
148     /** Only accessible method, it is necessary to call MultiDataObject's method
149      * from this package.
150      */

151     void removeSecondaryEntry2(Entry fe) {
152         removeSecondaryEntry (fe);
153     }
154
155     /** Creates new name for this instance when moving/copying to new folder destination.
156      * @param folder new folder destination. */

157     private String JavaDoc createPasteSuffix(DataFolder folder) {
158         String JavaDoc basicName = getPrimaryFile().getName();
159
160         DataObject[] children = folder.getChildren();
161         
162         
163         // Repeat until there is not such file name.
164
for(int i = 0; ; i++) {
165             String JavaDoc newName;
166             
167             if (i == 0) {
168                 newName = basicName;
169             } else {
170                 newName = basicName + i;
171             }
172             boolean exist = false;
173             
174             for(int j = 0; j < children.length; j++) {
175                 if(children[j] instanceof PropertiesDataObject && newName.equals(children[j].getName())) {
176                     exist = true;
177                     break;
178                 }
179             }
180                 
181             if(!exist) {
182                 if (i == 0) {
183                     return ""; // NOI18N
184
} else {
185                     return "" + i; // NOI18N
186
}
187             }
188         }
189     }
190
191     /** Returns open support. It's used by all subentries as open support too. */
192     public PropertiesOpen getOpenSupport() {
193         synchronized(OPEN_SUPPORT_LOCK) {
194             if(openSupport == null) {
195                 openSupport = new PropertiesOpen(this);
196             }
197
198             return openSupport;
199         }
200     }
201
202     /** Updates modification status of this dataobject from its entries. */
203     void updateModificationStatus() {
204         boolean modif = false;
205         if (((PresentableFileEntry)getPrimaryEntry()).isModified())
206             modif = true;
207         else {
208             for (Iterator JavaDoc it = secondaryEntries().iterator(); it.hasNext(); ) {
209                 if (((PresentableFileEntry)it.next()).isModified()) {
210                     modif = true;
211                     break;
212                 }
213             }
214         }
215
216         super.setModified(modif);
217     }
218
219     /** Provides node that should represent this data object. When a node for representation
220      * in a parent is requested by a call to getNode (parent) it is the exact copy of this node
221      * with only parent changed. This implementation creates instance
222      * <CODE>DataNode</CODE>.
223      * <P>
224      * This method is called only once.
225      *
226      * @return the node representation for this data object
227      * @see DataNode
228      */

229     protected Node createNodeDelegate () {
230         PropertiesChildren pc = new PropertiesChildren();
231
232         // properties node - creates new types
233
DataNode dn = new PropertiesDataNode(this, pc);
234         return dn;
235     }
236
237     /** Returns a structural view of this data object */
238     public BundleStructure getBundleStructure() {
239         if (bundleStructure == null)
240             bundleStructure = new BundleStructure(this);
241         return bundleStructure;
242     }
243
244     /** Comparator used for ordering secondary files, works over file names */
245     public static Comparator JavaDoc<String JavaDoc> getSecondaryFilesComparator() {
246         return new KeyComparator();
247     }
248
249     /**
250      */

251     void fireNameChange() {
252         firePropertyChange(PROP_NAME, null, null);
253     }
254     
255     /** Deserialization. */
256     private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
257         in.defaultReadObject();
258         initialize();
259     }
260
261     
262     /** Children of this <code>PropertiesDataObject</code>. */
263     private class PropertiesChildren extends Children.Keys<String JavaDoc> {
264
265         /** Listens to changes on the dataobject */
266         private PropertyChangeListener JavaDoc propertyListener = null;
267
268         
269         /** Constructor.*/
270         PropertiesChildren() {
271             super();
272         }
273
274         
275         /** Sets all keys in the correct order */
276         protected void mySetKeys() {
277             TreeSet JavaDoc<String JavaDoc> newKeys = new TreeSet JavaDoc<String JavaDoc>(new Comparator JavaDoc<String JavaDoc>() {
278                 public int compare(String JavaDoc o1, String JavaDoc o2) {
279                     if (o1 == o2) {
280                         return 0;
281                     }
282                     if (o1 == null) {
283                         return -1;
284                     }
285                     if (o2 == null) {
286                         return 1;
287                     }
288                     return o1.compareTo(o2);
289                 }
290             });
291
292             newKeys.add(getPrimaryEntry().getFile().getName());
293             
294             for (Entry entry : secondaryEntries()) {
295                 newKeys.add(entry.getFile().getName());
296             }
297
298             setKeys(newKeys);
299         }
300
301         /** Called to notify that the children has been asked for children
302          * after and that they should set its keys. Overrides superclass method. */

303         protected void addNotify () {
304             mySetKeys();
305             
306             // listener
307
if(propertyListener == null) {
308                 propertyListener = new PropertyChangeListener JavaDoc () {
309                     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
310                         if(PROP_FILES.equals(evt.getPropertyName())) {
311                             mySetKeys();
312                         }
313                     }
314                 };
315
316                 PropertiesDataObject.this.addPropertyChangeListener(
317                     WeakListeners.propertyChange(propertyListener, PropertiesDataObject.this));
318             }
319         }
320
321         /** Called to notify that the children has lost all of its references to
322          * its nodes associated to keys and that the keys could be cleared without
323          * affecting any nodes (because nobody listens to that nodes).
324          * Overrides superclass method. */

325         protected void removeNotify () {
326             setKeys(new ArrayList JavaDoc<String JavaDoc>());
327         }
328
329         /** Creates nodes for specified key. Implements superclass abstract method. */
330         protected Node[] createNodes(String JavaDoc entryName) {
331             if (entryName == null) {
332                 return null;
333             }
334             
335             PropertiesFileEntry entry = (PropertiesFileEntry)getPrimaryEntry();
336             
337             if(entryName.equals(entry.getFile().getName())) {
338                 return new Node[] {entry.getNodeDelegate()};
339             }
340             for(Iterator JavaDoc<Entry> it = secondaryEntries().iterator();it.hasNext();) {
341                 entry = (PropertiesFileEntry)it.next();
342                 
343                 if (entryName.equals(entry.getFile().getName())) {
344                     return new Node[] {entry.getNodeDelegate()};
345                 }
346             }
347                 
348             return null;
349         }
350
351     } // End of class PropertiesChildren.
352

353 }
354
Popular Tags