KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > i18n > form > FormI18nSupport


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

19
20
21 package org.netbeans.modules.i18n.form;
22
23
24 import java.io.IOException JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.util.*;
27 import java.util.Iterator JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import javax.swing.JPanel JavaDoc;
31 import javax.swing.SwingUtilities JavaDoc;
32 import javax.swing.text.AbstractDocument JavaDoc;
33 import javax.swing.text.BadLocationException JavaDoc;
34 import javax.swing.text.Element JavaDoc;
35 import javax.swing.text.Position JavaDoc;
36 import javax.swing.text.StyledDocument JavaDoc;
37 import org.netbeans.api.editor.guards.GuardedSection;
38 import org.netbeans.api.editor.guards.GuardedSectionManager;
39
40 import org.netbeans.modules.form.*;
41 import org.netbeans.modules.form.RADConnectionPropertyEditor.RADConnectionDesignValue;
42 import org.netbeans.modules.i18n.HardCodedString;
43 import org.netbeans.modules.i18n.I18nString;
44 import org.netbeans.modules.i18n.I18nSupport;
45 import org.netbeans.modules.i18n.InfoPanel;
46 import org.netbeans.modules.i18n.java.JavaI18nString;
47 import org.netbeans.modules.i18n.java.JavaI18nSupport;
48
49 import org.openide.loaders.DataObject;
50 import org.openide.nodes.Node;
51 import org.openide.NotifyDescriptor;
52 import org.openide.DialogDisplayer;
53 import org.openide.ErrorManager;
54 import org.openide.cookies.EditorCookie;
55 import org.openide.util.NbBundle;
56
57
58 /**
59  * Support for internationalizing strings in java sources with forms.
60  *
61  * @author Peter Zavadsky
62  */

