This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 48263
Collapse All | Expand All

(-)a/properties/apichanges.xml (+273 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
<?xml-stylesheet type="text/xml" href="../nbbuild/javadoctools/apichanges.xsl"?>
44
<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
45
46
<!--
47
48
INFO FOR PEOPLE ADDING CHANGES:
49
50
Check the DTD (apichanges.dtd) for details on the syntax. You do not
51
need to regenerate the HTML, as this is part of Javadoc generation; just
52
change the XML. Rough syntax of a change (several parts optional):
53
54
<change>
55
    <api name="compiler"/>
56
    <summary>Some brief description here, can use <b>XHTML</b></summary>
57
    <version major="1" minor="99"/>
58
    <date day="13" month="6" year="2001"/>
59
    <author login="jrhacker"/>
60
    <compatibility addition="yes"/>
61
    <description>
62
        The main description of the change here.
63
        Again can use full <b>XHTML</b> as needed.
64
    </description>
65
    <class package="org.openide.compiler" name="DoWhatIWantCompiler"/>
66
    <issue number="14309"/>
67
</change>
68
69
Also permitted elements: <package>, <branch>. <version> is API spec
70
version, recommended for all new changes. <compatibility> should say
71
if things were added/modified/deprecated/etc. and give all information
72
related to upgrading old code. List affected top-level classes and
73
link to issue numbers if applicable. See the DTD for more details.
74
75
Changes need not be in any particular order, they are sorted in various
76
ways by the stylesheet anyway.
77
78
Dates are assumed to mean "on the trunk". If you *also* make the same
79
change on a stabilization branch, use the <branch> tag to indicate this
80
and explain why the change was made on a branch in the <description>.
81
82
Please only change this file on the trunk! Rather: you can change it
83
on branches if you want, but these changes will be ignored; only the
84
trunk version of this file is important.
85
86
Deprecations do not count as incompatible, assuming that code using the
87
deprecated calls continues to see their documented behavior. But do
88
specify deprecation="yes" in <compatibility>.
89
90
This file is not a replacement for Javadoc: it is intended to list changes,
91
not describe the complete current behavior, for which ordinary documentation
92
is the proper place.
93
94
-->
95
96
<apichanges>
97
98
  <!-- First, a list of API names you may use: -->
99
  <apidefs>
100
    <!-- Probably should not be used much: -->
101
    <apidef name="properties">Properties API</apidef>
102
  </apidefs>
103
104
<!-- ACTUAL CHANGES BEGIN HERE: -->
105
106
  <changes>
107
       <change id="BundleEditPanel">
108
        <api name="properties"/>
109
        <summary>Changed to work with <code>BundleStructure</code> instead of single <code>DataObject</code></summary>
110
        <version major="1" minor="27"/>
111
        <date day="13" month="1" year="2009"/>
112
        <author login="alexeybutenko"/>
113
        <compatibility addition="yes" deprecation="yes" modification="yes"/>
114
        <description>
115
            <p>
116
              Added <code>@Deprecated</code> to following methods: constructor <code>
117
		BundleEditPanel(final PropertiesDataObject obj, PropertiesTableModel propTableModel)</code>,
118
		Added public constructor <code>BundleEditPanel(final BundleStructure structure, PropertiesTableModel propTableModel)</code>
119
            </p>
120
        </description>
121
        <class package="org.netbeans.modules.properties" name="BundleEditPanel"/>
122
    </change>
123
124
      <change id="MultiBundleStructure">
125
        <api name="properties"/>
126
        <summary>Added class <code>MultiBundleStructure</code></summary>
127
        <version major="1" minor="27"/>
128
        <date day="13" month="1" year="2009"/>
129
        <author login="alexeybutenko"/>
130
        <compatibility addition="yes"/>
131
        <description>
132
            <p>
133
                Added package private class <code>MultiBundleStructure</code> extends
134
                <code>BundleStructure</code> which can handle several <code>DataObject</code>
135
                with the same base name
136
            </p>
137
        </description>
138
        <class package="org.netbeans.modules.properties" name="MultiBundleStructure"/>
139
        <issue number="134558"/>
140
    </change>
141
 
142
     <change id="PropertiesDataLoader">
143
        <api name="properties"/>
144
        <summary>
145
          Method <code>findPrimaryFile</code> changed to return each <code>FileObject</code> as 
146
		primary entry for <code>DataObject</code>
147
        </summary>
148
        <version major="3" minor="13"/>
149
        <date day="10" month="1" year="2009"/>
150
        <author login="alexeybutenko"/>
151
        <compatibility modification="yes"/>
152
        <description>
153
            <p>
154
              Separate <code>DataObject</code> for each <code>FileObject</code> is created after this modification
155
            </p>
156
        </description>
157
        <class package="org.netbeans.modules.properties" name="PropertiesDataLoader"/>
158
    </change>
159
  
160
     <change id="PropertiesDataObject">
161
        <api name="properties"/>
162
        <summary>
163
          Methods <code>getOpenSupport</code>, and <code>getBundleStructure</code> modified 
164
        </summary>
165
        <version major="1" minor="27"/>
166
        <date day="14" month="1" year="2009"/>
167
        <author login="alexeybutenko"/>
168
        <compatibility modification="yes" deletion="yes"/>
169
        <description>
170
            <p>
171
              <code>getBundleStructure</code> method chaged to return the same 
172
              <code>MultiBundleStructure</code> instance for every DataObject belonging 
173
		to one set of locales, wich is defined by the base name, and locale suffix.
174
            </p>
175
            <p>
176
              <code>getOpenSupport</code> changed to return <code>OpenSupport</code> instance from 
177
              <code>BundleStructure</code>, thus it will the same for the set of locales with the the same 
178
              base name
179
            </p>
180
        </description>
181
        <class package="org.netbeans.modules.properties" name="PropertiesDataObject"/>
182
    </change>
183
     <change id="PropertiesOpen">
184
        <api name="properties"/>
185
        <summary>
186
           Added ability to work with several <code>DataObject</code>s with the same base name via
187
           their common <code>BundleStructure</code>
188
        </summary>
189
        <version major="1" minor="27"/>
190
        <date day="14" month="1" year="2009"/>
191
        <author login="alexeybutenko"/>
192
        <compatibility modification="yes" deprecation="yes" addition="yes"/>
193
        <description>
194
            <p>
195
              <code>PropertiesOpen(PropertiesDataObject propDataObject)</code> deprecated,
196
              <code>PropertiesOpen.Environment(PropertiesDataObject dataObject)</code> deprecated,
197
              <code>PropertiesOpen.Environment.isValid()</code> deprecated,
198
              <code>PropertiesOpen.Environment.markModified()</code> deprecated,
199
              <code> PropertiesOpen.Environment.unmarkModified()</code> deprecated,
200
              added <code>PropertiesOpen(BundleStructure structure)</code>,
201
              added <code>PropertiesOpen.Environment(BundleStructure structure)</code>,
202
              added <code>PropertiesOpen.Environment.isValid(PropertiesDataObject dataObject)</code>, 
203
              added <code>PropertiesOpen.Environment.markModified(PropertiesDataObject dataObject)</code>,
204
              added <code>PropertiesOpen.Environment.unmarkModified(PropertiesDataObject dataObject)</code>,
205
              method <code>PropertiesOpen.Environment.propertyChange(PropertyChangeEvent evt)</code> 
206
              modified to find <code>DataObject</code> which caused this event
207
            </p>
208
        </description>
209
        <class package="org.netbeans.modules.properties" name="PropertiesOpen"/>
210
    </change>
211
     <change id="Util">
212
        <api name="properties"/>
213
        <summary>
214
           Added several methods.
215
        </summary>
216
        <version major="1" minor="27"/>
217
        <date day="14" month="1" year="2009"/>
218
        <author login="alexeybutenko"/>
219
        <compatibility modification="yes" addition="yes"/>
220
        <description>
221
            <p>
222
                <code>getLocaleSuffix(MultiDataObject.Entry fe)</code> modified,
223
                added protected method<code>findPrimaryDataObject</code> return <code>DataObject</code>
224
                which represent the default locale.
225
            </p>
226
        </description>
227
        <class package="org.netbeans.modules.properties" name="Util"/>
228
    </change>
229
230
  </changes>
231
232
  <!-- Now the surrounding HTML text and document structure: -->
233
234
  <htmlcontents>
235
<!--
236
237
                            NO NO NO NO NO!
238
239
         ==============>    DO NOT EDIT ME!  <======================
240
241
          AUTOMATICALLY GENERATED FROM APICHANGES.XML, DO NOT EDIT
242
243
                SEE openidex/api/apichanges.xml
244
245
-->
246
    <head>
247
      <title>Change History for the Search API</title>
248
      <link rel="stylesheet" href="prose.css" type="text/css"/>
249
    </head>
250
    <body>
251
252
<p class="overviewlink"><a href="overview-summary.html">Overview</a></p>
253
254
<h1>Introduction</h1>
255
256
<p>
257
    This document lists changes made to the <code>Search API</code>.
258
</p>
259
260
<!-- The actual lists of changes, as summaries and details: -->
261
262
    <hr/>
263
264
    <standard-changelists module-code-name="org.netbeans.modules.properties/3"/>
265
266
    <hr/>
267
268
    <p>@FOOTER@</p>
269
270
    </body>
271
  </htmlcontents>
272
273
</apichanges>
(-)a/properties/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.properties/1
2
OpenIDE-Module: org.netbeans.modules.properties/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/properties/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/properties/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.26
4
OpenIDE-Module-Specification-Version: 1.27
5
OpenIDE-Module-Layer: org/netbeans/modules/properties/Layer.xml
5
OpenIDE-Module-Layer: org/netbeans/modules/properties/Layer.xml
6
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Show-In-Client: false
(-)a/properties/src/org/netbeans/modules/properties/BundleEditPanel.java (-28 / +120 lines)
Lines 73-80 Link Here
73
public class BundleEditPanel extends JPanel implements PropertyChangeListener {
73
public class BundleEditPanel extends JPanel implements PropertyChangeListener {
74
    
74
    
75
    /** PropertiesDataObject this panel presents. */
75
    /** PropertiesDataObject this panel presents. */
76
    private PropertiesDataObject obj;
76
//    private PropertiesDataObject obj;
77
    
77
78
    /** */
79
    private BundleStructure structure;
80
78
    /** Document listener for value and comment textareas. */
81
    /** Document listener for value and comment textareas. */
79
    private DocumentListener listener;
82
    private DocumentListener listener;
80
    
83
    
Lines 88-95 Link Here
88
    private int lastSelectedColumn;
91
    private int lastSelectedColumn;
89
    
92
    
90
    /** Creates new form BundleEditPanel */
93
    /** Creates new form BundleEditPanel */
94
    @Deprecated
91
    public BundleEditPanel(final PropertiesDataObject obj, PropertiesTableModel propTableModel) {
95
    public BundleEditPanel(final PropertiesDataObject obj, PropertiesTableModel propTableModel) {
92
        this.obj = obj;
96
//        this.obj = obj;
97
        this.structure = obj.getBundleStructure();
93
        
98
        
94
        initComponents();
99
        initComponents();
95
        initAccessibility();
100
        initAccessibility();
Lines 153-160 Link Here
153
                obj.getBundleStructure().sort(modelIndex);
158
                obj.getBundleStructure().sort(modelIndex);
154
            }
159
            }
155
        });
160
        });
161
156
        
162
        
163
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
164
            public void valueChanged(ListSelectionEvent evt) {
165
                final boolean correctCellSelection = !selectionUpdateDisabled;
166
                SwingUtilities.invokeLater(new Runnable() {
167
                    public void run() {
168
                        updateSelection(correctCellSelection);
169
                    }
170
                });
171
            }
172
        });
157
        
173
        
174
    } // End of constructor.
175
    
176
    /** Creates new form BundleEditPanel */