63 public class FormI18nSupport extends JavaI18nSupport {
64
65     //see RADComponent and RADVisualComponent
66
private static final String JavaDoc RAD_PROPERTIES = "properties"; // NOI18N
67
private static final String JavaDoc RAD_PROPERTIES2 = "properties2"; // NOI18N
68
private static final String JavaDoc RAD_ACCESSIBILITY = "accessibility"; // NOI18N
69
private static final String JavaDoc RAD_LAYOUT = "layout"; // NOI18N
70

71 // PENDING - Has not been used because of implementation of method
72
// isGuardedPosition(int) (now replaced with isInGuardedSection(...))
73
// The replacement for the isGuardedPosition method was made
74
// during bugfixing phase so the documentListener remained disabled
75
// to keep the amount of changes small (and thus minimize the risk
76
// of introducing new bugs.
77

78 // /** Listener which listens on changes of form document. */
79
// DocumentListener documentListener;
80

81     /** Constructor. */
82     private FormI18nSupport(DataObject sourceDataObject) {
83         super(sourceDataObject);
84     }
85
86     
87     /** Creates <code>I18nFinder</code>. Overrides superclass method. */
88     protected I18nFinder createFinder() {
89         return new FormI18nFinder(sourceDataObject, document);
90     }
91
92     /** Creates <code>I18nReplacer</code>. Creates superclass method. */
93     protected I18nReplacer createReplacer() {
94         return new FormI18nReplacer(/*sourceDataObject, document,*/ (FormI18nFinder)getFinder());
95         
96 // PENDING - Has not been used because of implementation of method
97
// isGuardedPosition(int) (now replaced with isInGuardedSection(...))
98
// See the first PENDING note.
99

100 // documentListener = new DocumentListener() {
101
// public void changedUpdate(DocumentEvent e) {
102
// }
103

104 // public void insertUpdate(DocumentEvent e) {
105
// updateFormProperties();
106
// }
107

108 // public void removeUpdate(DocumentEvent e) {
109
// }
110
// };
111

112 // document.addDocumentListener(documentListener);
113
}
114     
115     /**
116      * Overrides superclass methoid.
117      * Gets info panel about found hard string. */

118     public JPanel JavaDoc getInfo(HardCodedString hcString) {
119         return new FormInfoPanel(hcString, document);
120     }
121     
122     /** Helper method. */
123     static String JavaDoc toAscii(String JavaDoc str) {
124         // Note: All this code is copied from org.netbeans.core.editors.StringEditor.
125
StringBuffer JavaDoc buf = new StringBuffer JavaDoc(str.length() * 6); // x -> \u1234
126
char[] chars = str.toCharArray();
127         for (int i = 0; i < chars.length; i++) {
128             char c = chars[i];
129             switch (c) {
130             case '\b': buf.append("\\b"); break; // NOI18N
131
case '\t': buf.append("\\t"); break; // NOI18N
132
case '\n': buf.append("\\n"); break; // NOI18N
133
case '\f': buf.append("\\f"); break; // NOI18N
134
case '\r': buf.append("\\r"); break; // NOI18N
135
case '\"': buf.append("\\\""); break; // NOI18N
136
// case '\'': buf.append("\\'"); break; // NOI18N
137
case '\\': buf.append("\\\\"); break; // NOI18N
138
default:
139                 if (c >= 0x0020 && c <= 0x007f)
140                     buf.append(c);
141                 else {
142                     buf.append("\\u"); // NOI18N
143
String JavaDoc hex = Integer.toHexString(c);
144                     for (int j = 0; j < 4 - hex.length(); j++)
145                         buf.append('0');
146                     buf.append(hex);
147                 }
148             }
149         }
150         return buf.toString();
151     }
152
153     /** Inner class for holding info about form proeprties which can include hardcoded string.
154      * see formProperties variable in enclosing class. */

155     private static class ValidFormProperty {
156         /** Holds property of form. */
157         private Node.Property property;
158         
159         /** Holds rad component name. */
160         private String JavaDoc radCompName;
161         
162         /** How many occurences of found string should be skipped in this property.
163          * 0 means find the first occurence.
164          * All this just means that the property (mostly 'code generation-> pre-init, post-init etc.' properties)
165          * could contain more than one occurence of found string
166          * and in that case is very important to match and replace the same found in document. */

167         private int skip;
168    
169
170         /** Constructor. */
171         public ValidFormProperty(String JavaDoc radCompName, Node.Property property) {
172             this.radCompName = radCompName;
173             this.property = property;
174             this.skip = 0;
175         }
176
177         /** Constructor. */
178         public ValidFormProperty(ValidFormProperty validProperty) {
179             radCompName = validProperty.getRADComponentName();
180             property = validProperty.getProperty();
181             skip = validProperty.getSkip();
182         }
183         
184         
185         /** Getter for <code>radCompName</code> property. */
186         public String JavaDoc getRADComponentName() {
187             return radCompName;
188         }
189
190         /** Getter for property.
191          * @return property can contain hard-coded string */

192         public Node.Property getProperty() {
193             return property;
194         }
195         
196         /** Getter for skip.
197          * @return amount of occurences of hard-coded string to skip */

198         public int getSkip() {
199             return skip;
200         }
201         
202         /** Increment the amount of occurences to skip. */
203         public void incrementSkip() {
204             skip++;
205         }
206
207         /** Decrement skip amount of occurences to skip. */
208         public void decrementSkip() {
209             if(skip > 0)
210                 skip--;
211         }
212         
213     } // end of ValidFormProperty inner class
214

215     /** Helper inner class for formProperties variable in enclosing class.
216      * Provides sorting of ValidPropertyComparator classes with intenetion to get the order of
217      * properties to match order like they are generated to initComponents form guarded block.
218      * It has four stages of comparing two properies.
219      * 1) the property which belongs to creation block (preCreationCode, customCreationCode, postCreationCode)
220      * is less (will be generated sooner) then property which is from init block(other names).
221      * 2) than the property which component was added to form sooner is less then property which component was
222      * added later. (Top-level component is the least one.)
223      * 3) than a) creation block: preCreationCode < (is less) customCreationCode < postCreationCode
224      * b) init block: preInitCode < set-method-properties < postInitCode
225      * 4) than (for init block only) in case of set-method-properties. The property is less which has less index in
226      * array returned by method getAllProperties on component.
227      * */

228     private static class ValidFormPropertyComparator implements Comparator {
229         
230         private static final String JavaDoc CREATION_CODE_PRE = "creationCodePre"; // NOI18N
231
private static final String JavaDoc CREATION_CODE_CUSTOM = "creationCodeCustom"; // NOI18N
232
private static final String JavaDoc CREATION_CODE_POST = "creationCodePost"; // NOI18N
233

234         private static final String JavaDoc INIT_CODE_PRE = "initCodePre"; // NOI18N
235
private static final String JavaDoc INIT_CODE_POST = "initCodePost"; // NOI18N
236

237         /** <code>FormModel</code> on which <code>FormDataObject</code> the i18n session runs.*/
238         private final FormModel formModel;
239         
240         
241         /** Constructor. */
242         public ValidFormPropertyComparator(FormDataObject formDataObject) {
243             formModel = formDataObject.getFormEditor().getFormModel();
244         }
245         
246         
247         /** Compares two <code>ValidFormPropertiesObjects</code>. */
248         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
249             // 1st stage
250
String JavaDoc propName1 = ((ValidFormProperty)o1).getProperty().getName();
251             String JavaDoc propName2 = ((ValidFormProperty)o2).getProperty().getName();
252             
253             boolean isInCreation1 = false;
254             boolean isInCreation2 = false;
255             
256             if(propName1.equals(CREATION_CODE_PRE) || propName1.equals(CREATION_CODE_CUSTOM) || propName1.equals(CREATION_CODE_POST))
257                 isInCreation1 = true;
258             
259             if(propName2.equals(CREATION_CODE_PRE) || propName2.equals(CREATION_CODE_CUSTOM) || propName2.equals(CREATION_CODE_POST))
260                 isInCreation2 = true;
261             
262             if(isInCreation1 != isInCreation2)
263                 return isInCreation1 ? -1 : 1; // end of 1st stage
264

265                 // 2nd stage
266
RADComponent comp1 = formModel.findRADComponent(((ValidFormProperty)o1).getRADComponentName());
267                 RADComponent comp2 = formModel.findRADComponent(((ValidFormProperty)o2).getRADComponentName());
268                 
269                 int index1 = -1;
270                 int index2 = -1;
271                 
272                 if(!comp1.equals(comp2)) {
273                     Iterator JavaDoc it = formModel.getOrderedComponentList().iterator();
274                     while (it.hasNext()) {
275                         RADComponent comp = (RADComponent) it.next();
276                         if (comp == comp1)
277                             return -1;
278                         if (comp == comp2)
279                             return 1;
280                     }
281                     assert false;
282                     return 0;
283                 } // end of 2nd stage
284

285                 // 3rd stage
286
if(isInCreation1) {
287                     // 3a) stage
288
index1 = -1;
289                     index2 = -1;
290                     
291                     if(propName1.equals(CREATION_CODE_PRE)) index1 = 0;
292                     else if(propName1.equals(CREATION_CODE_CUSTOM)) index1 = 1;
293                     else if(propName1.equals(CREATION_CODE_POST)) index1 = 2;
294                     
295                     if(propName2.equals(CREATION_CODE_PRE)) index2 = 0;
296                     else if(propName2.equals(CREATION_CODE_CUSTOM)) index2 = 1;
297                     else if(propName2.equals(CREATION_CODE_POST)) index2 = 2;
298                     
299                     return index1 - index2; // end of 3a) stage
300
} else {
301                     // 3b) stage
302
index1 = -1;
303                     index2 = -1;
304                     
305                     if(propName1.equals(INIT_CODE_PRE)) index1 = 0;
306                     else if(propName1.equals(INIT_CODE_POST)) index1 = 2;
307                     else index1 = 1; // is one of set-method property
308

309                     if(propName2.equals(INIT_CODE_PRE)) index2 = 0;
310                     else if(propName2.equals(INIT_CODE_POST)) index2 = 2;
311                     else index2 = 1; // is one of set-method property
312

313                     if (index1 != 1 || index2 != 1)
314                         return index1 - index2; // end of 3b) stage
315
} // end of 3rd stage
316

317                 // 4th stage
318
Node.PropertySet[] propSets = comp1.getProperties();
319                 Object JavaDoc[] properties = new Node.Property[0];
320                 
321                 ArrayList aList = new ArrayList();
322                 for(int i=0; i<propSets.length; i++) {
323                     if(RAD_PROPERTIES.equals(propSets[i].getName())
324                     || RAD_PROPERTIES2.equals(propSets[i].getName())
325                     || RAD_LAYOUT.equals(propSets[i].getName())
326                     || RAD_ACCESSIBILITY.equals(propSets[i].getName())) {
327                         aList.addAll(Arrays.asList(propSets[i].getProperties()));
328                     }
329                 }
330                 properties = aList.toArray();
331                 
332                 index1 = -1;
333                 index2 = -1;
334                 
335                 Node.Property prop1 = ((ValidFormProperty)o1).getProperty();
336                 Node.Property prop2 = ((ValidFormProperty)o2).getProperty();
337                 
338                 for(int i=0; i<properties.length; i++) {
339                     if(prop1.equals(properties[i]))
340                         index1 = i;
341                     
342                     if(prop2.equals(properties[i]))
343                         index2 = i;
344                     
345                     if(index1!=-1 && index2!=-1)
346                         break;
347                 }
348                 
349                 return index1 - index2; // end of 4th stage
350
} // end of compare method
351

352     } // End of ValidFormPropertyCompoarator inner class.
353