177
    public BundleEditPanel(final BundleStructure structure, PropertiesTableModel propTableModel) {
178
        this.structure = structure;
179
180
        initComponents();
181
        initAccessibility();
182
        initSettings();
183
184
        // Sets table column model.
185
        table.setColumnModel(new TableViewColumnModel());
186
187
        // Sets custom table header renderer (with sorting indicators).
188
        JTableHeader header = table.getTableHeader();
189
        header.setDefaultRenderer(
190
                new TableViewHeaderRenderer(structure, header.getDefaultRenderer()));
191
192
        // Sets table model.
193
        table.setModel(propTableModel);
194
195
        // Sets table cell editor.
196
        JTextField textField = new JTextField();
197
        // Force the document to accept newlines. The textField doesn't like
198
        // it, but the same document is used by the <code>textValue</code> text
199
        // area that must accept newlines.
200
        textField.getDocument().putProperty("filterNewlines",  Boolean.FALSE); // NOI18N
201
        textField.setBorder(new LineBorder(Color.black));
202
        textField.getAccessibleContext().setAccessibleName(NbBundle.getBundle(BundleEditPanel.class).getString("ACSN_CellEditor"));
203
        textField.getAccessibleContext().setAccessibleDescription(NbBundle.getBundle(BundleEditPanel.class).getString("ACSD_CellEditor"));
204
        listener = new ModifiedListener();
205
        table.setDefaultEditor(PropertiesTableModel.StringPair.class,
206
            new PropertiesTableCellEditor(textField, textComment, textValue, valueLabel, listener));
207
208
        // Sets renderer.
209
        table.setDefaultRenderer(PropertiesTableModel.StringPair.class, new TableViewRenderer());
210
211
        updateAddButton();
212
213
        // property change listener - listens to editing state of the table
214
        table.addPropertyChangeListener(new PropertyChangeListener() {
215
            public void propertyChange(PropertyChangeEvent evt) {
216
                if (evt.getPropertyName().equals("tableCellEditor")) { // NOI18N
217
                    updateEnabled();
218
                } else if (evt.getPropertyName().equals("model")) { // NOI18N
219
                    updateAddButton();
220
                }
221
            }
222
        });
223
224
        // listens on clikcs on table header, detects column and sort accordingly to chosen one
225
        table.getTableHeader().addMouseListener(new MouseAdapter() {
226
            @Override
227
            public void mouseClicked(MouseEvent e) {
228
                TableColumnModel colModel = table.getColumnModel();
229
                int columnModelIndex = colModel.getColumnIndexAtX(e.getX());
230
                // No column was clicked.
231
                if (columnModelIndex < 0) {
232
                    return;
233
                }
234
                int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex();
235
                // not detected column
236
                if (modelIndex < 0) {
237
                    return;
238
                }
239
                structure.sort(modelIndex);
240
            }
241
        });
242
158
        ListSelectionListener listSelectionListener = new ListSelectionListener() {
243
        ListSelectionListener listSelectionListener = new ListSelectionListener() {
159
244
160
            public void valueChanged(ListSelectionEvent evt) {
245
            public void valueChanged(ListSelectionEvent evt) {
Lines 169-177 Link Here
169
254
170
        table.getColumnModel().getSelectionModel().addListSelectionListener(listSelectionListener);
255
        table.getColumnModel().getSelectionModel().addListSelectionListener(listSelectionListener);
171
        table.getSelectionModel().addListSelectionListener(listSelectionListener);
256
        table.getSelectionModel().addListSelectionListener(listSelectionListener);
172
        
257
173
    } // End of constructor.
258
    } // End of constructor.
174
    
175
    
259
    
176
    /** Stops editing if editing is in run. */
260
    /** Stops editing if editing is in run. */
177
    protected void stopEditing() {
261
    protected void stopEditing() {
Lines 233-239 Link Here
233
                    if (ex == null) {
317
                    if (ex == null) {
234
                        return;
318
                        return;
235
                    } 
319
                    } 
236
                    String [] keys = obj.getBundleStructure().getKeys();
320
                    String [] keys = structure.getKeys();
237
                    int idx;
321
                    int idx;
238
                    for (idx = 0; idx < keys.length; idx++) {
322
                    for (idx = 0; idx < keys.length; idx++) {
239
                        String key = keys[idx];
323
                        String key = keys[idx];
Lines 252-258 Link Here
252
        }
336
        }
253
        
337
        
254
        lastSelectedColumn = column;
338
        lastSelectedColumn = column;
255
        BundleStructure structure = obj.getBundleStructure();
339
//        BundleStructure structure = obj.getBundleStructure();
256
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
340
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
257
        String value;
341
        String value;
258
        String comment;
342
        String comment;
Lines 285-298 Link Here
285
    }
369
    }
286
    
370
    
287
    private void updateAddButton() {
371
    private void updateAddButton() {
288
        addButton.setEnabled(!obj.getBundleStructure().isReadOnly());
372
        addButton.setEnabled(!structure.isReadOnly());
289
    }
373
    }
290
    
374
    
291
    /** Returns the main table with all values */
375
    /** Returns the main table with all values */
292
    public JTable getTable() {
376
    public JTable getTable() {
293
        return table;
377
        return table;
294
    }
378
    }
295
    
296
    
379
    
297
    /** Initializes <code>settings</code> variable. */
380
    /** Initializes <code>settings</code> variable. */
298
    private void initSettings() {
381
    private void initSettings() {
Lines 515-524 Link Here
515
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
598
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
516
            try {
599
            try {
517
                // Starts "atomic" acion for special undo redo manager of open support.
600
                // Starts "atomic" acion for special undo redo manager of open support.
518
                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
601
//                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
602
                structure.getOpenSupport().atomicUndoRedoFlag = new Object();
519
                
603
                
520
                for (int i=0; i < obj.getBundleStructure().getEntryCount(); i++) {
604
                for (int i=0; i < structure.getEntryCount(); i++) {
521
                    PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
605
                    PropertiesFileEntry entry = structure.getNthEntry(i);
522
                    if (entry != null) {
606
                    if (entry != null) {
523
                        PropertiesStructure ps = entry.getHandler().getStructure();
607
                        PropertiesStructure ps = entry.getHandler().getStructure();
524
                        if (ps != null) {
608
                        if (ps != null) {
Lines 528-534 Link Here
528
                }
612
                }
529
            } finally {
613
            } finally {
530
                // finishes "atomic" undo redo action for special undo redo manager of open support
614
                // finishes "atomic" undo redo action for special undo redo manager of open support
531
                obj.getOpenSupport().atomicUndoRedoFlag = null;
615
//                obj.getOpenSupport().atomicUndoRedoFlag = null;
616
                structure.getOpenSupport().atomicUndoRedoFlag = null;
532
            }
617
            }
533
        }
618
        }
534
    }//GEN-LAST:event_removeButtonActionPerformed
619
    }//GEN-LAST:event_removeButtonActionPerformed
Lines 567-580 Link Here
567
            selectionUpdateDisabled = true;
652
            selectionUpdateDisabled = true;
568
653
569
            // Starts "atomic" acion for special undo redo manager of open support.
654
            // Starts "atomic" acion for special undo redo manager of open support.
570
            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
655
//            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
571
            
656
            structure.getOpenSupport().atomicUndoRedoFlag = new Object();
572
            String existingLocales = "";
657
            String existingLocales = "";
573
            String comma = ",\r\n"; //NOI18N
658
            String comma =",\r\n";
574
            int count = obj.getBundleStructure().getEntryCount();
575
            // add key to all entries
659
            // add key to all entries
576
            for (int i=0; i < count; i++) {
660
            for (int i=0; i < structure.getEntryCount(); i++) {
577
                PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
661
                PropertiesFileEntry entry = structure.getNthEntry(i);
578
                
662
                
579
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
663
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
580
                    existingLocales += Util.getLocaleLabel(entry) + comma;
664
                    existingLocales += Util.getLocaleLabel(entry) + comma;
Lines 595-604 Link Here
595
                    NotifyDescriptor.ERROR_MESSAGE);
679
                    NotifyDescriptor.ERROR_MESSAGE);
596
                    DialogDisplayer.getDefault().notify(msg);
680
                    DialogDisplayer.getDefault().notify(msg);
597
            }
681
            }
598
599
        } finally {
682
        } finally {
600
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
683
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
601
            obj.getOpenSupport().atomicUndoRedoFlag = null;
684
//            obj.getOpenSupport().atomicUndoRedoFlag = null;
685
            structure.getOpenSupport().atomicUndoRedoFlag = null;
602
686
603
            selectionUpdateDisabled = false;
687
            selectionUpdateDisabled = false;
604
        }
688
        }
Lines 612-618 Link Here
612
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
696
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
613
                public void run() {
697
                public void run() {
614
                    // Find indexes.
698
                    // Find indexes.
615
                    int rowIndex = obj.getBundleStructure().getKeyIndexByName(key);
699
                    int rowIndex = structure.getKeyIndexByName(key);
616
                    
700
                    
617
                    if((rowIndex != -1)) {
701
                    if((rowIndex != -1)) {
618
                        final int row = rowIndex;
702
                        final int row = rowIndex;
Lines 681-693 Link Here
681
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
765
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
682
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
766
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
683
767
684
        private final PropertiesDataObject propDataObj;
768
        private final BundleStructure bundleStructure;
685
        private final TableCellRenderer origRenderer;
769
        private final TableCellRenderer origRenderer;
686
        private ImageIcon iconSortAsc, iconSortDesc;
770
        private ImageIcon iconSortAsc, iconSortDesc;
687
        
771
772
        @Deprecated
688
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
773
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
689
                                TableCellRenderer origRenderer) {
774
                                TableCellRenderer origRenderer) {
690
            this.propDataObj = propDataObj;
775
            bundleStructure = propDataObj.getBundleStructure();
776
            this.origRenderer = origRenderer;
777
        }
778
779
        TableViewHeaderRenderer(BundleStructure bundleStructure,
780
                                TableCellRenderer origRenderer) {
781
            this.bundleStructure = bundleStructure;
691
            this.origRenderer = origRenderer;
782
            this.origRenderer = origRenderer;
692
        }
783
        }
693
784
Lines 702-708 Link Here
702
793
703
            if (comp instanceof JLabel) {
794
            if (comp instanceof JLabel) {
704
                JLabel label = (JLabel) comp;
795
                JLabel label = (JLabel) comp;
705
                BundleStructure bundleStruct = propDataObj.getBundleStructure();
796
                BundleStructure bundleStruct = bundleStructure;
706
                int sortIndex = table.convertColumnIndexToView(
797
                int sortIndex = table.convertColumnIndexToView(
707
                                        bundleStruct.getSortIndex());
798
                                        bundleStruct.getSortIndex());
708
                if (column == sortIndex) {
799
                if (column == sortIndex) {
Lines 1007-1015 Link Here
1007
        }
1098
        }
1008
        
1099
        
1009
        private void documentModified() {
1100
        private void documentModified() {
1010
            obj.setModified(true);
1101
            ((PropertiesTableModel)table.getModel()).getFileEntry(table.getEditingColumn()).getDataObject().setModified(true);
1102
//            obj.setModified(true);
1011
        }
1103
        }
1012
        
1104
        
1013
    }
1105
    }
1014
    
1106
1015
}
1107
}
(-)a/properties/src/org/netbeans/modules/properties/BundleStructure.java (-14 / +39 lines)
Lines 44-49 Link Here
44
44
45
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
46
import java.beans.PropertyChangeListener;
47
import java.io.Serializable;
47
import java.util.List;
48
import java.util.List;
48
import java.util.ArrayList;
49
import java.util.ArrayList;
49
import java.util.Collections;
50
import java.util.Collections;
Lines 51-56 Link Here
51
import java.util.Iterator;
52
import java.util.Iterator;
52
import java.util.Map;
53
import java.util.Map;
53
import java.util.TreeMap;
54
import java.util.TreeMap;
55
import org.openide.filesystems.FileObject;
54
import org.openide.loaders.MultiDataObject.Entry;
56
import org.openide.loaders.MultiDataObject.Entry;
55
import org.openide.util.WeakListeners;
57
import org.openide.util.WeakListeners;
56
58
Lines 69-75 Link Here
69
 * @author Petr Jiricka
71
 * @author Petr Jiricka
70
 */
72
 */
71
public class BundleStructure {
73
public class BundleStructure {
72
    
74
73
    /**
75
    /**
74
     * <code>PropertiesDataObject</code> whose structure is described
76
     * <code>PropertiesDataObject</code> whose structure is described
75
     * by this object
77
     * by this object
Lines 109-115 Link Here
109
111
110
    /** listens to changes on the underlying <code>PropertyDataObject</code> */
112
    /** listens to changes on the underlying <code>PropertyDataObject</code> */
111
    private PropertyChangeListener propListener;
113
    private PropertyChangeListener propListener;
112
    
114
115
    protected BundleStructure() {
116
        obj = null;
117
    }
113
    /**
118
    /**
114
     * Creates a new instance describing a given
119
     * Creates a new instance describing a given
115
     * <code>PropertiesDataObject</code>.
120
     * <code>PropertiesDataObject</code>.
Lines 543-548 Link Here
543
        return comparator.isAscending();
548
        return comparator.isAscending();
544
    }
549
    }
545
550
551
    PropertiesOpen getOpenSupport() {
552
        throw new UnsupportedOperationException("Not yet implemented");
553
    }
554
546
    /**
555
    /**
547
     * Builds (or rebuilds) a sorted list of entries of the underlying
556
     * Builds (or rebuilds) a sorted list of entries of the underlying
548
     * <code>PropertiesDataObject<code> and a sorted list of keys gathered
557
     * <code>PropertiesDataObject<code> and a sorted list of keys gathered
Lines 551-557 Link Here
551
     * @see  #entries
560
     * @see  #entries
552
     * @see  #keyList
561
     * @see  #keyList
553
     */
562
     */
554
    private void updateEntries() {
563
    void updateEntries() {
555
        Map<String,PropertiesFileEntry> tm = new TreeMap<String,PropertiesFileEntry>(
564
        Map<String,PropertiesFileEntry> tm = new TreeMap<String,PropertiesFileEntry>(
556
                PropertiesDataObject.getSecondaryFilesComparator());
565
                PropertiesDataObject.getSecondaryFilesComparator());
557
        for (Entry entry : obj.secondaryEntries()) {
566
        for (Entry entry : obj.secondaryEntries()) {
Lines 577-583 Link Here
577
     *
586
     *
578
     * @see  #keyList
587
     * @see  #keyList
579
     */
588
     */
580
    private synchronized void buildKeySet() {
589
    protected synchronized void buildKeySet() {
581
        List<String> keyList = new ArrayList<String>() {
590
        List<String> keyList = new ArrayList<String>() {
582
            public boolean equals(Object obj) {
591
            public boolean equals(Object obj) {
583
                if (!(obj instanceof ArrayList)) {
592
                if (!(obj instanceof ArrayList)) {
Lines 602-617 Link Here
602
        int entriesCount = getEntryCount();
611
        int entriesCount = getEntryCount();
603
        for (int index = 0; index < entriesCount; index++) {
612
        for (int index = 0; index < entriesCount; index++) {
604
            PropertiesFileEntry entry = getNthEntry(index);
613
            PropertiesFileEntry entry = getNthEntry(index);
605
            PropertiesStructure ps = entry.getHandler().getStructure();
614
            if (entry != null) {
606
            if (ps != null) {
615
                PropertiesStructure ps = entry.getHandler().getStructure();
607
                for (Iterator<Element.ItemElem> it = ps.allItems(); it.hasNext(); ) {
616
                if (ps != null) {
608
                    Element.ItemElem item = it.next();
617
                    for (Iterator<Element.ItemElem> it = ps.allItems(); it.hasNext(); ) {
609
                    if (item == null) {
618
                        Element.ItemElem item = it.next();
610
                        continue;
619
                        if (item == null) {
611
                    }
620
                            continue;
612
                    String key = item.getKey();
621
                        }
613
                    if (key != null && !(keyList.contains(key))) {
622
                        String key = item.getKey();
614
                        keyList.add(item.getKey());
623
                        if (key != null && !(keyList.contains(key))) {
624
                            keyList.add(item.getKey());
625
                        }
615
                    }
626
                    }
616
                }
627
                }
617
            }
628
            }
Lines 676-681 Link Here
676
     * @see  #removePropertyBundleListener
687
     * @see  #removePropertyBundleListener
677
     */
688
     */
678
    public void addPropertyBundleListener(PropertyBundleListener l) {
689
    public void addPropertyBundleListener(PropertyBundleListener l) {
690
        if (propBundleSupport == null) propBundleSupport = new PropertyBundleSupport(this);
679
        propBundleSupport.addPropertyBundleListener(l);
691
        propBundleSupport.addPropertyBundleListener(l);
680
    }
692
    }
681
693
Lines 707-712 Link Here
707
        );
719
        );
708
    }
720
    }
709
721
722
    void notifyOneFileChanged(FileObject file) {
723
        // PENDING - events should be finer
724
        // find out whether global key table has changed and fire a change
725
        // according to that
726
        List oldKeyList = keyList;
727
728
        buildKeySet();
729
        if (!keyList.equals(oldKeyList)) {
730
            propBundleSupport.fireBundleDataChanged();
731
        } else {
732
            propBundleSupport.fireFileChanged(file.getName());
733
        }
734
    }
710
    /**
735
    /**
711
     * Notifies registered listeners of a change in a single file entry.
736
     * Notifies registered listeners of a change in a single file entry.
712
     * Depending whether a list of keys has changed, either an event
737
     * Depending whether a list of keys has changed, either an event
(-)a/properties/src/org/netbeans/modules/properties/MultiBundleStructure.java (+291 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.modules.properties;
40
41
import java.io.Serializable;
42
import java.util.ArrayList;
43
import java.util.Arrays;
44
import java.util.HashSet;
45
import java.util.List;
46
import java.util.Locale;
47
import java.util.Set;
48
import org.openide.filesystems.FileObject;
49
import org.openide.loaders.DataObject;
50
import org.openide.loaders.DataObjectNotFoundException;
51
import org.openide.util.Exceptions;
52
53
/**
54
 *
55
 * @author alexeybutenko
56
 */
57
class MultiBundleStructure extends BundleStructure implements Serializable {
58
59
    private transient FileObject[] files;
60
    private transient PropertiesFileEntry primaryEntry;
61
    private String baseName;
62
63
    /** Generated Serialized Version UID. */
64
    static final long serialVersionUID = 7501232754255253334L;
65
66
    private transient PropertiesOpen openSupport;
67
    /** Lock used for synchronization of <code>openSupport</code> instance creation */
68
    private final transient Object OPEN_SUPPORT_LOCK = new Object();
69
70
71
    protected MultiBundleStructure() {
72
//        super();
73
//        files = null;
74
//        primaryEntry = null;
75
//        baseName = null;
76
    }
77
78
    public MultiBundleStructure(PropertiesDataObject obj) {
79
//        super(obj);
80
        this.obj = obj;
81
        baseName = Util.getBaseName(obj.getName());
82
    }
83
84
    /**
85
     * Find entries according to PropertiesDataObject
86
     *
87
     */
88
    private void findEntries() {
89
        try {
90
            if (obj == null) return;
91
            if (!obj.isValid()) {
92
                if (files.length == 1) {
93
                    primaryEntry = null;
94
                    obj = null;
95
                    files = null;
96
                    return;
97
                }
98
            } else {
99
                obj = Util.findPrimaryDataObject(obj);
100
                primaryEntry = (PropertiesFileEntry) obj.getPrimaryEntry();
101
            }
102
            FileObject primary = primaryEntry.getFile();
103
            FileObject parent = primary.getParent();
104
            List<FileObject> listFileObjects = new ArrayList<FileObject>();
105
            String fName;
106
            FileObject oldCandidate;
107
            for (FileObject file : parent.getChildren()) {
108
                fName = file.getName();
109
                if (fName.equals(baseName) && file.isValid()) {
110
                    listFileObjects.add(0,file);
111
                }
112
                if (fName.indexOf(baseName) != -1) {
113
                    int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
114
                    if (index == baseName.length()) {
115
                        oldCandidate = null;
116
                        while (index != -1) {
117
                            FileObject candidate = file;
118
                            if (candidate != null && isValidLocaleSuffix(fName.substring(index)) && oldCandidate == null && file.isValid()) {
119
                                listFileObjects.add(candidate);
120
                                oldCandidate = candidate;
121
                            }
122
                            index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
123
                        }
124
                    }
125
                }
126
            }
127
            files = new FileObject[listFileObjects.size()];
128
            int index = 0;
129
            for (FileObject file : listFileObjects) {
130
                files[index++] = file;
131
            }
132
            primaryEntry = getNthEntry(0);
133
            obj = (PropertiesDataObject) primaryEntry.getDataObject();
134
        } catch (DataObjectNotFoundException ex) {
135
            Exceptions.printStackTrace(ex);
136
        }
137
    }
138
139
    void updateEntries() {
140
        findEntries();
141
        if (files != null) {
142
            buildKeySet();
143
        }
144
    }
145
146
    @Override
147
    public PropertiesFileEntry getNthEntry(int index) {
148
        if (files == null) {
149
            return super.getNthEntry(index);
150
//            notifyEntriesNotInitialized();
151
        }
152
        if (index >= 0 && index < files.length) {
153
            try {
154
                return (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
155
            } catch (DataObjectNotFoundException ex) {
156
                Exceptions.printStackTrace(ex);
157
                return null;
158
            }
159
        } else {
160
            return null;
161
        }
162
    }
163
164
    /**
165
     * Retrieves an index of a file entry representing the given file.
166
     *
167
     * @param  fileName  simple name (without path and extension) of the
168
     *                   primary or secondary file
169
     * @return  index of the entry representing a file with the given filename;
170
     *          or <code>-1</code> if no such entry is found
171
     * @exception  java.lang.IllegalStateException
172
     *             if the list of entries has not been initialized yet
173
     * @see  #getEntryByFileName
174
     */
175
    @Override
176
    public int getEntryIndexByFileName(String fileName) {
177
        if (files == null) {
178
            notifyEntriesNotInitialized();
179
        }
180
        for (int i = 0; i < getEntryCount(); i++) {
181
            if (files[i].getName().equals(fileName)) {
182
                return i;
183
            }
184
        }
185
        return -1;
186
    }
187
188
    /**
189
     * Retrieves a file entry representing the given file
190
     *
191
     * @param  fileName  simple name (excl. path, incl. extension) of the
192
     *                   primary or secondary file
193
     * @return  entry representing the given file;
194
     *          or <code>null</code> if not such entry is found
195
     * @exception  java.lang.IllegalStateException
196
     *             if the list of entries has not been initialized yet
197
     * @see  #getEntryIndexByFileName
198
     */
199
    @Override
200
    public PropertiesFileEntry getEntryByFileName(String fileName) {
201
        int index = getEntryIndexByFileName(fileName);
202
        try {
203
            return (index == -1) ? null : (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
204
        } catch (DataObjectNotFoundException ex) {
205
            Exceptions.printStackTrace(ex);
206
            return null;
207
        }
208
    }
209
210
    /**
211
     * Retrieves number of file entries.
212
     *
213
     * @return  number of file entries
214
     * @exception  java.lang.IllegalStateException
215
     *             if the list of entries has not been initialized yet
216
     */
217
    @Override
218
    public int getEntryCount() {
219
        if (files == null) {
220
            return 0;//super.getEntryCount();
221
//            notifyEntriesNotInitialized();
222
        }
223
        return files.length;
224
    }
225
226
    /**
227
     * Throws a runtime exception with a message that the entries
228
     * have not been initialized yet.
229
     *
230
     * @exception  java.lang.IllegalStateException  thrown always
231
     * @see  #updateEntries
232
     */
233
    private void notifyEntriesNotInitialized() {
234
        throw new IllegalStateException(
235
                "Resource Bundles: Entries not initialized");           //NOI18N
236
    }
237
238
    private static boolean isValidLocaleSuffix(String s) {
239
        // first char is _
240
        int n = s.length();
241
        String s1;
242
        // check first suffix - language (two chars)
243
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
244
            s1 = s.substring(1, 3).toLowerCase();
245
        // language must be followed by a valid country suffix or no suffix
246
        } else {
247
            return false;
248
        }
249
        // check second suffix - country (two chars)
250
        String s2;
251
        if (n == 3) {
252
            s2 = null;
253
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
254
            s2 = s.substring(4, 6).toUpperCase();
255
        // country may be followed by whatever additional suffix
256
        } else {
257
            return false;
258
        }
259
260
        Set<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
261
        if (!knownLanguages.contains(s1)) {
262
            return false;
263
        }
264
265
        if (s2 != null) {
266
            Set<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
267
            if (!knownCountries.contains(s2)) {
268
                return false;
269
            }
270
        }
271
        return true;
272
    }
273
    @Override
274
    public PropertiesOpen getOpenSupport() {
275
        synchronized (OPEN_SUPPORT_LOCK) {
276
            if (openSupport == null) {
277
                openSupport = new PropertiesOpen(this);
278
            }
279
            return openSupport;
280
        }
281
    }
282
283
    @Override
284
    public int getKeyCount() {
285
        try {
286
            return super.getKeyCount();
287
        } catch (IllegalStateException ie) {
288
            return 0;
289
        }
290
    }
291
}
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataLoader.java (-7 / +12 lines)
Lines 87-92 Link Here
87
    /** */
87
    /** */
88
    private static Set<String> knownCountries;
88
    private static Set<String> knownCountries;
89
89
90
    /** */
91
    private static boolean nestedView = false;
92
90
    /** Creates new PropertiesDataLoader. */
93
    /** Creates new PropertiesDataLoader. */
91
    public PropertiesDataLoader() {
94
    public PropertiesDataLoader() {
92
        super("org.netbeans.modules.properties.PropertiesDataObject"); // NOI18N
95
        super("org.netbeans.modules.properties.PropertiesDataObject"); // NOI18N
Lines 153-166 Link Here
153
             * corresponding to an existing file
156
             * corresponding to an existing file
154
             */
157
             */
155
            String fName = fo.getName();
158
            String fName = fo.getName();
156
            int index = fName.indexOf(PRB_SEPARATOR_CHAR);
159
            if (nestedView) {
157
            while (index != -1) {
160
                int index = fName.indexOf(PRB_SEPARATOR_CHAR);
158
                FileObject candidate = fo.getParent().getFileObject(
161
                while (index != -1) {
159
                        fName.substring(0, index), fo.getExt());
162
                    FileObject candidate = fo.getParent().getFileObject(
160
                if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
163
                            fName.substring(0, index), fo.getExt());
161
                    return candidate;
164
                    if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
165
                        return candidate;
166
                    }
167
                    index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
162
                }
168
                }
163
                index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
164
            }
169
            }
165
            return fo;
170
            return fo;
166
        } else {
171
        } else {
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java (-7 / +6 lines)
Lines 60-66 Link Here
60
import org.openide.loaders.DataFolder;
60
import org.openide.loaders.DataFolder;
61
import org.openide.loaders.DataNode;
61
import org.openide.loaders.DataNode;
62
import org.openide.loaders.DataObject;
62
import org.openide.loaders.DataObject;
63
import org.openide.loaders.FileEntry;
64
import org.openide.nodes.Children;
63
import org.openide.nodes.Children;
65
import org.openide.nodes.Node;
64
import org.openide.nodes.Node;
66
import org.openide.nodes.NodeTransfer;
65
import org.openide.nodes.NodeTransfer;
Lines 103-109 Link Here
103
    public PropertiesDataNode(DataObject dataObject, Children children) {
102
    public PropertiesDataNode(DataObject dataObject, Children children) {
104
        super(dataObject, children);
103
        super(dataObject, children);
105
        setIconBaseWithExtension("org/netbeans/modules/properties/propertiesObject.png"); // NOI18N
104
        setIconBaseWithExtension("org/netbeans/modules/properties/propertiesObject.png"); // NOI18N
106
        
107
        dataObjectListener = new NameUpdater();
105
        dataObjectListener = new NameUpdater();
108
        dataObject.addPropertyChangeListener(
106
        dataObject.addPropertyChangeListener(
109
                WeakListeners.propertyChange(dataObjectListener, dataObject));
107
                WeakListeners.propertyChange(dataObjectListener, dataObject));
Lines 321-334 Link Here
321
    } // End of NewLocaleType class.
319
    } // End of NewLocaleType class.
322
320
323
    private static boolean containsLocale(PropertiesDataObject propertiesDataObject, Locale locale) {
321
    private static boolean containsLocale(PropertiesDataObject propertiesDataObject, Locale locale) {
324
        FileObject file = propertiesDataObject.getPrimaryFile();
322
        FileObject file = propertiesDataObject.getBundleStructure().getNthEntry(0).getFile();
323
//        FileObject file = propertiesDataObject.getPrimaryFile();
325
        String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
324
        String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
326
        Iterator it = propertiesDataObject.secondaryEntries().iterator();
325
        BundleStructure structure = propertiesDataObject.getBundleStructure();
327
        while (it.hasNext()) {
326
        for (int i = 0; i<structure.getEntryCount();i++) {
328
            FileObject f = ((FileEntry)it.next()).getFile();
327
            FileObject f = structure.getNthEntry(i).getFile();
329
            if (newName.startsWith(f.getName()) && f.getName().length() > file.getName().length())
328
            if (newName.startsWith(f.getName()) && f.getName().length() > file.getName().length())
330
                file = f;
329
                file = f;
331
        }        
330
        }
332
        return file.getName().equals(newName);
331
        return file.getName().equals(newName);
333
    }
332
    }
334
}
333
}
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataObject.java (-44 / +67 lines)
Lines 38-47 Link Here
38
 * Version 2 license, then the option applies only if the new code is
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
39
 * made subject to such option by the copyright holder.
40
 */
40
 */
41
42
43
package org.netbeans.modules.properties;
41
package org.netbeans.modules.properties;
44
45
42
46
import java.beans.PropertyChangeEvent;
43
import java.beans.PropertyChangeEvent;
47
import java.beans.PropertyChangeListener;
44
import java.beans.PropertyChangeListener;
Lines 60-69 Link Here
60
import org.openide.loaders.DataNode;
57
import org.openide.loaders.DataNode;
61
import org.openide.loaders.DataObject;
58
import org.openide.loaders.DataObject;
62
import org.openide.loaders.DataObjectExistsException;
59
import org.openide.loaders.DataObjectExistsException;
60
import org.openide.loaders.DataObjectNotFoundException;
63
import org.openide.loaders.MultiDataObject;
61
import org.openide.loaders.MultiDataObject;
64
import org.openide.nodes.Children;
62
import org.openide.nodes.Children;
65
import org.openide.nodes.CookieSet;
63
import org.openide.nodes.CookieSet;
66
import org.openide.nodes.Node;
64
import org.openide.nodes.Node;
65
import org.openide.util.Exceptions;
67
import org.openide.util.Lookup;
66
import org.openide.util.Lookup;
68
import org.openide.util.WeakListeners;
67
import org.openide.util.WeakListeners;
69
import static java.util.logging.Level.FINER;
68
import static java.util.logging.Level.FINER;
Lines 79-90 Link Here
79
78
80
    /** Generated Serialized Version UID. */
79
    /** Generated Serialized Version UID. */
81
    static final long serialVersionUID = 4795737295255253334L;
80
    static final long serialVersionUID = 4795737295255253334L;
82
    
81
83
    static final Logger LOG = Logger.getLogger(PropertiesDataObject.class.getName());
82
    static final Logger LOG = Logger.getLogger(PropertiesDataObject.class.getName());
84
83
85
    /** Structural view of the dataobject */
84
    /** Structural view of the dataobject */
86
    private transient BundleStructure bundleStructure;
85
    private transient BundleStructure bundleStructure;
87
    
86
88
    /** Open support for this data object. Provides editable table view on bundle. */
87
    /** Open support for this data object. Provides editable table view on bundle. */
89
    private transient PropertiesOpen openSupport;
88
    private transient PropertiesOpen openSupport;
90
89
Lines 94-100 Link Here
94
    // Hack due having lock on secondaries, can't override handleCopy, handleMove at all.
93
    // Hack due having lock on secondaries, can't override handleCopy, handleMove at all.
95
    /** Suffix used by copying/moving dataObject. */
94
    /** Suffix used by copying/moving dataObject. */
96
    private transient String pasteSuffix;
95
    private transient String pasteSuffix;
97
    
96
98
    /** */
97
    /** */
99
    private Lookup lookup;
98
    private Lookup lookup;
100
99
Lines 110-116 Link Here
110
     *              for the specified file
109
     *              for the specified file
111
     */
110
     */
112
    public PropertiesDataObject(final FileObject primaryFile,
111
    public PropertiesDataObject(final FileObject primaryFile,
113
                                final PropertiesDataLoader loader)
112
            final PropertiesDataLoader loader)
114
            throws DataObjectExistsException {
113
            throws DataObjectExistsException {
115
        super(primaryFile, loader);
114
        super(primaryFile, loader);
116
        // use editor support
115
        // use editor support
Lines 122-133 Link Here
122
    PropertiesEncoding getEncoding() {
121
    PropertiesEncoding getEncoding() {
123
        return ((PropertiesDataLoader) getLoader()).getEncoding();
122
        return ((PropertiesDataLoader) getLoader()).getEncoding();
124
    }
123
    }
125
    
124
126
    @Override
125
    @Override
127
    public Lookup getLookup() {
126
    public Lookup getLookup() {
128
        return getCookieSet().getLookup();
127
        return getCookieSet().getLookup();
129
    }
128
    }
130
    
129
131
    /** Initializes the object. Used by construction and deserialized. */
130
    /** Initializes the object. Used by construction and deserialized. */
132
    private void initialize() {
131
    private void initialize() {
133
        bundleStructure = null;
132
        bundleStructure = null;
Lines 154-160 Link Here
154
    CookieSet getCookieSet0() {
153
    CookieSet getCookieSet0() {
155
        return getCookieSet();
154
        return getCookieSet();
156
    }
155
    }
157
    
156
158
    /** Copies primary and secondary files to new folder.
157
    /** Copies primary and secondary files to new folder.
159
     * Overrides superclass method.
158
     * Overrides superclass method.
160
     * @param df the new folder
159
     * @param df the new folder
Lines 175-181 Link Here
175
            pasteSuffix = null;
174
            pasteSuffix = null;
176
        }
175
        }
177
    }
176
    }
178
    
177
179
    /** Moves primary and secondary files to a new folder.
178
    /** Moves primary and secondary files to a new folder.
180
     * Overrides superclass method.
179
     * Overrides superclass method.
181
     * @param df the new folder
180
     * @param df the new folder
Lines 197-209 Link Here
197
196
198
        try {
197
        try {
199
            pasteSuffix = createPasteSuffix(df);
198
            pasteSuffix = createPasteSuffix(df);
200
        
199
201
            return super.handleMove(df);
200
            return super.handleMove(df);
202
        } finally {
201
        } finally {
203
            pasteSuffix = null;
202
            pasteSuffix = null;
204
        }
203
        }
205
    }
204
    }
206
    
205
207
    /** Gets suffix used by entries by copying/moving. */
206
    /** Gets suffix used by entries by copying/moving. */
208
    String getPasteSuffix() {
207
    String getPasteSuffix() {
209
        return pasteSuffix;
208
        return pasteSuffix;
Lines 215-221 Link Here
215
    void removeSecondaryEntry2(Entry fe) {
214
    void removeSecondaryEntry2(Entry fe) {
216
        if (LOG.isLoggable(FINER)) {
215
        if (LOG.isLoggable(FINER)) {
217
            LOG.finer("removeSecondaryEntry2(Entry "                    //NOI18N
216
            LOG.finer("removeSecondaryEntry2(Entry "                    //NOI18N
218
                      + FileUtil.getFileDisplayName(fe.getFile()) + ')');
217
                    + FileUtil.getFileDisplayName(fe.getFile()) + ')');
219
        }
218
        }
220
        removeSecondaryEntry (fe);
219
        removeSecondaryEntry (fe);
221
    }
220
    }
Lines 226-251 Link Here
226
        String basicName = getPrimaryFile().getName();
225
        String basicName = getPrimaryFile().getName();
227
226
228
        DataObject[] children = folder.getChildren();
227
        DataObject[] children = folder.getChildren();
229
        
228
230
        
229
231
        // Repeat until there is not such file name.
230
        // Repeat until there is not such file name.
232
        for(int i = 0; ; i++) {
231
        for(int i = 0; ; i++) {
233
            String newName;
232
            String newName;
234
            
233
235
            if (i == 0) {
234
            if (i == 0) {
236
                newName = basicName;
235
                newName = basicName;
237
            } else {
236
            } else {
238
                newName = basicName + i;
237
                newName = basicName + i;
239
            }
238
            }
240
            boolean exist = false;
239
            boolean exist = false;
241
            
240
242
            for(int j = 0; j < children.length; j++) {
241
            for(int j = 0; j < children.length; j++) {
243
                if(children[j] instanceof PropertiesDataObject && newName.equals(children[j].getName())) {
242
                if(children[j] instanceof PropertiesDataObject && newName.equals(children[j].getName())) {
244
                    exist = true;
243
                    exist = true;
245
                    break;
244
                    break;
246
                }
245
                }
247
            }
246
            }
248
                
247
249
            if(!exist) {
248
            if(!exist) {
250
                if (i == 0) {
249
                if (i == 0) {
251
                    return ""; // NOI18N
250
                    return ""; // NOI18N
Lines 258-270 Link Here
258
257
259
    /** Returns open support. It's used by all subentries as open support too. */
258
    /** Returns open support. It's used by all subentries as open support too. */
260
    public PropertiesOpen getOpenSupport() {
259
    public PropertiesOpen getOpenSupport() {
261
        synchronized(OPEN_SUPPORT_LOCK) {
260
//        synchronized (OPEN_SUPPORT_LOCK) {
262
            if(openSupport == null) {
261
            return ((MultiBundleStructure)getBundleStructure()).getOpenSupport();
263
                openSupport = new PropertiesOpen(this);
262
//            PropertiesDataObject dataObject = this;
264
            }
263
//            try {
265
264
//                dataObject = Util.findPrimaryDataObject(this);
266
            return openSupport;
265
//            } catch (DataObjectNotFoundException ex) {
267
        }
266
//                Exceptions.printStackTrace(ex);
267
//            }
268
//            if (this == dataObject) {
269
//                    if (openSupport == null) {
270
//                        openSupport = new PropertiesOpen(this);
271
//                    }
272
//
273
//                    return openSupport;
274
//            } else {
275
//                return dataObject.getOpenSupport();
276
//            }
277
//        }
268
    }
278
    }
269
279
270
    /** Updates modification status of this dataobject from its entries. */
280
    /** Updates modification status of this dataobject from its entries. */
Lines 294-300 Link Here
294
     *
304
     *
295
     * @return the node representation for this data object
305
     * @return the node representation for this data object
296
     * @see DataNode
306
     * @see DataNode
297
     */                                                           
307
     */
298
    @Override
308
    @Override
299
    protected Node createNodeDelegate () {
309
    protected Node createNodeDelegate () {
300
        return new PropertiesDataNode(this);
310
        return new PropertiesDataNode(this);
Lines 304-318 Link Here
304
        return new PropertiesChildren();
314
        return new PropertiesChildren();
305
    }
315
    }
306
316
317
    //TODO XXX Now it is always false
307
    boolean isMultiLocale() {
318
    boolean isMultiLocale() {
308
        return secondaryEntries().size() > 0;
319
        return secondaryEntries().size() > 0;
309
    }
320
    }
310
321
311
    /** Returns a structural view of this data object */
322
    /** Returns a structural view of this data object */
312
    public BundleStructure getBundleStructure() {
323
    public BundleStructure getBundleStructure() {
313
        if (bundleStructure == null)
324
        PropertiesDataObject dataObject = null;
314
            bundleStructure = new BundleStructure(this);
325
        try {
315
        return bundleStructure;
326
            dataObject = Util.findPrimaryDataObject(this);
327
        } catch (DataObjectNotFoundException ex) {
328
            Exceptions.printStackTrace(ex);
329
        }
330
        if (this == dataObject) {
331
            if (bundleStructure == null) {
332
                bundleStructure = new MultiBundleStructure(this);
333
                ((MultiBundleStructure)bundleStructure).updateEntries();
334
            }
335
            return bundleStructure;
336
        } else {
337
            return dataObject.getBundleStructure();
338
        }
316
    }
339
    }
317
340
318
    /** Comparator used for ordering secondary files, works over file names */
341
    /** Comparator used for ordering secondary files, works over file names */
Lines 326-339 Link Here
326
        LOG.finer("fireNameChange()");                                  //NOI18N
349
        LOG.finer("fireNameChange()");                                  //NOI18N
327
        firePropertyChange(PROP_NAME, null, null);
350
        firePropertyChange(PROP_NAME, null, null);
328
    }
351
    }
329
    
352
330
    /** Deserialization. */
353
    /** Deserialization. */
331
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
354
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
332
        in.defaultReadObject();
355
        in.defaultReadObject();
333
        initialize();
356
        initialize();
334
    }
357
    }
335
358
336
    
359
337
    /** Children of this <code>PropertiesDataObject</code>. */
360
    /** Children of this <code>PropertiesDataObject</code>. */
338
    private class PropertiesChildren extends Children.Keys<String> {
361
    private class PropertiesChildren extends Children.Keys<String> {
339
362
Lines 341-353 Link Here
341
        private PropertyChangeListener propertyListener = null;
364
        private PropertyChangeListener propertyListener = null;
342
        private PropertyChangeListener weakPropListener = null;
365
        private PropertyChangeListener weakPropListener = null;
343
366
344
        
367
345
        /** Constructor.*/
368
        /** Constructor.*/
346
        PropertiesChildren() {
369
        PropertiesChildren() {
347
            super();
370
            super();
348
        }
371
        }
349
372
350
        
373
351
        /** Sets all keys in the correct order */
374
        /** Sets all keys in the correct order */
352
        protected void mySetKeys() {
375
        protected void mySetKeys() {
353
            TreeSet<String> newKeys = new TreeSet<String>(new Comparator<String>() {
376
            TreeSet<String> newKeys = new TreeSet<String>(new Comparator<String>() {
Lines 366-372 Link Here
366
            });
389
            });
367
390
368
            newKeys.add(getPrimaryEntry().getFile().getName());
391
            newKeys.add(getPrimaryEntry().getFile().getName());
369
            
392
370
            for (Entry entry : secondaryEntries()) {
393
            for (Entry entry : secondaryEntries()) {
371
                newKeys.add(entry.getFile().getName());
394
                newKeys.add(entry.getFile().getName());
372
            }
395
            }
Lines 379-392 Link Here
379
        @Override
402
        @Override
380
        protected void addNotify () {
403
        protected void addNotify () {
381
            mySetKeys();
404
            mySetKeys();
382
            
405
383
            // listener
406
            // listener
384
            if(propertyListener == null) {
407
            if(propertyListener == null) {
385
                propertyListener = new PropertyChangeListener () {
408
                propertyListener = new PropertyChangeListener () {
386
                    public void propertyChange(PropertyChangeEvent evt) {
409
                    public void propertyChange(PropertyChangeEvent evt) {
387
                        if(PROP_FILES.equals(evt.getPropertyName())) {
410
                        if(PROP_FILES.equals(evt.getPropertyName())) {
388
                            if (isMultiLocale()) {
411
                            if (isMultiLocale()) {
389
                            mySetKeys();
412
                                mySetKeys();
390
                            } else {
413
                            } else {
391
                                // These children are only used for two or more locales.
414
                                // These children are only used for two or more locales.
392
                                // If only default locale is left, disconnect the listener.
415
                                // If only default locale is left, disconnect the listener.
Lines 395-405 Link Here
395
                                if (propertyListener != null) {
418
                                if (propertyListener != null) {
396
                                    PropertiesDataObject.this.removePropertyChangeListener(weakPropListener);
419
                                    PropertiesDataObject.this.removePropertyChangeListener(weakPropListener);
397
                                    propertyListener = null;
420
                                    propertyListener = null;
421
                                }
422
                            }
398
                        }
423
                        }
399
                    }
424
                    }
400
                        }
425
                };
401
                    }
402
                }; 
403
                weakPropListener = WeakListeners.propertyChange(propertyListener, PropertiesDataObject.this);
426
                weakPropListener = WeakListeners.propertyChange(propertyListener, PropertiesDataObject.this);
404
                PropertiesDataObject.this.addPropertyChangeListener(weakPropListener);
427
                PropertiesDataObject.this.addPropertyChangeListener(weakPropListener);
405
            }
428
            }
Lines 419-438 Link Here
419
            if (entryName == null) {
442
            if (entryName == null) {
420
                return null;
443
                return null;
421
            }
444
            }
422
            
445
423
            PropertiesFileEntry entry = (PropertiesFileEntry)getPrimaryEntry();
446
            PropertiesFileEntry entry = (PropertiesFileEntry)getPrimaryEntry();
424
            
447
425
            if(entryName.equals(entry.getFile().getName())) {
448
            if(entryName.equals(entry.getFile().getName())) {
426
                return new Node[] {entry.getNodeDelegate()};
449
                return new Node[] {entry.getNodeDelegate()};
427
            }
450
            }
428
            for(Iterator<Entry> it = secondaryEntries().iterator();it.hasNext();) {
451
            for(Iterator<Entry> it = secondaryEntries().iterator();it.hasNext();) {
429
                entry = (PropertiesFileEntry)it.next();
452
                entry = (PropertiesFileEntry)it.next();
430
                
453
431
                if (entryName.equals(entry.getFile().getName())) {
454
                if (entryName.equals(entry.getFile().getName())) {
432
                    return new Node[] {entry.getNodeDelegate()};
455
                    return new Node[] {entry.getNodeDelegate()};
433
                }
456
                }
434
            }
457
            }
435
                
458
436
            return null;
459
            return null;
437
        }
460
        }
438
461
(-)a/properties/src/org/netbeans/modules/properties/PropertiesOpen.java (-93 / +295 lines)
Lines 57-64 Link Here
57
import java.io.ObjectInput;
57
import java.io.ObjectInput;
58
import java.io.ObjectOutput;
58
import java.io.ObjectOutput;
59
import java.io.Serializable;
59
import java.io.Serializable;
60
import java.util.ArrayList;
60
import java.util.Enumeration;
61
import java.util.Enumeration;
62
import java.util.HashMap;
61
import java.util.Iterator;
63
import java.util.Iterator;
64
import java.util.List;
62
import javax.swing.Action;
65
import javax.swing.Action;
63
import javax.swing.event.ChangeListener;
66
import javax.swing.event.ChangeListener;
64
import javax.swing.JPanel;
67
import javax.swing.JPanel;
Lines 91-97 Link Here
91
import org.openide.util.actions.SystemAction;
94
import org.openide.util.actions.SystemAction;
92
import org.openide.windows.CloneableOpenSupport;
95
import org.openide.windows.CloneableOpenSupport;
93
import org.openide.windows.CloneableTopComponent;
96
import org.openide.windows.CloneableTopComponent;
94
import org.openide.util.Utilities;
95
import org.openide.DialogDescriptor;
97
import org.openide.DialogDescriptor;
96
import org.openide.filesystems.FileUtil;
98
import org.openide.filesystems.FileUtil;
97
99
Lines 105-112 Link Here
105
                            implements OpenCookie, CloseCookie {
107
                            implements OpenCookie, CloseCookie {
106
108
107
    /** Main properties dataobject */
109
    /** Main properties dataobject */
110
    @Deprecated
108
    PropertiesDataObject propDataObject;
111
    PropertiesDataObject propDataObject;
109
    
112
113
114
    private List<PropertiesDataObject> dataObjectList;
115
116
    private BundleStructure bundleStructure;
110
    /** Listener for modificationc on dataobject, adding and removing save cookie */
117
    /** Listener for modificationc on dataobject, adding and removing save cookie */
111
    PropertyChangeListener modifL;
118
    PropertyChangeListener modifL;
112
119
Lines 118-133 Link Here
118
    
125
    
119
126
120
    /** Constructor */
127
    /** Constructor */
128
    @Deprecated
121
    public PropertiesOpen(PropertiesDataObject propDataObject) {
129
    public PropertiesOpen(PropertiesDataObject propDataObject) {
122
        super(new Environment(propDataObject));
130
        super(new Environment(propDataObject));
123
        
131
        
124
        this.propDataObject = propDataObject;
132
        this.propDataObject = propDataObject;
125
        
133
126
        this.propDataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL = 
134
        //PENDING Add Listeners for all DataObject from this OpenSupport
135
        this.propDataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL =
127
            new ModifiedListener(), this.propDataObject));
136
            new ModifiedListener(), this.propDataObject));
128
    }
137
    }
129
138
139
    public PropertiesOpen(BundleStructure structure) {
140
        super(new Environment(structure));
130
141
142
        this.bundleStructure = structure;
143
        addModifiedListeners();
144
    }
145
146
    private void addModifiedListeners() {
147
        BundleStructure structure = bundleStructure;
148
        dataObjectList = new ArrayList<PropertiesDataObject>();
149
        PropertiesDataObject dataObject;
150
        modifL = new ModifiedListener();
151
        for (int i=0;i<structure.getEntryCount();i++) {
152
            dataObject = (PropertiesDataObject) structure.getNthEntry(i).getDataObject();
153
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
154
            dataObjectList.add(dataObject);
155
        }
156
    }
157
158
    protected void addDataObject(PropertiesDataObject dataObject) {
159
        dataObject.removePropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
160
        dataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
161
        env = new Environment(bundleStructure);
162
        PropertiesCloneableTopComponent topComp = (PropertiesCloneableTopComponent) allEditors.getArbitraryComponent();
163
        if (topComp != null) {
164
            topComp.dataObjectAdded(dataObject);
165
        }
166
        dataObjectList.add(dataObject);
167
}
131
    /** 
168
    /** 
132
     * Tests whether all data is saved, and if not, prompts the user to save.
169
     * Tests whether all data is saved, and if not, prompts the user to save.
133
     *
170
     *
Lines 135-142 Link Here
135
     */
172
     */
136
    @Override
173
    @Override
137
    protected boolean canClose() {
174
    protected boolean canClose() {
138
        SaveCookie saveCookie = propDataObject.getCookie(SaveCookie.class);
175
        PropertiesDataObject dataObject;
139
        if (saveCookie == null) {
176
        SaveCookie saveCookie = null;
177
        HashMap<SaveCookie,PropertiesDataObject> map = new HashMap<SaveCookie,PropertiesDataObject>();
178
        for (int i=0;i<bundleStructure.getEntryCount();i++) {
179
            dataObject = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
180
            saveCookie = dataObject.getCookie(SaveCookie.class);
181
            //Need to find all saveCookie
182
            if (saveCookie != null) map.put(saveCookie, dataObject);
183
        }
184
        if (map.isEmpty()) {
140
            return true;
185
            return true;
141
        }
186
        }
142
        stopEditing();
187
        stopEditing();
Lines 149-155 Link Here
149
                                           "CTL_Question");         //NOI18N
194
                                           "CTL_Question");         //NOI18N
150
        String question = NbBundle.getMessage(PropertiesOpen.class,
195
        String question = NbBundle.getMessage(PropertiesOpen.class,
151
                                              "MSG_SaveFile",       //NOI18N
196
                                              "MSG_SaveFile",       //NOI18N
152
                                              propDataObject.getName());
197
                                              bundleStructure.getNthEntry(0).getName());
153
        String optionSave = NbBundle.getMessage(PropertiesOpen.class,
198
        String optionSave = NbBundle.getMessage(PropertiesOpen.class,
154
                                                "CTL_Save");        //NOI18N
199
                                                "CTL_Save");        //NOI18N
155
        String optionDiscard = NbBundle.getMessage(PropertiesOpen.class,
200
        String optionDiscard = NbBundle.getMessage(PropertiesOpen.class,
Lines 171-185 Link Here
171
        /* Save the file if the answer was "Save": */
216
        /* Save the file if the answer was "Save": */
172
        if (answer == optionSave) {
217
        if (answer == optionSave) {
173
            try {
218
            try {
174
                saveCookie.save();
219
                for (SaveCookie save : map.keySet()) {
175
                propDataObject.updateModificationStatus();
220
                    save.save();
221
                    map.get(save).updateModificationStatus();
222
                }
176
            }
223
            }
177
            catch (IOException e) {
224
            catch (IOException e) {
178
                ErrorManager.getDefault().notify(e);
225
                ErrorManager.getDefault().notify(e);
179
                return false;
226
                return false;
180
            }
227
            }
181
        }
228
        }
182
        propDataObject.updateModificationStatus();
229
        dataObject = null;
230
        for (int i=0;i<bundleStructure.getEntryCount();i++) {
231
            dataObject = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
232
            dataObject.updateModificationStatus();
233
        }
183
234
184
        return (answer == optionSave || answer == optionDiscard);
235
        return (answer == optionSave || answer == optionDiscard);
185
    }
236
    }
Lines 215-221 Link Here
215
     * @return the cloneable top component for this support
266
     * @return the cloneable top component for this support
216
     */
267
     */
217
    protected CloneableTopComponent createCloneableTopComponent() {
268
    protected CloneableTopComponent createCloneableTopComponent() {
218
        return new PropertiesCloneableTopComponent(propDataObject);
269
//        return new PropertiesCloneableTopComponent(propDataObject);
270
        return new PropertiesCloneableTopComponent(bundleStructure);
219
    }
271
    }
220
272
221
    /**
273
    /**
Lines 225-232 Link Here
225
     */
277
     */
226
    protected String messageOpening() {
278
    protected String messageOpening() {
227
        return NbBundle.getMessage(PropertiesOpen.class, "LBL_ObjectOpen", // NOI18N
279
        return NbBundle.getMessage(PropertiesOpen.class, "LBL_ObjectOpen", // NOI18N
228
            propDataObject.getName(),
280
            bundleStructure.getNthEntry(0).getName(),
229
            propDataObject.getPrimaryFile().toString()
281
            bundleStructure.getNthEntry(0).getFile().toString()
230
        );
282
        );
231
    }
283
    }
232
284
Lines 249-263 Link Here
249
        if (undoRedoManager != null) {
301
        if (undoRedoManager != null) {
250
            return undoRedoManager;
302
            return undoRedoManager;
251
        } else {
303
        } else {
252
            return new CompoundUndoRedoManager(propDataObject);
304
            return new CompoundUndoRedoManager(bundleStructure);
253
        }
305
        }
254
    }
306
    }
255
307
256
    /** Helper method. Closes documents. */
308
    /** Helper method. Closes documents. */
257
    private synchronized void closeDocuments() {
309
    private synchronized void closeDocuments() {
258
        closeEntry((PropertiesFileEntry)propDataObject.getPrimaryEntry());
310
        BundleStructure structure = bundleStructure;
259
        for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext(); ) {
311
        for (int i = 0; i< structure.getEntryCount(); i++) {
260
            closeEntry((PropertiesFileEntry)it.next());
312
            closeEntry(structure.getNthEntry(i));
261
        }
313
        }
262
    }
314
    }
263
315
Lines 278-284 Link Here
278
        }
330
        }
279
    }
331
    }
280
332
281
    /** 
333
    /**
282
     * Helper method. Should be called only if the object has SaveCookie
334
     * Helper method. Should be called only if the object has SaveCookie
283
     * @return true if closing this editor whithout saving would result in loss of data
335
     * @return true if closing this editor whithout saving would result in loss of data
284
     *  because al least one of the modified files is not open in the code editor
336
     *  because al least one of the modified files is not open in the code editor
Lines 286-300 Link Here
286
    private boolean shouldAskSave() {
338
    private boolean shouldAskSave() {
287
        // for each entry : if there is a SaveCookie and no open editor component, return true.
339
        // for each entry : if there is a SaveCookie and no open editor component, return true.
288
        // if passed for all entries, return false
340
        // if passed for all entries, return false
289
        PropertiesFileEntry entry = (PropertiesFileEntry)propDataObject.getPrimaryEntry();
341
        BundleStructure structure = bundleStructure;
290
        SaveCookie savec = entry.getCookie(SaveCookie.class);
342
        PropertiesFileEntry entry;
291
        
343
        SaveCookie savec;
292
        if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
344
        for (int i = 0; i < structure.getEntryCount(); i++) {
293
            return true;
345
            entry = structure.getNthEntry(i);
294
        }
295
296
        for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext(); ) {
297
            entry = (PropertiesFileEntry)it.next();
298
            savec = entry.getCookie(SaveCookie.class);
346
            savec = entry.getCookie(SaveCookie.class);
299
            if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
347
            if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
300
                return true;
348
                return true;
Lines 303-309 Link Here
303
        return false;
351
        return false;
304
    }
352
    }
305
353
306
    
354
307
    /** Environment that connects the open support together with {@code DataObject}. */
355
    /** Environment that connects the open support together with {@code DataObject}. */
308
    private static class Environment implements CloneableOpenSupport.Env, Serializable,
356
    private static class Environment implements CloneableOpenSupport.Env, Serializable,
309
        PropertyChangeListener, VetoableChangeListener {
357
        PropertyChangeListener, VetoableChangeListener {
Lines 312-318 Link Here
312
        static final long serialVersionUID = -1934890789745432531L;
360
        static final long serialVersionUID = -1934890789745432531L;
313
        
361
        
314
        /** Object to serialize and be connected to. */
362
        /** Object to serialize and be connected to. */
363
        @Deprecated
315
        private DataObject dataObject;
364
        private DataObject dataObject;
365
366
        private BundleStructure bundleStructure;
316
        
367
        
317
        /** Support for firing of property changes. */
368
        /** Support for firing of property changes. */
318
        private transient PropertyChangeSupport propSupp;
369
        private transient PropertyChangeSupport propSupp;
Lines 327-339 Link Here
327
         * are also rethrown to own listeners.
378
         * are also rethrown to own listeners.
328
         * @param dataObject data object to be attached to
379
         * @param dataObject data object to be attached to
329
         */
380
         */
381
        @Deprecated
330
        public Environment(PropertiesDataObject dataObject) {
382
        public Environment(PropertiesDataObject dataObject) {
331
            this.dataObject = dataObject;
383
            this.dataObject = dataObject;
332
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObject));
384
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObject));
333
            dataObject.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObject));
385
            dataObject.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObject));
334
        }
386
        }
335
387
336
        
388
        public Environment(BundleStructure structure) {
389
            this.bundleStructure = structure;
390
            dataObject = bundleStructure.getNthEntry(0).getDataObject();
391
            addListeners();
392
        }
393
394
395
        private void addListeners() {
396
            BundleStructure structure = bundleStructure;
397
            PropertiesDataObject dataObj;
398
            for(int i=0;i<structure.getEntryCount();i++) {
399
                dataObj = (PropertiesDataObject) structure.getNthEntry(i).getDataObject();
400
                dataObj.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObj));
401
                dataObj.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObj));
402
            }
403
404
        }
337
        /** Implements {@code CloneableOpenSupport.Env} interface. Adds property listener. */
405
        /** Implements {@code CloneableOpenSupport.Env} interface. Adds property listener. */
338
        public void addPropertyChangeListener(PropertyChangeListener l) {
406
        public void addPropertyChangeListener(PropertyChangeListener l) {
339
            prop().addPropertyChangeListener(l);
407
            prop().addPropertyChangeListener(l);
Lines 354-370 Link Here
354
            veto().removeVetoableChangeListener(l);
422
            veto().removeVetoableChangeListener(l);
355
        }
423
        }
356
424
357
        /** 
425
        /**
358
         * Implements {@code CloneableOpenSupport} interface.
426
         * Implements {@code CloneableOpenSupport} interface.
359
         * Method that allows environment to find its cloneable open support.
427
         * Method that allows environment to find its cloneable open support.
360
         * @return the support or null if the environemnt is not in valid 
428
         * @return the support or null if the environemnt is not in valid 
361
         * state and the CloneableOpenSupport cannot be found for associated
429
         * state and the CloneableOpenSupport cannot be found for associated
362
         * data object
430
         * data object
363
         */
431
         */
432
        @Deprecated
433
        //TODO PENDING Called from super class need to preserve
364
        public CloneableOpenSupport findCloneableOpenSupport() {
434
        public CloneableOpenSupport findCloneableOpenSupport() {
435
            return (CloneableOpenSupport) dataObject.getCookie(OpenCookie.class);
436
        }
437
438
        public CloneableOpenSupport findCloneableOpenSupport(PropertiesDataObject dataObject) {
365
            return (CloneableOpenSupport)dataObject.getCookie(OpenCookie.class);
439
            return (CloneableOpenSupport)dataObject.getCookie(OpenCookie.class);
366
        }
440
        }
367
        
441
368
        /** 
442
        /** 
369
         * Implements {@code CloneableOpenSupport.Env} interface.
443
         * Implements {@code CloneableOpenSupport.Env} interface.
370
         * Test whether the support is in valid state or not.
444
         * Test whether the support is in valid state or not.
Lines 372-380 Link Here
372
         * referenced to does not exist anymore.
446
         * referenced to does not exist anymore.
373
         * @return true or false depending on its state
447
         * @return true or false depending on its state
374
         */
448
         */
449
        @Deprecated
375
        public boolean isValid() {
450
        public boolean isValid() {
376
            return dataObject.isValid();
451
            return dataObject.isValid();
377
        }
452
        }
453
454
        public boolean isValid(PropertiesDataObject dataObject) {
455
            return dataObject.isValid();
456
        }
457
378
        
458
        
379
        /**
459
        /**
380
         * Implements {@code CloneableOpenSupport.Env} interface. 
460
         * Implements {@code CloneableOpenSupport.Env} interface. 
Lines 382-387 Link Here
382
         * @return true if the object is modified
462
         * @return true if the object is modified
383
         */
463
         */
384
        public boolean isModified() {
464
        public boolean isModified() {
465
            //if one dataObject is modified assume that everything modified
466
            for (int i=0; i < bundleStructure.getEntryCount();i++) {
467
                if (bundleStructure.getNthEntry(i).getDataObject().isModified()) {
468
                    return true;
469
                }
470
            }
471
            return false;
472
        }
473
474
        public boolean isModified(PropertiesDataObject dataObject) {
385
            return dataObject.isModified();
475
            return dataObject.isModified();
386
        }
476
        }
387
477
Lines 392-406 Link Here
392
         *   (for example when the file is readonly), when such exception
482
         *   (for example when the file is readonly), when such exception
393
         *   is the support should discard all previous changes
483
         *   is the support should discard all previous changes
394
         */
484
         */
485
        @Deprecated
395
        public void markModified() throws java.io.IOException {
486
        public void markModified() throws java.io.IOException {
396
            dataObject.setModified(true);
487
            dataObject.setModified(true);
397
        }
488
        }
398
        
489
490
        public void markModified(PropertiesDataObject dataObject) throws java.io.IOException {
491
            dataObject.setModified(true);
492
        }
399
        /** 
493
        /** 
400
         * Implements {@code CloneableOpenSupport.Env} interface.
494
         * Implements {@code CloneableOpenSupport.Env} interface.
401
         * Reverse method that can be called to make the environment unmodified.
495
         * Reverse method that can be called to make the environment unmodified.
402
         */
496
         */
497
        @Deprecated
403
        public void unmarkModified() {
498
        public void unmarkModified() {
499
            dataObject.setModified(false);
500
        }
501
502
        public void unmarkModified(PropertiesDataObject dataObject) {
404
            dataObject.setModified(false);
503
            dataObject.setModified(false);
405
        }
504
        }
406
        
505
        
Lines 410-419 Link Here
410
         */
509
         */
411
        public void propertyChange(PropertyChangeEvent evt) {
510
        public void propertyChange(PropertyChangeEvent evt) {
412
            if(DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
511
            if(DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
413
                if(dataObject.isModified()) {
512
                PropertiesDataObject dataObj = null;
414
                    dataObject.addVetoableChangeListener(this);
513
                if (evt.getSource() instanceof PropertiesDataObject) {
415
                } else {
514
                    dataObj = (PropertiesDataObject) evt.getSource();
416
                    dataObject.removeVetoableChangeListener(this);
515
                }
516
                if (dataObj!=null) {
517
                    if(dataObj.isModified()) {
518
                        dataObj.addVetoableChangeListener(this);
519
                    } else {
520
                        dataObj.removeVetoableChangeListener(this);
521
                    }
417
                }
522
                }
418
            } else if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) { 
523
            } else if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) { 
419
                // We will handle the object invalidation here.
524
                // We will handle the object invalidation here.
Lines 422-436 Link Here
422
                    return;
527
                    return;
423
                }
528
                }
424
529
530
                PropertiesDataObject dataObj = null;
531
                if (evt.getSource() instanceof PropertiesDataObject) {
532
                    dataObj = (PropertiesDataObject) evt.getSource();
533
                }
534
                if (dataObj != null) {
535
                    bundleStructure.updateEntries();
536
                    bundleStructure.notifyOneFileChanged(dataObj.getPrimaryFile());
537
                    if (bundleStructure.getEntryCount() == 0) {
425
                // Loosing validity.
538
                // Loosing validity.
426
                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
539
//                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
427
                if(support != null) {
540
                        PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport(dataObj);
541
                        if(support != null ) {
428
                    
542
                    
429
                    // Mark the object as not being modified, so nobody
543
                            // Mark the object as not being modified, so nobody
430
                    // will ask for save.
544
                            // will ask for save.
431
                    unmarkModified();
545
                            unmarkModified((PropertiesDataObject) evt.getSource());
432
                    
546
                    
433
                    support.close(false);
547
                            support.close(false);
548
                        }
549
                    }
434
                }
550
                }
435
            } else {
551
            } else {
436
                firePropertyChange (
552
                firePropertyChange (
Lines 496-515 Link Here
496
    /** Inner class. Listens to modifications and updates save cookie. */
612
    /** Inner class. Listens to modifications and updates save cookie. */
497
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
613
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
498
614
615
499
        /** Gives notification that the DataObject was changed.
616
        /** Gives notification that the DataObject was changed.
500
        * @param ev PropertyChangeEvent
617
        * @param ev PropertyChangeEvent
501
        */
618
        */
502
        public void propertyChange(PropertyChangeEvent evt) {
619
        public void propertyChange(PropertyChangeEvent evt) {
503
            // Data object changed, reset the UndoRedo manager.
620
            // Data object changed, reset the UndoRedo manager.
504
            if (evt.getSource().equals(propDataObject)) {
621
            if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
505
                ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(propDataObject);
622
                if (evt.getSource() instanceof  PropertiesDataObject) {
506
            }
623
                    PropertiesDataObject dataObject = (PropertiesDataObject) evt.getSource();
507
624
                    if(bundleStructure.getEntryByFileName(dataObject.getName())!=null) {
508
            if ((evt.getSource() == propDataObject) && (DataObject.PROP_MODIFIED.equals(evt.getPropertyName()))) {
625
                        ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(bundleStructure);
509
                if (((Boolean)evt.getNewValue()).booleanValue()) {
626
                            if (((Boolean)evt.getNewValue()).booleanValue()) {
510
                    addSaveCookie();
627
                                addSaveCookie(dataObject);
511
                } else {
628
                            } else {
512
                    removeSaveCookie();
629
                                removeSaveCookie(dataObject);
630
                            }
631
                     }
513
                }
632
                }
514
            }
633
            }
515
        }
634
        }
Lines 538-551 Link Here
538
        * @exception IOException on I/O error
657
        * @exception IOException on I/O error
539
        */
658
        */
540
        public void saveDocument() throws IOException {
659
        public void saveDocument() throws IOException {
541
            PropertiesFileEntry pfe = (PropertiesFileEntry)propDataObject.getPrimaryEntry();
660
            BundleStructure structure = bundleStructure;
542
            SaveCookie save = pfe.getCookie(SaveCookie.class);
661
            SaveCookie save;
543
            if (save != null) {
662
            for (int i=0; i<structure.getEntryCount();i++) {
544
                save.save();
663
                save = structure.getNthEntry(i).getCookie(SaveCookie.class);
545
            }
546
547
            for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext();) {
548
                save = ((PropertiesFileEntry) it.next()).getCookie(SaveCookie.class);
549
                if (save != null) {
664
                if (save != null) {
550
                    save.save();
665
                    save.save();
551
                }
666
                }
Lines 553-566 Link Here
553
        }
668
        }
554
669
555
        /** Adds save cookie to the dataobject. */
670
        /** Adds save cookie to the dataobject. */
671
        @Deprecated
556
        private void addSaveCookie() {
672
        private void addSaveCookie() {
673
            if(propDataObject.getCookie(SaveCookie.class) == null) {
674
                propDataObject.getCookieSet0().add(this);
675
            }
676
        }
677
678
        private void addSaveCookie(PropertiesDataObject propDataObject) {
557
            if(propDataObject.getCookie(SaveCookie.class) == null) {
679
            if(propDataObject.getCookie(SaveCookie.class) == null) {
558
                propDataObject.getCookieSet0().add(this);
680
                propDataObject.getCookieSet0().add(this);
559
            }
681
            }
560
        }
682
        }
561
        
683
        
562
        /** Removes save cookie from the dataobject. */
684
        /** Removes save cookie from the dataobject. */
685
        @Deprecated
563
        private void removeSaveCookie() {
686
        private void removeSaveCookie() {
687
            if(propDataObject.getCookie(SaveCookie.class) == this) {
688
                propDataObject.getCookieSet0().remove(this);
689
            }
690
        }
691
692
        private void removeSaveCookie(PropertiesDataObject propDataObject) {
564
            if(propDataObject.getCookie(SaveCookie.class) == this) {
693
            if(propDataObject.getCookie(SaveCookie.class) == this) {
565
                propDataObject.getCookieSet0().remove(this);
694
                propDataObject.getCookieSet0().remove(this);
566
            }
695
            }
Lines 597-603 Link Here
597
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
726
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
598
            editor.requestActive();
727
            editor.requestActive();
599
            
728
            
600
            BundleStructure bs = propDataObject.getBundleStructure();
729
            BundleStructure bs = bundleStructure;
730
            bs.updateEntries();
601
            // Find indexes.
731
            // Find indexes.
602
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
732
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
603
            int rowIndex   = bs.getKeyIndexByName(key);
733
            int rowIndex   = bs.getKeyIndexByName(key);
Lines 618-625 Link Here
618
                        }
748
                        }
619
749
620
                        // Update selection & edit.
750
                        // Update selection & edit.
621
                        table.getColumnModel().getSelectionModel().setSelectionInterval(row, column);
751
//XXX This caused to open properties for editing with wrong values
622
                        table.getSelectionModel().setSelectionInterval(row, column);
752
//                        table.getColumnModel().getSelectionModel().setSelectionInterval(row, column);
753
//                        table.getSelectionModel().setSelectionInterval(row, column);
623
754
624
                        table.editCellAt(row, column);
755
                        table.editCellAt(row, column);
625
                    }
756
                    }
Lines 633-644 Link Here
633
    public static class PropertiesCloneableTopComponent extends CloneableTopComponent {
764
    public static class PropertiesCloneableTopComponent extends CloneableTopComponent {
634
765
635
        /** Reference to underlying {@code PropertiesDataObject}. */
766
        /** Reference to underlying {@code PropertiesDataObject}. */
767
        @Deprecated
636
        private PropertiesDataObject propDataObject;
768
        private PropertiesDataObject propDataObject;
637
        
769
770
        private PropertiesDataObject[] dataObjecs;
638
        /** Listener for changes on {@code propDataObject} name and cookie properties.
771
        /** Listener for changes on {@code propDataObject} name and cookie properties.
639
         * Changes display name of components accordingly. */
772
         * Changes display name of components accordingly. */
640
        private transient PropertyChangeListener dataObjectListener;
773
        private transient PropertyChangeListener dataObjectListener;
641
        
774
775
        private transient static HashMap<PropertiesDataObject,PropertyChangeListener> weakListeners;
776
642
        /** Generated serial version UID. */
777
        /** Generated serial version UID. */
643
        static final long serialVersionUID =2836248291419024296L;
778
        static final long serialVersionUID =2836248291419024296L;
644
        
779
        
Lines 649-660 Link Here
649
        
784
        
650
        /** Constructor.
785
        /** Constructor.
651
        * @param propDataObject data object we belong to */
786
        * @param propDataObject data object we belong to */
787
        @Deprecated
652
        public PropertiesCloneableTopComponent (PropertiesDataObject propDataObject) {
788
        public PropertiesCloneableTopComponent (PropertiesDataObject propDataObject) {
653
            this.propDataObject  = propDataObject;
789
            this.propDataObject  = propDataObject;
654
790
655
            initialize();
791
            initialize();
656
        }
792
        }
657
793
794
        private MultiBundleStructure bundleStructure;
795
796
        public PropertiesCloneableTopComponent(BundleStructure structure) {
797
            this.bundleStructure = (MultiBundleStructure) structure;
798
            propDataObject = (PropertiesDataObject) bundleStructure.getNthEntry(0).getDataObject();
799
            dataObjecs = new PropertiesDataObject[bundleStructure.getEntryCount()];
800
            for (int i=0; i<bundleStructure.getEntryCount();i++) {
801
                dataObjecs[i] = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
802
            }
803
            weakListeners = new HashMap<PropertiesDataObject, PropertyChangeListener>();
804
            initialize();
805
        }
658
        /**
806
        /**
659
         */
807
         */
660
        @Override
808
        @Override
Lines 681-694 Link Here
681
        private void initialize() {
829
        private void initialize() {
682
            initComponents();
830
            initComponents();
683
            setupActions();
831
            setupActions();
684
            setActivatedNodes(new Node[] {propDataObject.getNodeDelegate()});
832
            BundleStructure structure = bundleStructure;
833
            PropertiesDataObject dataObject;
685
834
835
            Node[] node = new Node[structure.getEntryCount()];
686
            dataObjectListener = new NameUpdater();
836
            dataObjectListener = new NameUpdater();
687
            propDataObject.addPropertyChangeListener(
837
688
                    WeakListeners.propertyChange(dataObjectListener,
838
            for( int i=0; i<structure.getEntryCount();i++) {
689
                                                 propDataObject));
839
                    dataObject = dataObjecs[i];//(PropertiesDataObject) structure.getNthEntry(i).getDataObject();
840
                    node[i] = dataObject.getNodeDelegate();
841
                    weakListeners.put(dataObject,WeakListeners.propertyChange(dataObjectListener, dataObject));
842
                    dataObject.addPropertyChangeListener(weakListeners.get(dataObject));
843
            }
690
            
844
            
845
            setActivatedNodes(node);
846
691
            updateName();
847
            updateName();
848
        }
849
850
        /**
851
         * Called from PropertiesOpen when new DataObject added
852
         * @param dataObject to add listener to
853
         */
854
        protected void dataObjectAdded(PropertiesDataObject dataObject) {
855
            dataObject.removePropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
856
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
692
        }
857
        }
693
        
858
        
694
        /* Based on class DataNode.PropL. */
859
        /* Based on class DataNode.PropL. */
Lines 710-716 Link Here
710
            
875
            
711
            /** */
876
            /** */
712
            private final int action;
877
            private final int action;
713
            
878
714
            /**
879
            /**
715
             */
880
             */
716
            NameUpdater() {
881
            NameUpdater() {
Lines 730-736 Link Here
730
                    previous.removeFileStatusListener(weakL);
895
                    previous.removeFileStatusListener(weakL);
731
                }
896
                }
732
                try {
897
                try {
733
                    previous = propDataObject.getPrimaryFile().getFileSystem();
898
                    previous = bundleStructure.getNthEntry(0).getFile().getFileSystem();
734
                    if (weakL == null) {
899
                    if (weakL == null) {
735
                        weakL = org.openide.filesystems.FileUtil
900
                        weakL = org.openide.filesystems.FileUtil
736
                                .weakFileStatusListener(this, previous);
901
                                .weakFileStatusListener(this, previous);
Lines 750-757 Link Here
750
                }
915
                }
751
                
916
                
752
                boolean thisChanged = false;
917
                boolean thisChanged = false;
753
                for (FileObject fo : propDataObject.files()) {
918
                for (int i=0;i<bundleStructure.getEntryCount();i++) {
754
                    if (ev.hasChanged(fo)) {
919
                    if(ev.hasChanged(bundleStructure.getNthEntry(i).getFile())) {
755
                        thisChanged = true;
920
                        thisChanged = true;
756
                        break;
921
                        break;
757
                    }
922
                    }
Lines 765-771 Link Here
765
            /**
930
            /**
766
             */
931
             */
767
            public void propertyChange(PropertyChangeEvent e) {
932
            public void propertyChange(PropertyChangeEvent e) {
768
                if (!propDataObject.isValid()) {
933
                //PENDING Add correct propDataObject
934
                if (bundleStructure.getEntryCount() == 0) {return;}
935
                if (!bundleStructure.getNthEntry(0).getDataObject().isValid()) {
769
                    return;
936
                    return;
770
                }
937
                }
771
                
938
                
Lines 819-825 Link Here
819
        private void updateName() {
986
        private void updateName() {
820
            assert EventQueue.isDispatchThread();
987
            assert EventQueue.isDispatchThread();
821
            
988
            
822
            final String name = propDataObject.getName();
989
            final String name = bundleStructure.getNthEntry(0).getName();
823
            final String displayName = displayName();
990
            final String displayName = displayName();
824
            final String htmlDisplayName = htmlDisplayName();
991
            final String htmlDisplayName = htmlDisplayName();
825
            final String toolTip = messageToolTip();
992
            final String toolTip = messageToolTip();
Lines 853-860 Link Here
853
        /**
1020
        /**
854
         */
1021
         */
855
        private String addModifiedInfo(String name) {
1022
        private String addModifiedInfo(String name) {
856
            boolean modified
1023
            boolean modified = false;
857
                    = propDataObject.getCookie(SaveCookie.class) != null;
1024
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1025
                if(bundleStructure.getNthEntry(i).getDataObject().getCookie(SaveCookie.class) != null) {
1026
                    modified = true;
1027
                    break;
1028
                }
1029
            }
858
            int version = modified ? 1 : 3;
1030
            int version = modified ? 1 : 3;
859
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
1031
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
860
                                       "LBL_EditorName",                //NOI18N
1032
                                       "LBL_EditorName",                //NOI18N
Lines 869-875 Link Here
869
         * @see  #htmlDisplayName
1041
         * @see  #htmlDisplayName
870
         */
1042
         */
871
        private String displayName() {
1043
        private String displayName() {
872
            String nameBase = propDataObject.getNodeDelegate().getDisplayName();
1044
            String nameBase = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate().getDisplayName();
873
            return addModifiedInfo(nameBase);
1045
            return addModifiedInfo(nameBase);
874
        }
1046
        }
875
        
1047
        
Lines 880-886 Link Here
880
         * @see  #displayName()
1052
         * @see  #displayName()
881
         */
1053
         */
882
        private String htmlDisplayName() {
1054
        private String htmlDisplayName() {
883
            final Node node = propDataObject.getNodeDelegate();
1055
            final Node node = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate();
884
            String displayName = node.getHtmlDisplayName();
1056
            String displayName = node.getHtmlDisplayName();
885
            if (displayName != null) {
1057
            if (displayName != null) {
886
                if (!displayName.startsWith("<html>")) {                //NOI18N
1058
                if (!displayName.startsWith("<html>")) {                //NOI18N
Lines 894-915 Link Here
894
        
1066
        
895
        /** Gets string for tooltip. */
1067
        /** Gets string for tooltip. */
896
        private String messageToolTip() {
1068
        private String messageToolTip() {
897
            FileObject fo = propDataObject.getPrimaryFile();
1069
            FileObject fo = bundleStructure.getNthEntry(0).getFile();
898
            return FileUtil.getFileDisplayName(fo);
1070
            return FileUtil.getFileDisplayName(fo);
899
        }
1071
        }
900
        
1072
        
901
        /** 
1073
        /**
1074
         * 
902
         * Overrides superclass method. When closing last view, also close the document.
1075
         * Overrides superclass method. When closing last view, also close the document.
903
         * @return {@code true} if close succeeded
1076
         * @return {@code true} if close succeeded
904
         */
1077
         */
905
        @Override
1078
        @Override
906
        protected boolean closeLast () {
1079
        protected boolean closeLast () {
907
            if (!propDataObject.getOpenSupport().canClose ()) {
1080
            if (!bundleStructure.getOpenSupport().canClose ()) {
908
                // if we cannot close the last window
1081
                // if we cannot close the last window
909
                return false;
1082
                return false;
910
            }
1083
            }
911
            propDataObject.getOpenSupport().closeDocuments();
1084
            bundleStructure.getOpenSupport().closeDocuments();
912
1085
            PropertyChangeListener l;
1086
            for (PropertiesDataObject dataObject:dataObjecs) {
1087
                l = weakListeners.get(dataObject);
1088
                if (l!=null) {
1089
                    dataObject.removePropertyChangeListener(l);
1090
                    weakListeners.remove(l);
1091
                }
1092
            }
913
            return true;
1093
            return true;
914
        }
1094
        }
915
1095
Lines 920-926 Link Here
920
         */
1100
         */
921
        @Override
1101
        @Override
922
        protected CloneableTopComponent createClonedObject () {
1102
        protected CloneableTopComponent createClonedObject () {
923
            return new PropertiesCloneableTopComponent(propDataObject);
1103
            return new PropertiesCloneableTopComponent(bundleStructure);
924
        }
1104
        }
925
1105
926
        /** Gets {@code Icon}. */
1106
        /** Gets {@code Icon}. */
Lines 950-956 Link Here
950
         */
1130
         */
951
        @Override
1131
        @Override
952
        public UndoRedo getUndoRedo () {
1132
        public UndoRedo getUndoRedo () {
953
            return propDataObject.getOpenSupport().getUndoRedo();
1133
            return  bundleStructure.getOpenSupport().getUndoRedo();
954
        }
1134
        }
955
1135
956
        /** Inits the subcomponents. Sets layout for this top component and adds {@code BundleEditPanel} to it. 
1136
        /** Inits the subcomponents. Sets layout for this top component and adds {@code BundleEditPanel} to it. 
Lines 964-970 Link Here
964
            c.weightx = 1.0;
1144
            c.weightx = 1.0;
965
            c.weighty = 1.0;
1145
            c.weighty = 1.0;
966
            c.gridwidth = GridBagConstraints.REMAINDER;
1146
            c.gridwidth = GridBagConstraints.REMAINDER;
967
            JPanel panel = new BundleEditPanel(propDataObject, new PropertiesTableModel(propDataObject.getBundleStructure()));
1147
            JPanel panel = new BundleEditPanel(bundleStructure, new PropertiesTableModel(bundleStructure));
968
            gridbag.setConstraints(panel, c);
1148
            gridbag.setConstraints(panel, c);
969
            add(panel);
1149
            add(panel);
970
        }
1150
        }
Lines 973-979 Link Here
973
         *  is not valid.
1153
         *  is not valid.
974
         */
1154
         */
975
        private boolean discard () {
1155
        private boolean discard () {
976
            return propDataObject == null;
1156
            return bundleStructure == null;
977
        }
1157
        }
978
        
1158
        
979
1159
Lines 985-991 Link Here
985
        @Override
1165
        @Override
986
        public void writeExternal (ObjectOutput out) throws IOException {
1166
        public void writeExternal (ObjectOutput out) throws IOException {
987
            super.writeExternal(out);
1167
            super.writeExternal(out);
988
            out.writeObject(propDataObject);
1168
            out.writeObject(bundleStructure.getNthEntry(0).getDataObject());
989
        }
1169
        }
990
1170
991
        /** 
1171
        /** 
Lines 998-1004 Link Here
998
            super.readExternal(in);
1178
            super.readExternal(in);
999
1179
1000
            propDataObject = (PropertiesDataObject)in.readObject();
1180
            propDataObject = (PropertiesDataObject)in.readObject();
1001
            
1181
            bundleStructure = (MultiBundleStructure) propDataObject.getBundleStructure();
1182
            dataObjecs = new PropertiesDataObject[bundleStructure.getEntryCount()];
1183
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1184
                dataObjecs[i] = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
1185
            }
1186
            weakListeners = new HashMap<PropertiesDataObject, PropertyChangeListener>();
1002
            initialize();
1187
            initialize();
1003
        }
1188
        }
1004
    } // End of nested class PropertiesCloneableTopComponent.
1189
    } // End of nested class PropertiesCloneableTopComponent.
Lines 1017-1038 Link Here
1017
        // Constructor
1202
        // Constructor
1018
        
1203
        
1019
        /** Collects all UndoRedo managers from all editor support of all entries. */
1204
        /** Collects all UndoRedo managers from all editor support of all entries. */
1205
        @Deprecated
1020
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1206
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1021
            init(obj);
1207
            init(obj);
1022
        }
1208
        }
1209
        public CompoundUndoRedoManager(BundleStructure structure) {
1210
            init(structure);
1211
        }
1023
1212
1024
        /** Initialize set of managers. */
1213
        /** Initialize set of managers. */
1214
        @Deprecated
1025
        private void init(PropertiesDataObject obj) {
1215
        private void init(PropertiesDataObject obj) {
1026
            managers.add( ((PropertiesFileEntry)obj.getPrimaryEntry()).getPropertiesEditor().getUndoRedoManager());
1216
            BundleStructure structure = obj.getBundleStructure();
1027
            for (Iterator it = obj.secondaryEntries().iterator(); it.hasNext(); ) {
1217
            for(int i=0; i< structure.getEntryCount(); i++) {
1028
                managers.add( ((PropertiesFileEntry)it.next()).getPropertiesEditor().getUndoRedoManager() );
1218
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1029
            } 
1219
            }
1220
        }
1221
1222
        private void init(BundleStructure structure) {
1223
            for(int i=0; i< structure.getEntryCount(); i++) {
1224
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1225
            }
1030
        }
1226
        }
1031
1227
1032
        /** Resets the managers. Used when data object has changed. */
1228
        /** Resets the managers. Used when data object has changed. */
1229
        @Deprecated
1033
        public synchronized void reset(PropertiesDataObject obj) {
1230
        public synchronized void reset(PropertiesDataObject obj) {
1034
            managers.clear();
1231
            managers.clear();
1035
            init(obj);
1232
            init(obj);
1233
        }
1234
1235
        public synchronized void reset(BundleStructure structure) {
1236
            managers.clear();
1237
            init(structure);
1036
        }
1238
        }
1037
1239
1038
        /** Gets manager which undo edit comes to play.*/
1240
        /** Gets manager which undo edit comes to play.*/
(-)a/properties/src/org/netbeans/modules/properties/PropertiesTableCellEditor.java (-1 / +1 lines)
Lines 160-166 Link Here
160
        public void setValue(Object x) {
160
        public void setValue(Object x) {
161
            // PENDING - due to a compiler error explicitly do "super" code instead of calling super
161
            // PENDING - due to a compiler error explicitly do "super" code instead of calling super
162
            this.value = x;
162
            this.value = x;
163
            //super.setValue(x);
163
//            super.setValue(x);
164
            PropertiesTableModel.StringPair sp = (PropertiesTableModel.StringPair)x;
164
            PropertiesTableModel.StringPair sp = (PropertiesTableModel.StringPair)x;
165
165
166
            // set values as they deserve
166
            // set values as they deserve
(-)a/properties/src/org/netbeans/modules/properties/PropertiesTableModel.java (-6 / +16 lines)
Lines 284-289 Link Here
284
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1, columnModelIndex));
284
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1, columnModelIndex));
285
    }
285
    }
286
286
287
    /**
288
     * Get FileEntry  according to column in Table View
289
     * @param column
290
     * @return
291
     */
292
    PropertiesFileEntry getFileEntry(int column) {
293
        return structure.getNthEntry(column-1);
294
    }
287
    /** Overrides superclass method. */
295
    /** Overrides superclass method. */
288
    @Override
296
    @Override
289
    public String toString() {
297
    public String toString() {
Lines 364-371 Link Here
364
                // Note: Normal way would be use the next commented out rows, which should do in effect
372
                // Note: Normal way would be use the next commented out rows, which should do in effect
365
                // the same thing like reseting the model, but it doesn't, therefore we reset the model directly.
373
                // the same thing like reseting the model, but it doesn't, therefore we reset the model directly.
366
                
374
                
367
                //cancelEditingInTables(getDefaultCancelSelector());
375
                cancelEditingInTables(getDefaultCancelSelector());
368
                //fireTableStructureChanged(); 
376
                fireTableStructureChanged(); 
369
377
370
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
378
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
371
                for(int i = 0; i < list.length; i++) {
379
                for(int i = 0; i < list.length; i++) {
Lines 396-404 Link Here
396
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
404
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
397
                // File changed.
405
                // File changed.
398
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
406
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
407
                //This mean file deleted
399
                if (index == -1) {
408
                if (index == -1) {
400
                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
409
                    fireTableStructureChanged();
401
                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
410
//                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
411
//                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
402
                    return;
412
                    return;
403
                }
413
                }
404
                
414
                
Lines 409-416 Link Here
409
                        return (column == index + 1);
419
                        return (column == index + 1);
410
                    }
420
                    }
411
                });
421
                });
412
                
422
//                fireTableColumnChanged(index + 1);
413
                fireTableColumnChanged(index + 1);
423
                  fireTableStructureChanged();
414
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
424
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
415
                // one item changed
425
                // one item changed
416
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
426
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
(-)a/properties/src/org/netbeans/modules/properties/Util.java (-8 / +138 lines)
Lines 45-50 Link Here
45
45
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.text.MessageFormat;
47
import java.text.MessageFormat;
48
import java.util.Arrays;
49
import java.util.HashSet;
48
import java.util.Locale;
50
import java.util.Locale;
49
import org.openide.DialogDisplayer;
51
import org.openide.DialogDisplayer;
50
import org.openide.NotifyDescriptor;
52
import org.openide.NotifyDescriptor;
Lines 52-59 Link Here
52
import org.openide.filesystems.FileObject;
54
import org.openide.filesystems.FileObject;
53
import org.openide.filesystems.FileSystem;
55
import org.openide.filesystems.FileSystem;
54
import org.openide.filesystems.FileUtil;
56
import org.openide.filesystems.FileUtil;
57
import org.openide.filesystems.Repository;
55
import org.openide.loaders.DataFolder;
58
import org.openide.loaders.DataFolder;
56
import org.openide.loaders.DataObject;
59
import org.openide.loaders.DataObject;
60
import org.openide.loaders.DataObjectNotFoundException;
57
import org.openide.loaders.FileEntry;
61
import org.openide.loaders.FileEntry;
58
62
59
import org.openide.loaders.MultiDataObject;
63
import org.openide.loaders.MultiDataObject;
Lines 147-160 Link Here
147
     * @see  #getVariant
151
     * @see  #getVariant
148
     */
152
     */
149
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
153
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
150
        MultiDataObject.Entry pe = fe.getDataObject().getPrimaryEntry();
154
        FileObject fo = fe.getFile();
151
        if (fe == pe) {
155
        String fName = fo.getName();
152
            return "";                                                  //NOI18N
156
        int index = fName.indexOf(PRB_SEPARATOR_CHAR);
157
        FileObject po = fo;
158
        while (index != -1) {
159
            FileObject candidate = fo.getParent().getFileObject(
160
                    fName.substring(0, index), fo.getExt());
161
            if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
162
                po = candidate;
163
            }
164
            index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
153
        }
165
        }
154
        String myName   = fe.getFile().getName();
166
        if (fo == po) {
155
        String baseName = pe.getFile().getName();
167
            return "";
168
        }
169
        String myName   = fo.getName();
170
        String baseName = po.getName();
156
        assert myName.startsWith(baseName);
171
        assert myName.startsWith(baseName);
157
        return myName.substring(baseName.length());
172
        return myName.substring(baseName.length());
173
//        MultiDataObject.Entry pe = fe.getDataObject().getPrimaryEntry();
174
//        if (fe == pe) {
175
//            return "";                                                  //NOI18N
176
//        }
177
//        String myName   = fe.getFile().getName();
178
//        String baseName = pe.getFile().getName();
179
//        assert myName.startsWith(baseName);
180
//        return myName.substring(baseName.length());
181
    }
182
183
    private static boolean isValidLocaleSuffix(String s) {
184
        // first char is _
185
        int n = s.length();
186
        String s1;
187
        // check first suffix - language (two chars)
188
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
189
            s1 = s.substring(1, 3).toLowerCase();
190
            // language must be followed by a valid country suffix or no suffix
191
        } else {
192
            return false;
193
        }
194
        // check second suffix - country (two chars)
195
        String s2;
196
        if (n == 3) {
197
            s2 = null;
198
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
199
            s2 = s.substring(4, 6).toUpperCase();
200
            // country may be followed by whatever additional suffix
201
        } else {
202
            return false;
203
        }
204
205
        HashSet<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
206
        if (!knownLanguages.contains(s1)) {
207
            return false;
208
        }
209
210
        if (s2 != null) {
211
            HashSet<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
212
            if (!knownCountries.contains(s2)) {
213
                return false;
214
            }
215
        }
216
        return true;
158
    }
217
    }
159
218
160
    /**
219
    /**
Lines 384-395 Link Here
384
            folder = FileUtil.createFolder(folder, folderPath);
443
            folder = FileUtil.createFolder(folder, folderPath);
385
            fileName = fileName.substring(idx + 1);
444
            fileName = fileName.substring(idx + 1);
386
        }
445
        }
387
        FileObject templateFO = FileUtil.getConfigFile("Templates/Other/properties.properties"); // NOI18N
446
        FileSystem defaultFS = Repository.getDefault().getDefaultFileSystem();
447
        FileObject templateFO = defaultFS.findResource("Templates/Other/properties.properties"); // NOI18N
388
        DataObject template = DataObject.find(templateFO);
448
        DataObject template = DataObject.find(templateFO);
389
        return (PropertiesDataObject)
449
        return (PropertiesDataObject)
390
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
450
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
391
    }
451
    }
392
452
453
    /**
454
     * Create new DataObject with requested locale and notify that new locale was added
455
     * @param propertiesDataObject DataObject to add locale
456
     * @param locale
457
     * @param copyInitialContent
458
     */
393
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
459
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
394
                                        String locale,
460
                                        String locale,
395
                                        boolean copyInitialContent)
461
                                        boolean copyInitialContent)
Lines 402-409 Link Here
402
            }
468
            }
403
469
404
            if(propertiesDataObject != null) {
470
            if(propertiesDataObject != null) {
405
                FileObject file = propertiesDataObject.getPrimaryFile();
471
//                FileObject file = propertiesDataObject.getPrimaryFile();
406
                final String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
472
                FileObject file = propertiesDataObject.getBundleStructure().getNthEntry(0).getFile();
473
                //Default locale may be deleted
474
                final String newName = getBaseName(file.getName()) + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
407
                final FileObject folder = file.getParent();
475
                final FileObject folder = file.getParent();
408
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
476
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
409
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
477
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
Lines 428-433 Link Here
428
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
496
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
429
                            }
497
                            }
430
                        });
498
                        });
499
                        //update entries in BundleStructure
500
                        propertiesDataObject.getBundleStructure().updateEntries();
501
                        //find just created DataObject
502
                        PropertiesDataObject dataObject = (PropertiesDataObject) DataObject.find(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
503
                        //Add it to OpenSupport
504
                        propertiesDataObject.getOpenSupport().addDataObject(dataObject);
505
                        //Notify BundleStructure that one file changed
506
                        propertiesDataObject.getBundleStructure().notifyOneFileChanged(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
507
//                        propertiesDataObject.getBundleStructure().notifyFileAdded(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
431
                    }
508
                    }
432
                } else {
509
                } else {
433
                    // Create an empty file - creating from template via DataObject
510
                    // Create an empty file - creating from template via DataObject
Lines 443-446 Link Here
443
            notifyError(locale);
520
            notifyError(locale);
444
        }
521
        }