354     
355     /** Nested class. Finder in java source with form. */
356     private static class FormI18nFinder extends JavaI18nFinder {
357         /** */
358         private DataObject sourceDataObject;
359         
360         /** Holds name of component which property has hardcoded string. */
361         private String JavaDoc componentName = ""; // NOI18N
362

363         /** Holds name of property with found hardcoded string */
364         private String JavaDoc propertyName = ""; // NOI18N
365

366         /** Collection for holding properties of form and their components, if search is in form performed. */
367         private TreeSet formProperties;
368
369         /** Found valid form property from last search. */
370         private ValidFormProperty lastFoundProp;
371
372         
373         /** Constructor. */
374         public FormI18nFinder(DataObject sourceDataObject, StyledDocument JavaDoc document) {
375             super(document);
376             this.sourceDataObject = sourceDataObject;
377             
378             init();
379         }
380         
381         
382         /** Initializes finder. */
383         private void init() {
384             clearFormInfoValues();
385             
386             lastFoundProp = null;
387             
388             createFormProperties();
389         }
390
391         /** Resets finder. Overrides superclass method. */
392         protected void reset() {
393             super.reset();
394             
395             init();
396         }
397         
398         /** Decrements skip value of last found property. Called from replacer. */
399         void decrementLastFoundSkip() {
400             if(lastFoundProp != null)
401                 lastFoundProp.decrementSkip();
402         }
403
404         /** Cretaes collection of properties of form which are value type of String.class
405          * and could have null value (it saves time to determine the cases the value was changed).
406          * Collection is referenced to formProperties variable.
407          * @return True if sorted collection was created. */

408         private synchronized boolean createFormProperties() {
409             // creates new collection
410
formProperties = new TreeSet(new ValidFormPropertyComparator((FormDataObject)sourceDataObject));
411             updateFormProperties();
412
413             return true;
414         }
415
416         /** Updates collection in formProperties variable. */
417         private synchronized void updateFormProperties() {
418             if(formProperties == null)
419                 return;
420
421             // All components in current FormDataObject.
422
Collection c = ((FormDataObject)sourceDataObject).getFormEditor().getFormModel().getAllComponents();
423             Iterator JavaDoc it = c.iterator();
424
425             // search thru all RADComponents in the form
426
while(it.hasNext()) {
427                 RADComponent radComponent = (RADComponent)it.next();
428                 Node.PropertySet[] propSets = radComponent.getProperties();
429
430                 // go thru properties sets
431
for(int i=0; i<propSets.length; i++) {
432                     String JavaDoc setName = propSets[i].getName();
433                     // go just thru these property sets
434
if (false == (RAD_PROPERTIES.equals(setName) || RAD_PROPERTIES2.equals(setName)
435                     || RAD_ACCESSIBILITY.equals(setName) || RAD_LAYOUT.equals(setName))) {
436                         continue;
437                     }
438                     Node.Property[] properties = propSets[i].getProperties();
439
440                     // go thru properties in sets
441
for(int j=0; j<properties.length; j++) {
442                         Node.Property property = properties[j];
443
444                         // skip hidden and unchanged properties
445
if (property.isHidden()
446                                 || !(property instanceof FormProperty)
447                                 || !((FormProperty)property).isChanged())
448                             continue;
449
450                         // get value
451
Object JavaDoc value;
452                         try {
453                             value = property.getValue();
454                         } catch(IllegalAccessException JavaDoc iae) {
455                             continue; // next property
456
} catch(InvocationTargetException JavaDoc ite) {
457                             continue; // next property
458
}
459
460                         // Property have to be a non-null value and have "value type" of String (don't confuse with the type of object referred by value variable!!)
461
// or value be RADconnectiondesignValue and be type of TYPE_VALUE or TYPE_CODE
462
if(value != null && (property.getValueType().equals(String JavaDoc.class)
463                             || (value instanceof RADConnectionDesignValue
464                                 && ( ((RADConnectionDesignValue)value).getType() == RADConnectionDesignValue.TYPE_VALUE
465                                     || ((RADConnectionDesignValue)value).getType() == RADConnectionDesignValue.TYPE_CODE)
466                                 ) )
467                             ) {
468                             // Actually add the property to the list.
469
// Note: add only ValidFormProperty instances
470
formProperties.add(new ValidFormProperty(radComponent.getName(), property));
471                         }
472                     }
473                 }
474             }
475         }
476         
477         /** Overrides superclass method. */
478         protected HardCodedString findNextString() {
479             //boolean found;
480
HardCodedString hcString;
481
482             clearFormInfoValues();
483             
484             boolean guarded = false;
485
486             do {
487                 hcString = super.findNextString();
488
489                 // If i18n search we are not interesting in form values.
490
if(i18nSearch)
491                     return hcString;
492                 
493                 if(hcString != null) {
494                     guarded = isInGuardedSection(hcString.getStartPosition(),
495                                                  hcString.getEndPosition());
496                 } else
497                     // No more hardcoded strings in source.
498
break;
499
500                 if(guarded)
501                     hcString = findInForm(hcString);
502
503             // Skip found hardcoded string if it is in a guarded block and not found appropriate form component property.
504
} while(guarded && (hcString == null));
505
506             // PENDING
507
// See first PENDING.
508
// if(!found)
509
// document.removeDocumentListener(documentListener);
510

511             return hcString;
512         }
513
514         /** Helper method. */
515         private void clearFormInfoValues() {
516             componentName = ""; // NOI18N
517
propertyName = ""; // NOI18N
518
}
519         
520         
521         /** Analyzes the text in a guraded block, tries to find the name
522          * of the component and of the property which value matches
523          * with just found hardcoded string.
524          */

525         private synchronized HardCodedString findInForm(HardCodedString hcString) {
526             boolean found = false;
527
528             String JavaDoc hardString = hcString.getText();
529             
530             // Valid form property.
531
ValidFormProperty validProp = null;
532
533             // Node property.
534
Node.Property nodeProperty = null;
535
536             Iterator JavaDoc it;
537
538             if(lastFoundProp != null) {
539                 validProp = lastFoundProp;
540                 it = formProperties.tailSet(lastFoundProp).iterator();
541             } else
542                 it = formProperties.iterator();
543             
544             do {
545                 if(validProp == null && it.hasNext())
546                     validProp = (ValidFormProperty)it.next();
547
548                 if(validProp == null)
549                     break;
550                 
551                 Node.Property property = validProp.getProperty();
552                 String JavaDoc radCompName = validProp.getRADComponentName();
553                 
554                 // get value
555
Object JavaDoc value;
556                 try {
557                     value = property.getValue();
558                 } catch(IllegalAccessException JavaDoc iae) {
559                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, iae);
560                     validProp = null;
561                     continue; // next property
562
} catch(InvocationTargetException JavaDoc ite) {
563                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ite);
564                     validProp = null;
565                     continue; // next property
566
}
567
568                 // Property have to be a non-null value and have "value type" of String (don't confuse with the type of object referred by value variable!!)
569
// or value be RADconnectiondesignValue and be type of TYPE_VALUE or TYPE_CODE
570
if(value != null && (property.getValueType().equals(String JavaDoc.class)
571                     || (value instanceof RADConnectionDesignValue
572                         && ( ((RADConnectionDesignValue)value).getType() == RADConnectionDesignValue.TYPE_VALUE
573                             || ((RADConnectionDesignValue)value).getType() == RADConnectionDesignValue.TYPE_CODE)
574                         ) )
575                     ) {
576                         
577                     String JavaDoc string;
578                     
579                     if(property instanceof FormProperty) {
580                         // RADProperty, the value could be constructed from one of PropertyEditors
581
if(value instanceof FormI18nString) {
582                             // resource bundle value, do not replace, is internationalized already !!
583
validProp = null;
584                             continue; // next property
585
} else if (value instanceof RADConnectionDesignValue) {
586                             // is Form connection value
587
string = ""; // NOI18N
588
RADConnectionDesignValue connectionValue = (RADConnectionDesignValue)value;
589                             if(connectionValue.getType() == RADConnectionDesignValue.TYPE_VALUE) {
590                                 // is type of VALUE
591
string = connectionValue.getValue();
592
593                             if(indexOfNonI18nString(string, hardString, validProp.getSkip()) != -1)
594                                 found = true;
595                             } else if (connectionValue.getType() == RADConnectionDesignValue.TYPE_CODE) {
596                                 // is type of TYPE_CODE
597
string = connectionValue.getCode();
598
599                                 if(indexOfNonI18nString(string, hardString, validProp.getSkip()) != -1)
600                                     found = true;
601                             }
602                         } else {
603                             // Has to be plain String, there is other Property Editor for String RAD Property.
604
// It's converted via toAscii method cause for this value is used org.netbeans.core.editors.StringEditor
605
// which does the same thing.
606
string = toAscii((String JavaDoc)value);
607                             
608                             if(validProp.getSkip()==0 && string.equals(hardString))
609                                 found = true;
610                         }
611                     } else {
612                         // Node.Property, the value should be plain String.
613
string = (String JavaDoc)value;
614                         
615                         if(indexOfNonI18nString(string, hardString, validProp.getSkip()) != -1) {
616                             // non-internationalized hardString found.
617
found = true;
618                         }
619                     }
620                 }
621                 if(found) {
622                     nodeProperty = property;
623                     componentName = radCompName;
624                     propertyName = property.getName();
625
626                     break;
627                 } else
628                     validProp = null;
629                 
630             } while(it.hasNext());
631
632             if(found) {
633                 lastFoundProp = new ValidFormProperty(validProp);
634                 lastFoundProp.incrementSkip();
635
636                 return new FormHardCodedString(
637                     hcString.getText(),
638                     hcString.getStartPosition(),
639                     hcString.getEndPosition(),
640                     validProp,
641                     nodeProperty
642                 );
643             } else {
644                 return null;
645             }
646         }
647         
648         
649         /** Getter for <code>lastPosition</code> property. */
650         public Position JavaDoc getLastPosition() {
651             return lastPosition;
652         }
653         
654         /** Setter for <code>lastPosition</code> property. */
655         public void setLastPosition(Position JavaDoc lastPosition) {
656             super.lastPosition = lastPosition;
657         }
658         
659         /** Helper method. */
660         public int indexOfNonI18nString(String JavaDoc source, String JavaDoc hardString, int skip) {
661             // Index of found string in code described by source string.
662
int index = 0;
663
664             // Start index for each iteration of loop.
665
int startIndex=0;
666
667             while(true) {
668                 // Find out if there could be some string yet.
669
int startString = source.indexOf('\"', startIndex);
670
671                 if(startString == -1)
672                     break;
673
674                 // Get the string.
675
int endString = source.indexOf('\"', startString+1);
676
677                 int endLineIndex = source.indexOf('\n', startString+1);
678
679                 // Check for validity of that string. (It has to be in one row).
680
if(endLineIndex == -1 || endString < endLineIndex) {
681                     // Get valid string.
682
String JavaDoc foundString = source.substring(startString, endString+1);
683
684                     // Construct part line which will be compared in with regular expression.
685
String JavaDoc partLine;
686                     
687                     // Adjust start index so the part line starts at the same line like found string.
688
int startLine = source.indexOf('\n', startIndex + 1);
689                     if(startLine != -1 && startLine < startString)
690                         startIndex = startLine + 1;
691
692                     if(endLineIndex == -1)
693                         partLine = source.substring(startIndex);
694                     else {
695                         int quote = source.indexOf('\"', endString+1);
696
697                         // If there is another string on that line cut part line before that.
698
if(quote != -1 && quote < endLineIndex)
699                             // The second part is little trick to cheat out regular expression in minor case the next string is same and i18n-ized already.
700
partLine = source.substring(startIndex, quote) + source.substring(quote, endLineIndex).replace('\"','_');
701                         else
702                             partLine = source.substring(startIndex, endLineIndex);
703                     }
704
705                     // Compare with regular expression.
706
if(isSearchedString(partLine, foundString)) {
707                         // Is non-i18n-ized string and has the has the order number in source string code we search for.
708
if(index == skip) {
709                             if(foundString.equals("\""+hardString+"\""))
710                                 // It is our hard string.
711
return startString;
712                             else
713                                 // Is not our hardString.
714
return -1;
715                         }
716
717                         index++;
718                     }
719
720                     // Set start index for next iteration.
721
startIndex = endString + 1;
722                 } else
723                     startIndex = endLineIndex + 1;
724             } // End of infinite loop.
725

726             return -1;
727         }
728
729         /**
730          * Checks whether the given section of text overlaps with any of the
731          * guarded sections in the editor.
732          *
733          * @param startPos beginning position if the section to check
734          * @param endPos ending position of the section to check
735          * @return <code>true</code> if the section of text overlaps,
736          * <code>false</code> otherwise
737          */