445
    }
522
    }
523
524
    /**
525
     *
526
     * @param obj DataObject
527
     * @return DataObject which represent default locale
528
     *          In case when default locale is absent it will return first found locale as primary,
529
     *          which has the same base name
530
     * @throws org.openide.loaders.DataObjectNotFoundException
531
     */
532
    static PropertiesDataObject findPrimaryDataObject(PropertiesDataObject obj) throws DataObjectNotFoundException {
533
        FileObject primary = obj.getPrimaryFile();
534
        assert primary != null : "Object " + obj + " cannot have null primary file"; // NOI18N
535
        String fName;
536
        fName = primary.getName();
537
        String baseName = getBaseName(fName);
538
        FileObject parent = primary.getParent();
539
        int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
540
        while (index != -1) {
541
            FileObject candidate = parent.getFileObject(
542
                    fName.substring(0, index), primary.getExt());
543
            if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
544
                return (PropertiesDataObject) DataObject.find(candidate);
545
            } else if (candidate == null){
546
                for (FileObject file : parent.getChildren()) {
547
                    if (file.getName().indexOf(baseName) != -1) {
548
                        if (isValidLocaleSuffix(file.getName().substring(index))) {
549
                            return (PropertiesDataObject) DataObject.find(file);
550
                        }
551
                    }
552
                }
553
            }
554
            index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
555
        }
556
        return obj;
557
    }
558
559
    /**
560
     * @param name file name
561
     * @return Base name for this locale
562
     */
563
    static String getBaseName(String name) {
564
        String baseName = null;
565
        int index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
566
        while (index != -1) {
567
            baseName = name.substring(0, index);
568
            if (baseName != null && isValidLocaleSuffix(name.substring(index))) {
569
                return baseName;
570
            }
571
            index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
572
        }
573
        return name;
574
    }
575
446
}
576
}
(-)a/properties/test/unit/src/org/netbeans/modules/properties/MultiBundleStructureTest.java (+230 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.properties;
41
42
import java.io.File;
43
import java.io.FileWriter;
44
import org.junit.Test;
45
import org.netbeans.junit.NbTestCase;
46
import org.openide.filesystems.FileUtil;
47
import org.openide.loaders.DataObject;
48
import static org.junit.Assert.*;
49
50
/**
51
 *
52
 * @author alex
53
 */
54
public class MultiBundleStructureTest extends NbTestCase {
55
56
    public MultiBundleStructureTest(String name) {
57
        super(name);
58
    }
59
60
    /**
61
     * Test of updateEntries method, of class MultiBundleStructure.
62
     */
63
    @Test
64
    public void testUpdateEntries() throws Exception {
65
        System.out.println("updateEntries");
66
        File propFile = new File(getWorkDir(), "foo.properties");
67
        propFile.createNewFile();
68
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
69
        assertTrue(propDO instanceof PropertiesDataObject);
70
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
71
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
72
        instance.updateEntries();
73
        assertEquals(instance.getEntryCount(), 1);
74
    }
75
76
    /**
77
     * Test of getNthEntry method, of class MultiBundleStructure.
78
     */
79
    @Test
80
    public void testGetNthEntry() throws Exception {
81
        System.out.println("getNthEntry");
82
        int index = 0;
83
        File propFile = new File(getWorkDir(), "foo.properties");
84
        propFile.createNewFile();
85
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
86
        assertTrue(propDO instanceof PropertiesDataObject);
87
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
88
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
89
        instance.updateEntries();
90
        PropertiesFileEntry result = instance.getNthEntry(index);
91
        assertEquals(dataObject.getName(),result.getName());
92
    }
93
94
    /**
95
     * Test of getEntryIndexByFileName method, of class MultiBundleStructure.
96
     */
97
    @Test
98
    public void testGetEntryIndexByFileName() throws Exception {
99
        System.out.println("getEntryIndexByFileName");
100
        String fileName = "foo";
101
        String ext = ".properties";
102
        File propFile = new File(getWorkDir(), fileName+ext);
103
        propFile.createNewFile();
104
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
105
        assertTrue(propDO instanceof PropertiesDataObject);
106
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
107
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
108
        instance.updateEntries();
109
        int expResult = 0;
110
        int result = instance.getEntryIndexByFileName(fileName);
111
        assertEquals(expResult, result);
112
    }
113
114
    /**
115
     * Test of getEntryByFileName method, of class MultiBundleStructure.
116
     */
117
    @Test
118
    public void testGetEntryByFileName() throws Exception {
119
        System.out.println("getEntryByFileName");
120
        String fileName1 = "foo";
121
        String fileName2 = "foo_ru";
122
        String ext = ".properties";
123
        File propFile = new File(getWorkDir(), fileName1+ext);
124
        propFile.createNewFile();
125
        File propFile2 = new File(getWorkDir(), fileName2+ext);
126
        propFile2.createNewFile();
127
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
128
//        DataObject.find(FileUtil.toFileObject(propFile2));
129
        assertTrue(propDO instanceof PropertiesDataObject);
130
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
131
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
132
        instance.updateEntries();
133
        PropertiesFileEntry result = instance.getEntryByFileName(fileName1);
134
        assertEquals(result.getFile().getName(), fileName1);
135
    }
136
137
    /**
138
     * Test of getEntryCount method, of class MultiBundleStructure.
139
     */
140
    @Test
141
    public void testGetEntryCount1() throws Exception{
142
        System.out.println("getEntryCount1");
143
144
        String fileName1 = "foo.properties";
145
        File propFile = new File(getWorkDir(), fileName1);
146
        propFile.createNewFile();
147
        String fileName2 = "foo_ru.properties";
148
        File propFile2 = new File(getWorkDir(), fileName2);
149
        propFile2.createNewFile();
150
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
151
        assertTrue(propDO instanceof PropertiesDataObject);
152
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
153
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
154
        instance.updateEntries();
155
        int expResult = 2;
156
        int result = instance.getEntryCount();
157
        assertEquals(expResult, result);
158
    }
159
160
    /**
161
     * Test of getEntryCount method, of class MultiBundleStructure.
162
     */
163
    @Test
164
    public void testGetEntryCount2() throws Exception{
165
        System.out.println("getEntryCount2");
166
167
        String fileName1 = "foo.properties";
168
        File propFile = new File(getWorkDir(), fileName1);
169
        propFile.createNewFile();
170
        String fileName2 = "foo_debug.properties";
171
        File propFile2 = new File(getWorkDir(), fileName2);
172
        propFile2.createNewFile();
173
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
174
        assertTrue(propDO instanceof PropertiesDataObject);
175
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
176
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
177
        instance.updateEntries();
178
        int expResult = 1;
179
        int result = instance.getEntryCount();
180
        assertEquals(expResult, result);
181
    }
182
183
    /**
184
     * Test of getOpenSupport method, of class MultiBundleStructure.
185
     */
186
    @Test
187
    public void testGetOpenSupport() throws Exception{
188
        System.out.println("getOpenSupport");
189
        String fileName1 = "foo.properties";
190
        String fileName2 = "foo_ru.properties";
191
        File propFile = new File(getWorkDir(), fileName1);
192
        propFile.createNewFile();
193
        File propFile2 = new File(getWorkDir(), fileName2);
194
        propFile2.createNewFile();
195
        DataObject propDO1 = DataObject.find(FileUtil.toFileObject(propFile));
196
        DataObject propDO2 = DataObject.find(FileUtil.toFileObject(propFile));
197
        DataObject.find(FileUtil.toFileObject(propFile2));
198
        assertTrue(propDO1 instanceof PropertiesDataObject);
199
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO1;
200
        MultiBundleStructure instance = (MultiBundleStructure) dataObject.getBundleStructure();
201
        MultiBundleStructure instance2 = (MultiBundleStructure) ((PropertiesDataObject)propDO2).getBundleStructure();
202
        //instances should be the same
203
        assertEquals(instance, instance2);
204
        instance.updateEntries();
205
        PropertiesOpen result = instance.getOpenSupport();
206
        assertNotNull(result);
207
    }
208
209
    /**
210
     * Test of getKeyCount method, of class MultiBundleStructure.
211
     */
212
    @Test
213
    public void testGetKeyCount() throws Exception {
214
        System.out.println("getKeyCount");
215
        File propFile = new File(getWorkDir(), "foo.properties");
216
        propFile.createNewFile();
217
        FileWriter wr = new FileWriter(propFile);
218
        wr.append("a=1\nb=2");
219
        wr.close();
220
        DataObject propDO = DataObject.find(FileUtil.toFileObject(propFile));
221
        assertTrue(propDO instanceof PropertiesDataObject);
222
        PropertiesDataObject dataObject = (PropertiesDataObject) propDO;
223
        MultiBundleStructure instance = new MultiBundleStructure(dataObject);
224
        instance.updateEntries();
225
        int expResult = 2;
226
        int result = instance.getKeyCount();
227
        assertEquals(expResult, result);
228
    }
229
230
}

Return to bug 48263