738         private synchronized boolean isInGuardedSection(final Position JavaDoc startPos,
739                                                         final Position JavaDoc endPos) {
740             EditorCookie editor = (EditorCookie) sourceDataObject.getCookie(EditorCookie.class);
741             StyledDocument JavaDoc doc = null;
742             GuardedSectionManager guards = null;
743             if (editor != null) {
744                 try {
745                     doc = editor.openDocument();
746                 }
747                 catch (IOException JavaDoc ex) {
748                     Logger.getLogger("global").log(Level.SEVERE, ex.getLocalizedMessage(), ex);
749                     return false;
750                 }
751             }
752             
753             if (doc != null) {
754                 guards = GuardedSectionManager.getInstance(doc);
755             }
756             
757             if (guards != null) {
758                 for (Iterator JavaDoc it = guards.getGuardedSections().iterator(); it.hasNext();) {
759                     GuardedSection gsection = (GuardedSection) it.next();
760                     if (gsection.contains(startPos, true) ||
761                             gsection.contains(endPos, true)) {
762                         return true;
763                     }
764                 }
765
766             }
767             return false;
768         }
769
770         DataObject getSourceDataObject() {
771       return sourceDataObject;
772     }
773
774
775     } // End of nested class I18nFormFinder.
776

777     
778     /** Replacer used by enclosing class. */
779    private static class FormI18nReplacer extends JavaI18nReplacer {
780        
781        /** Reference to form finder. */
782        private FormI18nFinder finder;
783        
784        private final ResourceBundle bundle;
785        
786        /** Constructor. */
787        public FormI18nReplacer(FormI18nFinder finder) {
788            this.finder = finder;
789            bundle = NbBundle.getBundle(FormI18nSupport.class);
790        }
791
792        
793        /** Overrides superclass method. */
794        public void replace(final HardCodedString hcString, final I18nString i18nString) {
795            if(hcString instanceof FormHardCodedString) {
796                replaceInGuarded((FormHardCodedString)hcString, (JavaI18nString)i18nString);
797            } else
798                super.replace(hcString, i18nString);
799        }
800
801        /** Replaces found hard coded string in guarded blocks. */
802        private void replaceInGuarded(FormHardCodedString formHcString, JavaI18nString javaI18nString) {
803            try {
804                String JavaDoc replaceString = javaI18nString.getReplaceString();
805
806                // Remember position offset before change of guarded block
807
int lastPos = ((FormI18nFinder)finder).getLastPosition().getOffset();
808
809                int pos = formHcString.getEndPosition().getOffset();
810
811                // new value to set
812
Object JavaDoc newValue;
813
814                Node.Property nodeProperty = formHcString.getNodeProperty();
815
816                ValidFormProperty validProp = formHcString.getValidProperty();
817
818                // old value
819
Object JavaDoc oldValue = nodeProperty.getValue();
820
821                // RAD property -> like text, title etc.
822
if(nodeProperty instanceof FormProperty) {
823                    if(oldValue instanceof RADConnectionDesignValue
824                    && ((RADConnectionDesignValue)oldValue).getType() == RADConnectionDesignValue.TYPE_CODE) {
825                        // The old value is set via RADConnectionPropertyEditor,
826
// (in our case if value was RADConnectionDesignValue of type TYPE_CODE (= user code))
827
String JavaDoc oldString = ((RADConnectionDesignValue)oldValue).getCode();
828
829                        StringBuffer JavaDoc buff = new StringBuffer JavaDoc(oldString);
830
831                        int index = indexOfHardString(oldString, formHcString.getText(), validProp.getSkip());
832
833                        if (index == -1) {
834                            NotifyDescriptor.Message message = new NotifyDescriptor.Message(
835                                bundle.getString("MSG_StringNotFoundInGuarded"), NotifyDescriptor.ERROR_MESSAGE);
836                                DialogDisplayer.getDefault().notify(message);
837                                 
838                            return;
839                        }
840
841                        int startOffset = index;
842
843                        int endOffset = startOffset + formHcString.getText().length() + 2; // 2 for quotes.
844

845                        buff.replace(startOffset, endOffset, replaceString);
846
847                        RADConnectionDesignValue newConnectionValue = new RADConnectionDesignValue(buff.toString());
848                        newValue = newConnectionValue;
849                    } else {
850                        // The old value is set via ResourceBundleStringFormEditor,
851
// (in our case if value was "plain string" or
852
// RADConnectionDesignValue of type TYPE_VALUE.
853
((FormProperty)nodeProperty).setCurrentEditor(new FormI18nStringEditor());
854                        newValue = new FormI18nString(javaI18nString);
855                    }
856                } else {
857                    // Node.Property -> code generation properties.
858
// Replace the part of old value which matches "quoted" hardString only.
859
String JavaDoc oldString = (String JavaDoc)oldValue;
860                    StringBuffer JavaDoc buff = new StringBuffer JavaDoc(oldString);
861
862                    int index = indexOfHardString(oldString, formHcString.getText(), validProp.getSkip());
863
864                    if(index == -1) {
865                        NotifyDescriptor.Message message = new NotifyDescriptor.Message(
866                            bundle.getString("MSG_StringNotFoundInGuarded"), NotifyDescriptor.ERROR_MESSAGE);
867                            DialogDisplayer.getDefault().notify(message);
868                            
869                        return;
870                    }
871
872                    int startOffset = index;
873                    
874                    int endOffset = startOffset + formHcString.getText().length() + 2; // 2 for quotes
875

876                    buff.replace(startOffset, endOffset, replaceString);
877
878                    newValue = buff.toString();
879                }
880
881                // Finally set the new value to property.
882
nodeProperty.setValue(newValue);
883
884                // Decrement last found skip.
885
finder.decrementLastFoundSkip();
886                
887                final StyledDocument JavaDoc document = javaI18nString.getSupport().getDocument();
888
889                // form editor may change the string, e.g. replace ResourceBundle.getBundle with bundle variable
890
int replaceStringLength = newValue instanceof FormI18nString ? 0 : replaceString.length();
891                final int lastP = lastPos + replaceStringLength - formHcString.getText().length() - 2; // 2 for quotes
892
SwingUtilities.invokeLater(new Runnable JavaDoc() {
893                     public void run() {
894                        // Little trick to reset the last position in finder after guarded block was regenerated.
895
if(document instanceof AbstractDocument JavaDoc)
896                            ((AbstractDocument JavaDoc)document).readLock();
897                        try {
898                            ((FormI18nFinder)finder).setLastPosition(document.createPosition(lastP));
899                        } catch (BadLocationException JavaDoc ble) {
900                            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ble);
901                        } finally {
902                            if(document instanceof AbstractDocument JavaDoc)
903                                ((AbstractDocument JavaDoc)document).readUnlock();
904                        }
905                     }
906                });
907             } catch (IllegalAccessException JavaDoc iae) {
908                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, iae);
909             } catch (InvocationTargetException JavaDoc ite) {
910                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ite);
911             }
912         }
913
914         /** Helper method. */
915         private int indexOfHardString(String JavaDoc source, String JavaDoc hardString, int skip) {
916             while(skip >= 0) {
917                 int index = finder.indexOfNonI18nString(source, hardString, skip);
918                 if(index >= 0)
919                     return index;
920                 skip--;
921             }
922             
923             return -1;
924         }
925         
926     } // End of nested class FormI18nReplacer
927

928     
929     /** HardCoded string found within form guarded block
930      * and which contains values of form property to wich belongs. */

931     private static class FormHardCodedString extends HardCodedString {
932         
933         /** Valid property with name etc. */
934         private ValidFormProperty validProperty;
935         
936         /** Valid property. */
937         private Node.Property nodeProperty;
938         
939
940         /** Constructor. */
941         FormHardCodedString(String JavaDoc text, Position JavaDoc startPosition, Position JavaDoc endPosition,
942             ValidFormProperty validProperty, Node.Property nodeProperty) {
943                 
944             super(text, startPosition, endPosition);
945             this.validProperty = validProperty;
946             this.nodeProperty = nodeProperty;
947         }
948         
949         
950         /** Getter for <code>validProperty</code>. */
951         public ValidFormProperty getValidProperty() {
952             return validProperty;
953         }
954         
955         /** Getter for <code>nodeProperty</code>. */
956         public Node.Property getNodeProperty() {
957             return nodeProperty;
958         }
959         
960     } // End of nested class FormHardCodedString.
961

962     
963     /** Panel for showing info about hard coded string. */
964     private static class FormInfoPanel extends InfoPanel {
965         
966         /** Constructor. */
967         public FormInfoPanel(HardCodedString hcString, StyledDocument JavaDoc document) {
968             super(hcString, document);
969         }
970         
971         
972         /** Implements superclass abstract method. */
973         protected void setHardCodedString(HardCodedString hcString, StyledDocument JavaDoc document) {
974
975             getStringText().setText(hcString == null ? "" : hcString.getText()); // NOI18N
976

977             int pos;
978
979             String JavaDoc hardLine;
980             
981             if(hcString.getStartPosition() == null)
982                 hardLine = ""; // NOI18N
983
else {
984                 pos = hcString.getStartPosition().getOffset();
985
986                 try {
987                     Element JavaDoc paragraph = document.getParagraphElement(pos);
988                     hardLine = document.getText(paragraph.getStartOffset(), paragraph.getEndOffset()-paragraph.getStartOffset()).trim();
989                 } catch (BadLocationException JavaDoc ble) {
990                     hardLine = ""; // NOI18N
991
}
992             }
993
994             getFoundInText().setText(hardLine);
995
996             if(hcString instanceof FormHardCodedString) {
997                 getComponentText().setText( ((FormHardCodedString)hcString).getValidProperty().getRADComponentName());
998                 getPropertyText().setText( ((FormHardCodedString)hcString).getNodeProperty().getName());
999             } else {
1000                remove(getComponentLabel());
1001                remove(getComponentText());
1002                remove(getPropertyLabel());
1003                remove(getPropertyText());
1004            }
1005            
1006        }
1007    } // End of FormInfoPanel inner class.
1008

1009    /** Factory for <code>FormI18nSupport</code>. */
1010    public static class Factory extends I18nSupport.Factory {
1011
1012        /** Instantiated from META-INF/services */
1013        public Factory() {
1014        }
1015
1016        /** Gets <code>I18nSupport</code> instance for specified data object and document. Overrides superclass method.
1017         * @exception IOException when the document could not be loaded */

1018        public I18nSupport create(DataObject dataObject) throws IOException JavaDoc {
1019            I18nSupport support = super.create(dataObject);
1020            
1021            FormEditorSupport formSupport = ((FormDataObject)dataObject).getFormEditor();
1022            if(formSupport.isOpened())
1023                return support;
1024            
1025            if(formSupport.loadForm())
1026               return support;
1027            
1028            throw new IOException JavaDoc("I18N: Loading form for " + dataObject.getName() + " was not succesful."); // NOI18N
1029
}
1030        
1031        /** Implements superclass abstract method. */
1032        public I18nSupport createI18nSupport(DataObject dataObject) {
1033            return new FormI18nSupport(dataObject);
1034        }
1035        
1036        /** Gets class of supported <code>DataObject</code>.
1037         * @return <code>FormDataObject</code> class or <code>null</code> */

1038        public Class JavaDoc getDataObjectClass() {
1039            return FormDataObject.class;
1040// try {
1041
// // FIXME remove reflection with system classloader. what's wrong missing implementaion dependency?
1042
// return Class.forName("org.netbeans.modules.form..FormDataObject", false, (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class)); // NOI18N
1043
// } catch (ClassNotFoundException e) {
1044
// ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot enable I18N support: " + e.getMessage()); //NOI18N
1045
// return null;
1046
// }
1047
}
1048
1049    } // End of class Factory.
1050

1051}
1052
Popular Tags