KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > GandalfPersistenceManager


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 package org.netbeans.modules.form;
21
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.Tree;
24 import com.sun.source.util.TreePath;
25 import java.beans.*;
26 import java.io.*;
27 import java.util.*;
28 import java.lang.reflect.*;
29 import javax.lang.model.element.Element;
30 import javax.lang.model.element.ElementKind;
31 import javax.lang.model.element.TypeElement;
32 import org.netbeans.api.java.source.CancellableTask;
33 import org.netbeans.api.java.source.CompilationController;
34 import org.netbeans.api.java.source.JavaSource;
35
36 import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
37 import org.openide.filesystems.FileLock;
38 import org.openide.filesystems.FileObject;
39 import org.openide.nodes.Node;
40 import org.openide.util.Utilities;
41 import org.openide.*;
42 import org.openide.xml.XMLUtil;
43
44 import org.netbeans.modules.form.editors2.FontEditor;
45 import org.netbeans.modules.form.layoutsupport.*;
46 import org.netbeans.modules.form.layoutsupport.delegates.*;
47 import org.netbeans.modules.form.codestructure.*;
48 import org.netbeans.modules.form.layoutdesign.LayoutModel;
49 import org.netbeans.modules.form.layoutdesign.LayoutComponent;
50 import org.netbeans.modules.form.layoutdesign.support.SwingLayoutBuilder;
51
52 import org.netbeans.api.java.classpath.ClassPath;
53 import org.openide.nodes.Node.Property;
54 import org.openide.util.TopologicalSortException;
55 import org.w3c.dom.NamedNodeMap JavaDoc;
56
57 /**
58  * XML persistence manager - responsible for saving/loading forms to/from XML.
59  * The class contains lots of complicated code with many hacks ensuring full
60  * compatibility of the format despite that many original classes already don't
61  * exist (e.g. FormInfo and DesignLayout and subclasses).
62  *
63  * @author Ian Formanek, Tomas Pavek
64  */

65
66 public class GandalfPersistenceManager extends PersistenceManager {
67     static final String JavaDoc NB32_VERSION = "1.0"; // NOI18N
68
static final String JavaDoc NB33_VERSION = "1.1"; // NOI18N
69
static final String JavaDoc NB34_VERSION = "1.2"; // NOI18N
70
static final String JavaDoc NB42_VERSION = "1.3"; // NOI18N
71
static final String JavaDoc NB60_VERSION = "1.4"; // NOI18N
72

73     // XML elements names
74
static final String JavaDoc XML_FORM = "Form"; // NOI18N
75
static final String JavaDoc XML_NON_VISUAL_COMPONENTS = "NonVisualComponents"; // NOI18N
76
static final String JavaDoc XML_CONTAINER = "Container"; // NOI18N
77
static final String JavaDoc XML_COMPONENT = "Component"; // NOI18N
78
static final String JavaDoc XML_COMPONENT_REF = "ComponentRef"; // NOI18N
79
static final String JavaDoc XML_MENU_COMPONENT = "MenuItem"; // NOI18N
80
static final String JavaDoc XML_MENU_CONTAINER = "Menu"; // NOI18N
81
static final String JavaDoc XML_LAYOUT = "Layout"; // NOI18N
82
static final String JavaDoc XML_LAYOUT_CODE = "LayoutCode"; // NOI18N
83
static final String JavaDoc XML_CONSTRAINTS = "Constraints"; // NOI18N
84
static final String JavaDoc XML_CONSTRAINT = "Constraint"; // NOI18N
85
static final String JavaDoc XML_SUB_COMPONENTS = "SubComponents"; // NOI18N
86
static final String JavaDoc XML_EVENTS = "Events"; // NOI18N
87
static final String JavaDoc XML_EVENT = "EventHandler"; // NOI18N
88
static final String JavaDoc XML_PROPERTIES = "Properties"; // NOI18N
89
static final String JavaDoc XML_PROPERTY = "Property"; // NOI18N
90
static final String JavaDoc XML_VALUE = "Value"; // NOI18N
91
static final String JavaDoc XML_SYNTHETIC_PROPERTY = "SyntheticProperty"; // NOI18N
92
static final String JavaDoc XML_SYNTHETIC_PROPERTIES = "SyntheticProperties"; // NOI18N
93
static final String JavaDoc XML_AUX_VALUES = "AuxValues"; // NOI18N
94
static final String JavaDoc XML_AUX_VALUE = "AuxValue"; // NOI18N
95
static final String JavaDoc XML_A11Y_PROPERTIES = "AccessibilityProperties"; // NOI18N
96
static final String JavaDoc XML_SERIALIZED_PROPERTY_VALUE = "SerializedValue"; // NOI18N
97
static final String JavaDoc XML_CODE_EXPRESSION = "CodeExpression"; // NOI18N
98
static final String JavaDoc XML_CODE_VARIABLE = "CodeVariable"; // NOI18N
99
static final String JavaDoc XML_CODE_ORIGIN = "ExpressionOrigin"; // NOI18N
100
static final String JavaDoc XML_CODE_STATEMENT = "CodeStatement"; // NOI18N
101
static final String JavaDoc XML_CODE_PARAMETERS = "Parameters"; // NOI18N
102
static final String JavaDoc XML_CODE_STATEMENTS = "Statements"; // NOI18N
103
static final String JavaDoc XML_ORIGIN_META_OBJECT = "ExpressionProvider"; // NOI18N
104
static final String JavaDoc XML_STATEMENT_META_OBJECT = "StatementProvider"; // NOI18N
105
static final String JavaDoc XML_CODE_CONSTRUCTOR = "CodeConstructor"; // NOI18N
106
static final String JavaDoc XML_CODE_METHOD = "CodeMethod"; // NOI18N
107
static final String JavaDoc XML_CODE_FIELD = "CodeField"; // NOI18N
108
static final String JavaDoc XML_PROPERTY_BEAN = "PropertyBean"; // NOI18N
109

110     // XML attributes names
111
static final String JavaDoc ATTR_FORM_VERSION = "version"; // NOI18N
112
static final String JavaDoc ATTR_FORM_TYPE = "type"; // NOI18N
113
static final String JavaDoc ATTR_COMPONENT_NAME = "name"; // NOI18N
114
static final String JavaDoc ATTR_COMPONENT_CLASS = "class"; // NOI18N
115
static final String JavaDoc ATTR_PROPERTY_NAME = "name"; // NOI18N
116
static final String JavaDoc ATTR_PROPERTY_TYPE = "type"; // NOI18N
117
static final String JavaDoc ATTR_PROPERTY_EDITOR = "editor"; // NOI18N
118
static final String JavaDoc ATTR_PROPERTY_VALUE = "value"; // NOI18N
119
static final String JavaDoc ATTR_PROPERTY_PRE_CODE = "preCode"; // NOI18N
120
static final String JavaDoc ATTR_PROPERTY_POST_CODE = "postCode"; // NOI18N
121
static final String JavaDoc ATTR_EVENT_NAME = "event"; // NOI18N
122
static final String JavaDoc ATTR_EVENT_LISTENER = "listener"; // NOI18N
123
static final String JavaDoc ATTR_EVENT_PARAMS = "parameters"; // NOI18N
124
static final String JavaDoc ATTR_EVENT_HANDLER = "handler"; // NOI18N
125
static final String JavaDoc ATTR_AUX_NAME = "name"; // NOI18N
126
static final String JavaDoc ATTR_AUX_VALUE = "value"; // NOI18N
127
static final String JavaDoc ATTR_AUX_VALUE_TYPE = "type"; // NOI18N
128
static final String JavaDoc ATTR_LAYOUT_CLASS = "class"; // NOI18N
129
static final String JavaDoc ATTR_CONSTRAINT_LAYOUT = "layoutClass"; // NOI18N
130
static final String JavaDoc ATTR_CONSTRAINT_VALUE = "value"; // NOI18N
131
static final String JavaDoc ATTR_EXPRESSION_ID = "id"; // NOI18N
132
static final String JavaDoc ATTR_VAR_NAME = "name"; // NOI18N
133
static final String JavaDoc ATTR_VAR_TYPE = "type"; // NOI18N
134
static final String JavaDoc ATTR_VAR_DECLARED_TYPE = "declaredType"; // NOI18N
135
static final String JavaDoc ATTR_META_OBJECT_TYPE = "type"; // NOI18N
136
static final String JavaDoc ATTR_MEMBER_CLASS = "class"; // NOI18N
137
static final String JavaDoc ATTR_MEMBER_PARAMS = "parameterTypes"; // NOI18N
138
static final String JavaDoc ATTR_MEMBER_NAME = "name"; // NOI18N
139

140     private static final String JavaDoc ONE_INDENT = " "; // NOI18N
141
private static final Object JavaDoc NO_VALUE = new Object JavaDoc();
142     private static final String JavaDoc FORM_SETTINGS_PREFIX = "FormSettings_"; // NOI18N
143

144     private org.w3c.dom.Document JavaDoc topDocument =
145         XMLUtil.createDocument("topDocument",null,null,null); // NOI18N
146

147     private FileObject formFile;
148
149     private FormModel formModel;
150
151     private List nonfatalErrors;
152
153     // maps of properties that cannot be loaded before component is added to
154
// parent container, or container is filled with sub-components
155
private Map JavaDoc<RADComponent, java.util.List JavaDoc> parentDependentProperties;
156     private Map JavaDoc<RADComponent, java.util.List JavaDoc> childrenDependentProperties;
157
158     // map of loaded components (not necessarily added to FormModel yet)
159
private Map JavaDoc loadedComponents;
160
161     private ConnectedProperties connectedProperties;
162
163     // XML persistence of code structure
164
private Map JavaDoc expressions; // map of expressions/IDs already saved/loaded
165
private int lastExpId; // CodeExpression ID counter (for saving)
166
private Map JavaDoc savedVariables; // set of code variables already saved
167
private boolean codeFlow = true; // we can save/load either code flow
168
// or static code structure
169

170     private String JavaDoc formatVersion; // format version for saving the form file
171

172     private Boolean JavaDoc newLayout; // whether a new layout support was loaded
173

174     /** This method is used to check if the persistence manager can read the
175      * given form (if it understands the form file format).
176      * @return true if this persistence manager can load the form
177      * @exception PersistenceException if any unexpected problem occurred
178      */

179     public boolean canLoadForm(FormDataObject formObject)
180         throws PersistenceException
181     {
182         FileObject formFile = formObject.getFormEntry().getFile();
183         org.w3c.dom.Element JavaDoc mainElement;
184         try {
185             org.w3c.dom.Document JavaDoc doc = XMLUtil.parse(
186                 new org.xml.sax.InputSource JavaDoc(formFile.getURL().toExternalForm()),
187                 false, false, null, null);
188
189             mainElement = doc.getDocumentElement();
190         }
191         catch (IOException ex) {
192             throw new PersistenceException(ex, "Cannot open form file"); // NOI18N
193
}
194         catch (org.xml.sax.SAXException JavaDoc e) {
195             // ignore SAXException?
196
e.printStackTrace();
197             return false;
198         }
199
200         return mainElement != null && XML_FORM.equals(mainElement.getTagName());
201     }
202
203     /** This method loads the form from given data object.
204      * @param formObject FormDataObject representing the form files
205      * @param formModel FormModel to be filled with loaded data
206      * @param nonfatalErrors List to be filled with errors occurred during
207      * loading which are not fatal (but should be reported)
208      * @exception PersistenceException if some fatal problem occurred which
209      * prevents loading the form
210      */

211     public void loadForm(FormDataObject formObject,
212                          FormModel formModel,
213                          List nonfatalErrors)
214         throws PersistenceException
215     {
216         loadForm(formObject.getFormEntry().getFile(),
217               formObject.getPrimaryFile(),
218               formModel,
219               nonfatalErrors);
220     }
221     
222     /** This method loads the form from given data object.
223      * @param formFile form file corresponding to java file
224      * @param javafile java file
225      * @param formModel FormModel to be filled with loaded data
226      * @param nonfatalErrors List to be filled with errors occurred during
227      * loading which are not fatal (but should be reported)
228      * @exception PersistenceException if some fatal problem occurred which
229      * prevents loading the form
230      */

231     public FormModel loadForm(FileObject formFile, FileObject javaFile,
232                          FormModel formModel,
233                          List nonfatalErrors)
234         throws PersistenceException
235     {
236         this.formFile = formFile;
237         
238         boolean underTest = ((javaFile == null) || (javaFile.equals(formFile)));
239                 
240         if (formModel == null) {
241             formModel = new FormModel();
242         }
243         org.w3c.dom.Element JavaDoc mainElement;
244         try { // parse document, get the main element
245
mainElement = XMLUtil.parse(new org.xml.sax.InputSource JavaDoc(
246                                             formFile.getURL().toExternalForm()),
247                                         false, false, null, null)
248                           .getDocumentElement();
249         }
250         catch (IOException ex) {
251             PersistenceException pe = new PersistenceException(
252                                           ex, "Cannot open form file"); // NOI18N
253
ErrorManager.getDefault().annotate(
254                 ex,
255                 FormUtils.getBundleString("MSG_ERR_LoadingErrors")); // NOI18N
256
throw pe;
257         }
258         catch (org.xml.sax.SAXException JavaDoc ex) {
259             PersistenceException pe = new PersistenceException(
260                                           ex, "Invalid XML in form file"); // NOI18N
261
ErrorManager.getDefault().annotate(
262                 ex,
263                 FormUtils.getBundleString("MSG_ERR_InvalidXML")); // NOI18N
264
throw pe;
265         }
266
267         // check the main element
268
if (mainElement == null || !XML_FORM.equals(mainElement.getTagName())) {
269             PersistenceException ex = new PersistenceException(
270                             "Missing expected main XML element"); // NOI18N
271
ErrorManager.getDefault().annotate(
272                 ex,
273                 ErrorManager.ERROR,
274                 null,
275                 FormUtils.getBundleString("MSG_ERR_MissingMainElement"), // NOI18N
276
null,
277                 null);
278             throw ex;
279         }
280
281         // check the form version
282
if (!isSupportedFormatVersion(mainElement.getAttribute(ATTR_FORM_VERSION))) {
283             PersistenceException ex = new PersistenceException(
284                                      "Unsupported form version"); // NOI18N
285
ErrorManager.getDefault().annotate(
286                 ex,
287                 ErrorManager.ERROR,
288                 null,
289                 FormUtils.getFormattedBundleString(
290                     "FMT_ERR_UnsupportedVersion", // NOI18N
291
new Object JavaDoc[] { mainElement.getAttribute(ATTR_FORM_VERSION) }),
292                 null,
293                 null);
294             throw ex;
295         }
296
297         // --------
298
// get the form base class and set it to FormModel
299
String JavaDoc declaredSuperclassName = null;
300         Class JavaDoc formBaseClass = null;
301         Throwable JavaDoc formBaseClassEx = null;
302
303         // get the formerly used FormInfo type (to be used as fallback alternative)
304
String JavaDoc formInfoName = mainElement.getAttribute(ATTR_FORM_TYPE);
305         if ("".equals(formInfoName)) // NOI18N
306
formInfoName = null; // not available
307

308         try { // try declared superclass from java source first
309
if (!underTest) {
310                 declaredSuperclassName = getSuperClassName(javaFile);
311             }
312             
313             Class JavaDoc superclass = declaredSuperclassName != null ?
314                 FormUtils.loadClass(declaredSuperclassName, formFile) : Object JavaDoc.class;
315             formBaseClass = checkDeclaredSuperclass(superclass, formInfoName);
316
317             if (formBaseClass != superclass && !underTest)
318                 System.err.println(FormUtils.getFormattedBundleString(
319                     "FMT_IncompatibleFormTypeWarning", // NOI18N
320
new Object JavaDoc[] { javaFile.getName() }));
321
322             formModel.setFormBaseClass(formBaseClass);
323         }
324         catch (Exception JavaDoc ex) {
325             formBaseClassEx = ex;
326         }
327         catch (LinkageError JavaDoc ex) {
328             formBaseClassEx = ex;
329         }
330
331         if (formModel.getFormBaseClass() == null) {
332             // using superclass declared in java source failed, so try to use
333
// some well-known substitute class instead
334
Class JavaDoc substClass = null;
335
336             if (formBaseClass != null) // try to honor the declared superclass
337
substClass = getCompatibleFormClass(formBaseClass);
338  
339             if (substClass == null && formInfoName != null) // fall back to FormInfo type
340
substClass = getCompatibleFormClass(formInfoName);
341
342             if (substClass != null) { // succeeded, there is a substitute class
343
try {
344                     formModel.setFormBaseClass(substClass);
345
346                     // print a warning about using fallback type
347
String JavaDoc msg = FormUtils.getFormattedBundleString(
348                         "FMT_FormTypeWarning", // NOI18N
349
new Object JavaDoc[] { javaFile.getName(),
350                                        substClass.getName(),
351                                        declaredSuperclassName != null ?
352                                          declaredSuperclassName : "<unknown class>" }); // NOI18N
353
System.err.println(msg);
354                     if (formBaseClassEx != null)
355                         formBaseClassEx.printStackTrace();
356                 }
357                 catch (Exception JavaDoc ex) { // should not happen for the substitute types
358
ex.printStackTrace();
359                 }
360                 catch (LinkageError JavaDoc ex) { // should not happen for the substitute types
361
ex.printStackTrace();
362                 }
363             }
364
365             if (formModel.getFormBaseClass() == null) {
366                 // after all, we still cannot determine the form base class
367
String JavaDoc annotation;
368                 if (declaredSuperclassName != null) {
369                     // the class from java source at least can be loaded, but
370
// cannot be used as the form type; no substitute available
371
annotation = FormUtils.getFormattedBundleString(
372                                      "FMT_ERR_InvalidBaseClass", // NOI18N
373
new Object JavaDoc[] { declaredSuperclassName });
374                 }
375                 else { // cannot determine form base class at all;
376
// no substitute available
377
annotation = FormUtils.getBundleString(
378                          "MSG_ERR_CannotDetermineBaseClass"); // NOI18N
379
}
380
381                 PersistenceException ex;
382                 if (formBaseClassEx != null) {
383                     ex = new PersistenceException(formBaseClassEx,
384                                                   "Invalid form base class"); // NOI18N
385
ErrorManager.getDefault().annotate(formBaseClassEx,
386                                                        annotation);
387                 }
388                 else {
389                     ex = new PersistenceException("Invalid form base class"); // NOI18N
390
ErrorManager.getDefault().annotate(
391                         ex, ErrorManager.ERROR, null, annotation, null, null);
392                 }
393                 throw ex;
394             }
395         }
396         // base class set
397
// ---------
398

399         // initial cleanup
400
if (loadedComponents != null)
401             loadedComponents.clear();
402         if (expressions != null)
403             expressions.clear();
404         parentDependentProperties = null;
405         childrenDependentProperties = null;
406         connectedProperties = null;
407
408         this.formModel = formModel;
409         this.nonfatalErrors = nonfatalErrors;
410         this.newLayout = null;
411
412         formModel.setName(javaFile.getName());
413
414         // load "Other Components" first
415
loadNonVisuals(mainElement);
416
417         RADComponent topComp = formModel.getTopRADComponent();
418         if (topComp != null) // load the main form component
419
loadComponent(mainElement, topComp, null);
420
421         if(connectedProperties != null) {
422            connectedProperties.setValues();
423            connectedProperties = null;
424         }
425                 
426         if (Boolean.TRUE.equals(newLayout) && (!underTest)) { // for sure update project classpath with layout extensions library
427
FormEditor.getFormEditor(formModel).updateProjectForNaturalLayout();
428         }
429         if (!Boolean.FALSE.equals(newLayout)) {
430             formModel.setFreeDesignDefaultLayout(true);
431         }
432
433         // final cleanup
434
parentDependentProperties = null;
435         childrenDependentProperties = null;
436         if (expressions != null)
437             expressions.clear();
438         if (loadedComponents != null)
439             loadedComponents.clear();
440         this.formModel = null;
441         return formModel;
442     }
443
444     /**
445      * gets superclass if the 'extends' keyword is present
446      */

447     private static String JavaDoc getSuperClassName(final FileObject javaFile) throws IllegalArgumentException JavaDoc, IOException {
448         final String JavaDoc javaFileName = javaFile.getName();
449         final String JavaDoc[] result = new String JavaDoc[1];
450         JavaSource js = JavaSource.forFileObject(javaFile);
451         js.runUserActionTask(new CancellableTask<CompilationController>() {
452             public void cancel() {
453             }
454             public void run(CompilationController controller) throws Exception JavaDoc {
455                 controller.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
456                 for (Tree t: controller.getCompilationUnit().getTypeDecls()) {
457                     if (t.getKind() == Tree.Kind.CLASS && javaFileName.equals(((ClassTree) t).getSimpleName().toString())) {
458                         Tree superT = ((ClassTree) t).getExtendsClause();
459                         if (superT != null) {
460                             TreePath superTPath = controller.getTrees().getPath(controller.getCompilationUnit(), superT);
461                             Element superEl = controller.getTrees().getElement(superTPath);
462                             if (superEl != null && superEl.getKind() == ElementKind.CLASS) {
463                                 result[0] = ((TypeElement) superEl).getQualifiedName().toString();
464                                 break;
465                             }
466                         }
467                     }
468                 }
469             }
470         }, true);
471         return result[0];
472     }
473     
474     private void loadNonVisuals(org.w3c.dom.Node JavaDoc node) throws PersistenceException {
475         org.w3c.dom.Node JavaDoc nonVisualsNode =
476                                 findSubNode(node, XML_NON_VISUAL_COMPONENTS);
477         org.w3c.dom.NodeList JavaDoc childNodes = nonVisualsNode == null ? null :
478                                           nonVisualsNode.getChildNodes();
479         ArrayList list = new ArrayList();
480
481         if (childNodes != null) {
482             for (int i = 0; i < childNodes.getLength(); i++) {
483                 org.w3c.dom.Node JavaDoc subnode = childNodes.item(i);
484                 if (subnode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
485                     continue; // ignore text nodes
486

487                 RADComponent comp = restoreComponent(subnode, null);
488                 if (comp != null)
489                     list.add(comp);
490             }
491         }
492
493         RADComponent[] nonVisualComps = new RADComponent[list.size()];
494         list.toArray(nonVisualComps);
495         formModel.getModelContainer().initSubComponents(nonVisualComps);
496     }
497
498     // recognizes, creates, initializes and loads a meta component
499
private RADComponent restoreComponent(org.w3c.dom.Node JavaDoc node,
500                                           RADComponent parentComponent)
501         throws PersistenceException
502     {
503         org.w3c.dom.NamedNodeMap JavaDoc attrs = node.getAttributes();
504         if (attrs == null) { // should not be null even if there are no attributes
505
PersistenceException ex = new PersistenceException(
506                       "Missing attributes of component element"); // NOI18N
507
nonfatalErrors.add(ex);
508             return null;
509         }
510
511         org.w3c.dom.Node JavaDoc classNode = attrs.getNamedItem(ATTR_COMPONENT_CLASS);
512         org.w3c.dom.Node JavaDoc nameNode = attrs.getNamedItem(ATTR_COMPONENT_NAME);
513         String JavaDoc className = classNode != null ? classNode.getNodeValue() : null;
514         String JavaDoc compName = nameNode != null ? nameNode.getNodeValue() : null;
515
516         if (className == null) {
517             PersistenceException ex = new PersistenceException(
518                                  "Missing component class name"); // NOI18N
519
String JavaDoc msg = createLoadingErrorMessage(
520                            FormUtils.getBundleString("MSG_ERR_MissingClass"), // NOI18N
521
node);
522             ErrorManager.getDefault().annotate(
523                 ex, ErrorManager.ERROR, null, msg, null, null);
524             nonfatalErrors.add(ex);
525             return null;
526         }
527
528         // first load the component class
529
Class JavaDoc compClass = null;
530         Throwable JavaDoc compEx = null;
531         try {
532             FormLAF.setCustomizingUIClasses(true); // Issue 80198
533
compClass = PersistenceObjectRegistry.loadClass(className, formFile);
534             // Force creation of the default instance in the correct L&F context
535
BeanSupport.getDefaultInstance(compClass);
536         }
537         catch (Exception JavaDoc ex) {
538             compClass = InvalidComponent.class;
539             compEx = ex;
540         }
541         catch (LinkageError JavaDoc ex) {
542             compClass = InvalidComponent.class;
543             compEx = ex;
544         } finally {
545             FormLAF.setCustomizingUIClasses(false);
546         }
547         if (compEx != null) { // loading the component class failed
548
String JavaDoc msg = createLoadingErrorMessage(
549                 FormUtils.getFormattedBundleString("FMT_ERR_CannotLoadClass", // NOI18N
550
new Object JavaDoc[] { className }),
551                 node);
552             ErrorManager.getDefault().annotate(compEx, msg);
553             nonfatalErrors.add(compEx);
554         }
555
556         compEx = null;
557         // create a new metacomponent
558
RADComponent newComponent;
559         String JavaDoc nodeName = node.getNodeName();
560                 
561         if (XML_COMPONENT.equals(nodeName)) {
562             if (compClass == InvalidComponent.class) {
563                 if(parentComponent instanceof RADVisualContainer) {
564                     newComponent = new RADVisualComponent();
565                 } else {
566                     newComponent = new RADComponent();
567                 }
568             } else {
569                 if (java.awt.Component JavaDoc.class.isAssignableFrom(compClass))
570                     newComponent = new RADVisualComponent();
571                 else newComponent = new RADComponent();
572             }
573         }
574         else if (XML_MENU_COMPONENT.equals(nodeName)) {
575             newComponent = new RADMenuItemComponent();
576         }
577         else if (XML_MENU_CONTAINER.equals(nodeName)) {
578             newComponent = new RADMenuComponent();
579         }
580         else if (XML_CONTAINER.equals(nodeName)) {
581             if (compClass == InvalidComponent.class) {
582                 newComponent = new RADVisualContainer();
583             } else {
584                 if (java.awt.Container JavaDoc.class.isAssignableFrom(compClass))
585                     newComponent = new RADVisualContainer();
586                 else newComponent = new RADContainer();
587             }
588         }
589         else {
590             PersistenceException ex = new PersistenceException(
591                                     "Unknown component element"); // NOI18N
592
ErrorManager.getDefault().annotate(
593                 ex,
594                 ErrorManager.ERROR,
595                 null,
596                 FormUtils.getFormattedBundleString("FMT_ERR_UnknownElement", // NOI18N
597
new Object JavaDoc[] { nodeName }),
598                 null,
599                 null);
600             nonfatalErrors.add(ex);
601             return null;
602         }
603
604         // initialize the metacomponent
605
try {
606             if(compClass==InvalidComponent.class){
607                 newComponent.setValid(false);
608                 newComponent.setMissingClassName(className);
609             }
610             newComponent.initialize(formModel);
611             newComponent.setStoredName(compName);
612             newComponent.initInstance(compClass);
613             newComponent.setInModel(true);
614         }
615         catch (Exception JavaDoc ex) {
616             compEx = ex;
617         }
618         catch (LinkageError JavaDoc ex) {
619             compEx = ex;
620         }
621         if (compEx != null) { // creating component instance failed
622
String JavaDoc msg = createLoadingErrorMessage(
623                 FormUtils.getFormattedBundleString("FMT_ERR_CannotCreateInstance", // NOI18N
624
new Object JavaDoc[] { className }),
625                 node);
626             ErrorManager.getDefault().annotate(compEx, msg);
627             nonfatalErrors.add(compEx);
628             return null;
629         }
630
631         getComponentsMap().put(compName, newComponent);
632
633         // load the metacomponent (properties, events, layout, etc)
634
loadComponent(node, newComponent, parentComponent);
635
636         return newComponent;
637     }
638
639     private void loadComponent(org.w3c.dom.Node JavaDoc node,
640                                RADComponent component,
641                                RADComponent parentComponent)
642         throws PersistenceException
643     {
644         org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
645         if (childNodes == null)
646             return;
647
648         org.w3c.dom.Node JavaDoc layoutNode = null;
649         org.w3c.dom.Node JavaDoc layoutCodeNode = null;
650         org.w3c.dom.Node JavaDoc subCompsNode = null;
651         org.w3c.dom.Node JavaDoc constraintsNode = null;
652
653         for (int i = 0; i < childNodes.getLength(); i++) {
654             org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
655             if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
656                 continue; // ignore text nodes
657

658             String JavaDoc nodeName = childNode.getNodeName();
659
660             if (XML_PROPERTIES.equals(nodeName)
661                 || XML_A11Y_PROPERTIES.equals(nodeName))
662             {
663                 loadComponentProperties(childNode, component, nodeName);
664             }
665             else if (XML_EVENTS.equals(nodeName)) {
666                 loadEvents(childNode, component);
667             }
668             else if (XML_CONSTRAINTS.equals(nodeName)) {
669                 constraintsNode = childNode;
670             }
671             else if (XML_LAYOUT.equals(nodeName)) {
672                 if (layoutCodeNode == null)
673                     layoutNode = childNode;
674             }
675             else if (XML_LAYOUT_CODE.equals(nodeName)) {
676                 layoutCodeNode = childNode;
677                 layoutNode = null;
678             }
679             else if (XML_SUB_COMPONENTS.equals(nodeName)) {
680                 subCompsNode = childNode;
681             }
682             else if (XML_AUX_VALUES.equals(nodeName)) {
683                 loadAuxValues(childNode, component);
684             }
685             else if (XML_SYNTHETIC_PROPERTIES.equals(nodeName)) {
686                 loadSyntheticProperties(childNode, component);
687             }
688             // ignore unknown elements?
689
}
690
691         // if the loaded component is a visual component in a visual contianer,
692
// then load NB 3.1 layout constraints for it
693
if (component instanceof RADVisualComponent
694             && parentComponent instanceof RADVisualContainer
695             && layoutConvIndex != LAYOUT_FROM_CODE)
696         {
697             CodeExpression compExp = component.getCodeExpression();
698             LayoutSupportManager layoutSupport =
699                 ((RADVisualContainer)parentComponent).getLayoutSupport();
700
701             org.w3c.dom.Node JavaDoc[] constrNodes = constraintsNode != null ?
702                 findSubNodes(constraintsNode, XML_CONSTRAINT) : null;
703
704             boolean constraintsLoaded = false;
705
706             if (constrNodes != null && constrNodes.length > 0) {
707                 // NB 3.1 used to save all constraints ever set. We must
708
// go through all of them, but only those of current layout
709
// will be loaded.
710
for (int i=0; !constraintsLoaded && i < constrNodes.length; i++)
711                     constraintsLoaded = loadConstraints(constrNodes[i],
712                                                         compExp,
713                                                         layoutSupport);
714             }
715
716             if (!constraintsLoaded)
717                 setupDefaultComponentCode(compExp, layoutSupport);
718         }
719
720         ComponentContainer container = // is this component a container?
721
component instanceof ComponentContainer ?
722                        (ComponentContainer) component : null;
723         if (container == null)
724             return; // this component is not a container
725

726         // we continue in loading container
727

728         RADVisualContainer visualContainer = // is it a visual container?
729
component instanceof RADVisualContainer ?
730                         (RADVisualContainer) component : null;
731
732         if (visualContainer != null)
733             visualContainer.setOldLayoutSupport(true);
734
735         int convIndex = LAYOUT_UNKNOWN;
736         if (visualContainer != null) {
737             if (layoutNode != null) {
738                 // load container layout properties saved in NB 3.1 format;
739
// these properties are loaded before subcomponents
740
convIndex = loadLayout(layoutNode,
741                                        visualContainer.getLayoutSupport());
742             }
743             else if (layoutCodeNode != null) {
744                 convIndex = LAYOUT_FROM_CODE;
745             }
746         }
747
748         // load subcomponents
749
RADComponent[] childComponents;
750         childNodes = subCompsNode != null ?
751                      subCompsNode.getChildNodes() : null;
752         if (childNodes != null) {
753             ArrayList list = new ArrayList();
754             for (int i=0, n=childNodes.getLength(); i < n; i++) {
755                 org.w3c.dom.Node JavaDoc componentNode = childNodes.item(i);
756                 if (componentNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
757                     continue; // ignore text nodes
758

759                 // hack for dealing with multiple constraints saved by NB 3.1
760
layoutConvIndex = convIndex;
761
762                 RADComponent newComp = restoreComponent(componentNode, component);
763
764                 if (newComp != null)
765                     list.add(newComp);
766             }
767
768             childComponents = new RADComponent[list.size()];
769             list.toArray(childComponents);
770         }
771         else childComponents = new RADComponent[0];
772
773         if (visualContainer != null && layoutCodeNode != null) {
774             // load complete layout code (both for container and components);
775
// this container doesn't use NB 3.1 format for saving layout data
776
loadLayoutCode(layoutCodeNode);
777         }
778
779         if (visualContainer != null) {
780             Throwable JavaDoc layoutEx = null;
781             boolean layoutInitialized = false;
782             LayoutSupportManager layoutSupport = visualContainer.getLayoutSupport();
783
784             if (convIndex == LAYOUT_NATURAL) {
785                 LayoutModel layoutModel = formModel.getLayoutModel();
786                 Map JavaDoc<String JavaDoc, String JavaDoc> nameToIdMap = new HashMap();
787                 for (int i=0; i<childComponents.length; i++) {
788                     RADComponent comp = childComponents[i];
789                     nameToIdMap.put(comp.getName(), comp.getId());
790                 }
791                 try {
792                     layoutModel.loadModel(visualContainer.getId(), layoutNode.getChildNodes(), nameToIdMap);
793                     visualContainer.setOldLayoutSupport(false);
794                     layoutSupport = null;
795                     layoutInitialized = true;
796                     newLayout = Boolean.TRUE;
797                 }
798                 catch (Exception JavaDoc ex) {
799                     // error occurred - treat this container as with unknown layout
800
layoutModel.changeContainerToComponent(visualContainer.getId());
801                     layoutEx = ex;
802                 }
803             }
804             else if (convIndex >= 0 || layoutCodeNode != null) {
805                 // initialize layout support from restored code
806
try {
807                     layoutInitialized =
808                         layoutSupport.prepareLayoutDelegate(true, true);
809                 }
810                 catch (Exception JavaDoc ex) {
811                         layoutEx = ex;
812                 }
813                 catch (LinkageError JavaDoc ex) {
814                     layoutEx = ex;
815                 }
816             } else if (layoutNode == null) { // Issue 63394, 68753: Bean form that is container
817
// Issue 70369: Container saved with unknown layout
818
try {
819                     layoutInitialized = layoutSupport.prepareLayoutDelegate(false, true);
820                     if (!layoutInitialized) { // not known to the old support
821
// (but we are sure the container instance is empty)
822
java.awt.Container JavaDoc cont = layoutSupport.getPrimaryContainerDelegate();
823                         if (SwingLayoutBuilder.isRelevantContainer(cont)) {
824                             // acknowledged by SwingLayoutBuilder - this is new layout
825
visualContainer.setOldLayoutSupport(false);
826                             java.awt.Dimension JavaDoc prefSize = cont.getPreferredSize();
827                             java.awt.Insets JavaDoc insets = cont.getInsets();
828                             int w = prefSize != null ? prefSize.width - insets.left - insets.right : 100;
829                             int h = prefSize != null ? prefSize.height - insets.top - insets.bottom : 100;
830                             formModel.getLayoutModel().addRootComponent(
831                                 new LayoutComponent(visualContainer.getId(), true, w, h));
832                             layoutSupport = null;
833                             newLayout = Boolean.TRUE;
834                         }
835                         else {
836                             layoutSupport.setUnknownLayoutDelegate(true);
837                             System.err.println("[WARNING] Unknown layout in "+createLoadingErrorMessage((String JavaDoc)null, node) // NOI18N
838
+" ("+component.getBeanClass().getName()+")"); // NOI18N
839
}
840                         layoutInitialized = true;
841                     }
842                 } catch (Exception JavaDoc ex) {
843                     layoutEx = ex;
844                 }
845             }
846
847             if (!layoutInitialized) {
848                 if (layoutEx != null) { // layout initialization failed
849
org.w3c.dom.Node JavaDoc errNode;
850                     if (layoutNode != null)
851                         errNode = layoutNode;
852                     else if (layoutCodeNode != null)
853                         errNode = layoutCodeNode;
854                     else
855                         errNode = node;
856
857                     String JavaDoc msg = createLoadingErrorMessage(
858                         FormUtils.getBundleString("MSG_ERR_LayoutInitFailed"), // NOI18N
859
errNode);
860                     ErrorManager.getDefault().annotate(layoutEx, msg);
861                     nonfatalErrors.add(layoutEx);
862                 }
863                 else { // no LayoutSupportDelegate found
864
org.w3c.dom.Node JavaDoc errNode;
865                     if (layoutNode != null)
866                         errNode = layoutNode;
867                     else if (layoutCodeNode != null)
868                         errNode = layoutCodeNode;
869                     else
870                         errNode = node;
871
872                     String JavaDoc msg = createLoadingErrorMessage(
873                         FormUtils.getBundleString(
874                             "MSG_ERR_NoLayoutSupportFound"), // NOI18N
875
errNode);
876
877                     PersistenceException ex = new PersistenceException(
878                                               "No layout support found"); // NOI18N
879
ErrorManager.getDefault().annotate(
880                         ex, ErrorManager.ERROR, null, msg, null, null);
881                     nonfatalErrors.add(ex);
882                 }
883                 layoutSupport.setUnknownLayoutDelegate(true);
884             }
885
886             visualContainer.initSubComponents(childComponents);
887             if (layoutSupport != null) {
888                 if (newLayout == null) {
889                     newLayout = Boolean.FALSE;
890                 }
891                 try { // some weird problems might occur - see issue 67890
892
layoutSupport.updatePrimaryContainer();
893                 }
894                 // can't do anything reasonable on failure, just log stack trace
895
catch (Exception JavaDoc ex) {
896                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
897                 }
898                 catch (Error JavaDoc ex) {
899                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
900                 }
901             }
902         }
903         else // non-visual container
904
container.initSubComponents(childComponents);
905
906         // hack for properties that can't be set until the component is added
907
// to the parent container
908
for (RADComponent childcomp : childComponents) {
909             List postProps;
910             if (parentDependentProperties != null
911                 && (postProps = parentDependentProperties.get(childcomp)) != null)
912             {
913                 for (Iterator it = postProps.iterator(); it.hasNext(); ) {
914                     RADProperty prop = (RADProperty) it.next();
915                     Object JavaDoc propValue = it.next();
916                     try {
917                         prop.setValue(propValue);
918                     }
919                     catch (Exception JavaDoc ex) { // ignore
920
String JavaDoc msg = createLoadingErrorMessage(
921                             FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
922
node);
923                         ErrorManager.getDefault().annotate(ex, msg);
924                         nonfatalErrors.add(ex);
925                     }
926                 }
927             }
928         }
929
930         // hack for properties that can't be set until all subcomponents
931
// are added to the container
932
List postProps;
933         if (childrenDependentProperties != null
934             && (postProps = childrenDependentProperties.get(component)) != null)
935         {
936             for (Iterator it = postProps.iterator(); it.hasNext(); ) {
937                 RADProperty prop = (RADProperty) it.next();
938                 Object JavaDoc propValue = it.next();
939                 try {
940                     prop.setValue(propValue);
941                 }
942                 catch (Exception JavaDoc ex) { // ignore
943
String JavaDoc msg = createLoadingErrorMessage(
944                         FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
945
node);
946                     ErrorManager.getDefault().annotate(ex, msg);
947                     nonfatalErrors.add(ex);
948                 }
949             }
950         }
951     }
952
953     private boolean loadConstraints(org.w3c.dom.Node JavaDoc node,
954                                     CodeExpression compExp,
955                                     LayoutSupportManager layoutSupport)
956     {
957         int convIndex = -1;
958         String JavaDoc layout31ConstraintName = node != null ?
959                    getAttribute(node, ATTR_CONSTRAINT_VALUE) : null;
960         if (layout31ConstraintName != null)
961             for (int i=0; i < layout31ConstraintsNames.length; i++)
962                 if (layout31ConstraintName.equals(layout31ConstraintsNames[i])) {
963                     convIndex = i;
964                     break;
965                 }
966
967         // skip constraints saved by NB 3.1 which are not for the current layout
968
if (convIndex < 0
969                 || (layoutConvIndex >= 0 && convIndex != layoutConvIndex))
970             return false;
971
972         org.w3c.dom.Node JavaDoc constrNode = null;
973         org.w3c.dom.NamedNodeMap JavaDoc constrAttr = null;
974
975         if (/*convIndex >= 0 &&*/reasonable31Constraints[convIndex]) {
976             org.w3c.dom.NodeList JavaDoc children = node.getChildNodes();
977             if (children != null)
978                 for (int i=0, n=children.getLength(); i < n; i++) {
979                     org.w3c.dom.Node JavaDoc cNode = children.item(i);
980                     if (cNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
981                         constrNode = cNode;
982                         constrAttr = cNode.getAttributes();
983                         break;
984                     }
985                 }
986         }
987
988         if (constrNode == null)
989             return false;
990
991         try { // obligatory try/catch block for finding methods and constructors
992

993         CodeStructure codeStructure = layoutSupport.getCodeStructure();
994         CodeExpression contCodeExp = layoutSupport.getContainerCodeExpression();
995         CodeExpression contDelCodeExp =
996             layoutSupport.getContainerDelegateCodeExpression();
997
998         if (convIndex == LAYOUT_BORDER) {
999             if (!"BorderConstraints".equals(constrNode.getNodeName())) // NOI18N
1000
return false; // should not happen
1001

1002            node = constrAttr.getNamedItem("direction"); // NOI18N
1003
if (node != null) {
1004                String JavaDoc strValue = node.getNodeValue();
1005                // create add method statement
1006
CodeStructure.createStatement(
1007                    contDelCodeExp,
1008                    getAddWithConstrMethod(),
1009                    new CodeExpression[] { compExp,
1010                                           codeStructure.createExpression(
1011                                                           String JavaDoc.class,
1012                                                           strValue,
1013                                                           strValue) });
1014            }
1015        }
1016
1017        else if (convIndex == LAYOUT_GRIDBAG) {
1018            if (!"GridBagConstraints".equals(constrNode.getNodeName())) // NOI18N
1019
return false; // should not happen
1020

1021            // create GridBagConstraints constructor expression
1022
if (gridBagConstrConstructor == null)
1023                gridBagConstrConstructor =
1024                    java.awt.GridBagConstraints JavaDoc.class.getConstructor(
1025                                                          new Class JavaDoc[0]);
1026
1027            CodeExpression constrExp = codeStructure.createExpression(
1028                    gridBagConstrConstructor, CodeStructure.EMPTY_PARAMS);
1029
1030            // create statements for GridBagConstraints fields
1031
String JavaDoc[] gbcAttrs = new String JavaDoc[] {
1032                "gridX", "gridY", "gridWidth", "gridHeight", // NOI18N
1033
"fill", "ipadX", "ipadY", // NOI18N
1034
"anchor", "weightX", "weightY" }; // NOI18N
1035
String JavaDoc[] gbcFields = new String JavaDoc[] {
1036                "gridx", "gridy", "gridwidth", "gridheight", // NOI18N
1037
"fill", "ipadx", "ipady", // NOI18N
1038
"anchor", "weightx", "weighty" }; // NOI18N
1039

1040            for (int i=0; i < gbcAttrs.length; i++) {
1041                node = constrAttr.getNamedItem(gbcAttrs[i]);
1042                if (node != null) {
1043                    Class JavaDoc valueType;
1044                    Object JavaDoc value;
1045                    String JavaDoc strValue = node.getNodeValue();
1046                    if (i < 8) { // treat as int
1047
valueType = Integer.TYPE;
1048                        value = Integer.valueOf(strValue);
1049                    }
1050                    else { // treat as double
1051
valueType = Double.TYPE;
1052                        value = Double.valueOf(strValue);
1053                    }
1054
1055                    CodeStructure.createStatement(
1056                        constrExp,
1057                        java.awt.GridBagConstraints JavaDoc.class.getField(gbcFields[i]),
1058                        codeStructure.createExpression(valueType, value, strValue));
1059                }
1060            }
1061
1062            // Insets
1063
CodeExpression[] insetsParams = new CodeExpression[4];
1064            String JavaDoc[] insetsAttrs = new String JavaDoc[] {
1065                "insetsTop", "insetsLeft", "insetsBottom", "insetsRight" }; // NOI18N
1066

1067            for (int i=0; i < insetsAttrs.length; i++) {
1068                node = constrAttr.getNamedItem(insetsAttrs[i]);
1069                String JavaDoc strValue = node != null ? node.getNodeValue() : "0"; // NOI18N
1070
insetsParams[i] = codeStructure.createExpression(
1071                                                    Integer.TYPE,
1072                                                    Integer.valueOf(strValue),
1073                                                    strValue);
1074            }
1075
1076            if (insetsConstructor == null)
1077                insetsConstructor = java.awt.Insets JavaDoc.class.getConstructor(
1078                    new Class JavaDoc[] { Integer.TYPE, Integer.TYPE,
1079                                  Integer.TYPE, Integer.TYPE });
1080
1081            CodeStructure.createStatement(
1082                          constrExp,
1083                          java.awt.GridBagConstraints JavaDoc.class.getField("insets"), // NOI18N
1084
codeStructure.createExpression(insetsConstructor,
1085                                                         insetsParams));
1086
1087            // create add method statement
1088
CodeStructure.createStatement(
1089                contDelCodeExp,
1090                getAddWithConstrMethod(),
1091                new CodeExpression[] { compExp, constrExp });
1092        }
1093
1094        else if (convIndex == LAYOUT_JTAB) {
1095            if (!"JTabbedPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
1096
return false; // should not happen
1097

1098            Object JavaDoc tabName = null;
1099            PropertyEditor tabNamePropEd = null;
1100            Object JavaDoc toolTip = null;
1101            PropertyEditor toolTipPropEd = null;
1102            Object JavaDoc icon = null;
1103            PropertyEditor iconPropEd = null;
1104
1105            org.w3c.dom.Node JavaDoc[] propNodes = findSubNodes(constrNode, XML_PROPERTY);
1106            if (propNodes != null)
1107                for (int i=0; i < propNodes.length; i++) {
1108                    Object JavaDoc editorOrValue = getPropertyEditorOrValue(propNodes[i]);
1109                     if (editorOrValue == NO_VALUE)
1110                         continue;
1111
1112                    PropertyEditor prEd = null;
1113                    Object JavaDoc value = null;
1114                    if (editorOrValue instanceof PropertyEditor)
1115                        prEd = (PropertyEditor) editorOrValue;
1116                    else
1117                        value = editorOrValue;
1118
1119                    String JavaDoc name = getAttribute(propNodes[i], ATTR_PROPERTY_NAME);
1120                    if ("tabTitle".equals(name)) { // NOI18N
1121
tabName = value;
1122                        tabNamePropEd = prEd;
1123                    }
1124                    else if ("tabToolTip".equals(name)) { // NOI18N
1125
toolTip = value;
1126                        toolTipPropEd = prEd;
1127                    }
1128                    else if ("tabIcon".equals(name)) { // NOI18N
1129
icon = value;
1130                        iconPropEd = prEd;
1131                    }
1132                }
1133
1134            if (tabName == null
1135                    && (node = constrAttr.getNamedItem("tabName")) != null) // NOI18N
1136
tabName = node.getNodeValue();
1137            if (toolTip == null
1138                    && (node = constrAttr.getNamedItem("toolTip")) != null) // NOI18N
1139
toolTip = node.getNodeValue();
1140
1141            if (toolTip != null || toolTipPropEd != null) {
1142                if (addTabMethod1 == null)
1143                    addTabMethod1 = javax.swing.JTabbedPane JavaDoc.class.getMethod(
1144                                    "addTab", // NOI18N
1145
new Class JavaDoc[] { String JavaDoc.class,
1146                                                  javax.swing.Icon JavaDoc.class,
1147                                                  java.awt.Component JavaDoc.class,
1148                                                  String JavaDoc.class });
1149                CodeStructure.createStatement(
1150                    contCodeExp,
1151                    addTabMethod1,
1152                    new CodeExpression[] {
1153                        createExpressionForProperty(
1154                            codeStructure, String JavaDoc.class, tabName, tabNamePropEd),
1155                        createExpressionForProperty(
1156                            codeStructure, javax.swing.Icon JavaDoc.class, icon, iconPropEd),
1157                        compExp,
1158                        createExpressionForProperty(
1159                            codeStructure, String JavaDoc.class, toolTip, toolTipPropEd) });
1160            }
1161            else if (icon != null || iconPropEd != null) {
1162                if (addTabMethod2 == null)
1163                    addTabMethod2 = javax.swing.JTabbedPane JavaDoc.class.getMethod(
1164                                    "addTab", // NOI18N
1165
new Class JavaDoc[] { String JavaDoc.class,
1166                                                  javax.swing.Icon JavaDoc.class,
1167                                                  java.awt.Component JavaDoc.class });
1168                CodeStructure.createStatement(
1169                    contCodeExp,
1170                    addTabMethod2,
1171                    new CodeExpression[] {
1172                        createExpressionForProperty(
1173                            codeStructure, String JavaDoc.class, tabName, tabNamePropEd),
1174                        createExpressionForProperty(
1175                            codeStructure, javax.swing.Icon JavaDoc.class, icon, iconPropEd),
1176                        compExp });
1177            }
1178            else {
1179                if (addTabMethod3 == null)
1180                    addTabMethod3 = javax.swing.JTabbedPane JavaDoc.class.getMethod(
1181                                    "addTab", // NOI18N
1182
new Class JavaDoc[] { String JavaDoc.class,
1183                                                  java.awt.Component JavaDoc.class });
1184                CodeStructure.createStatement(
1185                    contCodeExp,
1186                    addTabMethod3,
1187                    new CodeExpression[] {
1188                        createExpressionForProperty(
1189                            codeStructure, String JavaDoc.class, tabName, tabNamePropEd),
1190                        compExp });
1191            }
1192        }
1193
1194        else if (convIndex == LAYOUT_JSPLIT) {
1195            if (!"JSplitPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
1196
return false;
1197
1198            node = constrAttr.getNamedItem("position"); // NOI18N
1199
if (node != null) {
1200                String JavaDoc position = node.getNodeValue();
1201                Method addMethod;
1202
1203                if ("top".equals(position)) { // NOI18N
1204
if (setTopComponentMethod == null)
1205                        setTopComponentMethod =
1206                            javax.swing.JSplitPane JavaDoc.class.getMethod(
1207                                    "setTopComponent", // NOI18N
1208
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1209                    addMethod = setTopComponentMethod;
1210                }
1211                else if ("bottom".equals(position)) { // NOI18N
1212
if (setBottomComponentMethod == null)
1213                        setBottomComponentMethod =
1214                            javax.swing.JSplitPane JavaDoc.class.getMethod(
1215                                    "setBottomComponent", // NOI18N
1216
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1217                    addMethod = setBottomComponentMethod;
1218                }
1219                else if ("left".equals(position)) { // NOI18N
1220
if (setLeftComponentMethod == null)
1221                        setLeftComponentMethod =
1222                            javax.swing.JSplitPane JavaDoc.class.getMethod(
1223                                    "setLeftComponent", // NOI18N
1224
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1225                    addMethod = setLeftComponentMethod;
1226                }
1227                else if ("right".equals(position)) { // NOI18N
1228
if (setRightComponentMethod == null)
1229                        setRightComponentMethod =
1230                            javax.swing.JSplitPane JavaDoc.class.getMethod(
1231                                    "setRightComponent", // NOI18N
1232
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1233                    addMethod = setRightComponentMethod;
1234                }
1235                else return false;
1236
1237                CodeStructure.createStatement(contCodeExp,
1238                                              addMethod,
1239                                              new CodeExpression[] { compExp });
1240            }
1241        }
1242
1243        else if (convIndex == LAYOUT_CARD) {
1244            if (!"CardConstraints".equals(constrNode.getNodeName())) // NOI18N
1245
return false;
1246
1247            node = constrAttr.getNamedItem("cardName"); // NOI18N
1248
if (node != null) {
1249                String JavaDoc strValue = node.getNodeValue();
1250                // create add method statement
1251
CodeStructure.createStatement(
1252                    contDelCodeExp,
1253                    getAddWithConstrMethod(),
1254                    new CodeExpression[] { compExp,
1255                                           codeStructure.createExpression(
1256                                                           String JavaDoc.class,
1257                                                           strValue,
1258                                                           strValue) });
1259            }
1260        }
1261
1262        else if (convIndex == LAYOUT_JLAYER) {
1263            if (!"JLayeredPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
1264
return false;
1265
1266            CodeExpression[] boundsParams = new CodeExpression[4];
1267            String JavaDoc[] boundsAttrs = new String JavaDoc[] { "x", "y", "width", "height" }; // NOI18N
1268

1269            for (int i=0; i < boundsAttrs.length; i++) {
1270                node = constrAttr.getNamedItem(boundsAttrs[i]);
1271                String JavaDoc strValue = node != null ?
1272                                      node.getNodeValue() :
1273                                      (i < 2 ? "0" : "-1"); // NOI18N
1274
boundsParams[i] = codeStructure.createExpression(
1275                                                    Integer.TYPE,
1276                                                    Integer.valueOf(strValue),
1277                                                    strValue);
1278            }
1279
1280            if (setBoundsMethod == null)
1281                setBoundsMethod = java.awt.Component JavaDoc.class.getMethod(
1282                                    "setBounds", // NOI18N
1283
new Class JavaDoc[] { Integer.TYPE, Integer.TYPE,
1284                                                  Integer.TYPE, Integer.TYPE });
1285            CodeStructure.createStatement(
1286                            compExp, setBoundsMethod, boundsParams);
1287
1288            node = constrAttr.getNamedItem("layer"); // NOI18N
1289
if (node != null) {
1290                String JavaDoc strValue = node.getNodeValue();
1291                // create add method statement
1292
CodeStructure.createStatement(
1293                    contDelCodeExp,
1294                    getAddWithConstrMethod(),
1295                    new CodeExpression[] { compExp,
1296                                           codeStructure.createExpression(
1297                                               Integer.TYPE,
1298                                               Integer.valueOf(strValue),
1299                                               strValue) });
1300            }
1301        }
1302
1303        else if (convIndex == LAYOUT_ABSOLUTE) {
1304            if (!"AbsoluteConstraints".equals(constrNode.getNodeName())) // NOI18N
1305
return false;
1306
1307            CodeExpression[] boundsParams = new CodeExpression[4];
1308            String JavaDoc[] boundsAttrs = new String JavaDoc[] { "x", "y", "width", "height" }; // NOI18N
1309

1310            for (int i=0; i < boundsAttrs.length; i++) {
1311                node = constrAttr.getNamedItem(boundsAttrs[i]);
1312                String JavaDoc strValue = node != null ?
1313                                      node.getNodeValue() :
1314                                      (i < 2 ? "0" : "-1"); // NOI18N
1315
boundsParams[i] = codeStructure.createExpression(
1316                                                    Integer.TYPE,
1317                                                    Integer.valueOf(strValue),
1318                                                    strValue);
1319            }
1320
1321            Iterator it = CodeStructure.getDefinedStatementsIterator(contDelCodeExp);
1322            CodeStatement[] statements = CodeStructure.filterStatements(
1323                                                it, getSetLayoutMethod());
1324            boolean nullLayout;
1325            if (statements.length > 0) {
1326                CodeExpression layoutExp =
1327                    statements[0].getStatementParameters()[0];
1328                nullLayout = layoutExp.getOrigin().getType()
1329                             != org.netbeans.lib.awtextra.AbsoluteLayout.class;
1330            }
1331            else nullLayout = true;
1332
1333            if (nullLayout) {
1334                if (setBoundsMethod == null)
1335                    setBoundsMethod = java.awt.Component JavaDoc.class.getMethod(
1336                                      "setBounds", // NOI18N
1337
new Class JavaDoc[] { Integer.TYPE, Integer.TYPE,
1338                                                    Integer.TYPE, Integer.TYPE });
1339                CodeStructure.createStatement(
1340                    compExp, setBoundsMethod, boundsParams);
1341
1342                // create add method statement
1343
CodeStructure.createStatement(contDelCodeExp,
1344                                              getSimpleAddMethod(),
1345                                              new CodeExpression[] { compExp });
1346            }
1347            else {
1348                if (absoluteConstraintsConstructor == null)
1349                    absoluteConstraintsConstructor =
1350                        org.netbeans.lib.awtextra.AbsoluteConstraints.class
1351                                                      .getConstructor(
1352                            new Class JavaDoc[] { Integer.TYPE, Integer.TYPE,
1353                                          Integer.TYPE, Integer.TYPE });
1354
1355                // create add method statement
1356
CodeStructure.createStatement(
1357                    contDelCodeExp,
1358                    getAddWithConstrMethod(),
1359                    new CodeExpression[] { compExp,
1360                                        codeStructure.createExpression(
1361                                            absoluteConstraintsConstructor,
1362                                            boundsParams) });
1363            }
1364        }
1365
1366        return true;
1367
1368        }
1369        catch (NoSuchMethodException JavaDoc ex) { // should not happen
1370
ex.printStackTrace();
1371        }
1372        catch (NoSuchFieldException JavaDoc ex) { // should not happen
1373
ex.printStackTrace();
1374        }
1375        return false;
1376    }
1377
1378    private void setupDefaultComponentCode(CodeExpression compExp,
1379                                           LayoutSupportManager layoutSupport)
1380    {
1381        if (layoutConvIndex == LAYOUT_JSCROLL) {
1382            // JScrollPane requires special add code although there are
1383
// no constraints ...
1384
if (setViewportViewMethod == null) {
1385                try {
1386                    setViewportViewMethod =
1387                            javax.swing.JScrollPane JavaDoc.class.getMethod(
1388                                    "setViewportView", // NOI18N
1389
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1390                }
1391                catch (NoSuchMethodException JavaDoc ex) { // should not happen
1392
ex.printStackTrace();
1393                    return;
1394                }
1395            }
1396
1397            CodeStructure.createStatement(
1398                              layoutSupport.getContainerCodeExpression(),
1399                              setViewportViewMethod,
1400                              new CodeExpression[] { compExp });
1401        }
1402        else { // create simple add method statement with no constraints
1403
CodeStructure.createStatement(
1404                    layoutSupport.getContainerDelegateCodeExpression(),
1405                    getSimpleAddMethod(),
1406                    new CodeExpression[] { compExp });
1407        }
1408    }
1409
1410    private static Method getSimpleAddMethod() {
1411        if (simpleAddMethod == null) {
1412            try {
1413                simpleAddMethod = java.awt.Container JavaDoc.class.getMethod(
1414                                      "add", // NOI18N
1415
new Class JavaDoc[] { java.awt.Component JavaDoc.class });
1416            }
1417            catch (NoSuchMethodException JavaDoc ex) { // should not happen
1418
ex.printStackTrace();
1419            }
1420        }
1421        return simpleAddMethod;
1422    }
1423
1424    private static Method getAddWithConstrMethod() {
1425        if (addWithConstrMethod == null) {
1426            try {
1427                addWithConstrMethod = java.awt.Container JavaDoc.class.getMethod(
1428                                      "add", // NOI18N
1429
new Class JavaDoc[] { java.awt.Component JavaDoc.class,
1430                                                    Object JavaDoc.class });
1431            }
1432            catch (NoSuchMethodException JavaDoc ex) { // should not happen
1433
ex.printStackTrace();
1434            }
1435        }
1436        return addWithConstrMethod;
1437    }
1438
1439    private static Method getSetLayoutMethod() {
1440        if (setLayoutMethod == null) {
1441            try {
1442                setLayoutMethod = java.awt.Container JavaDoc.class.getMethod(
1443                            "setLayout", // NOI18N
1444
new Class JavaDoc[] { java.awt.LayoutManager JavaDoc.class });
1445            }
1446            catch (NoSuchMethodException JavaDoc ex) { // should not happen
1447
ex.printStackTrace();
1448            }
1449        }
1450        return setLayoutMethod;
1451    }
1452
1453    private int loadLayout(org.w3c.dom.Node JavaDoc layoutNode,
1454                           LayoutSupportManager layoutSupport)
1455    {
1456        org.w3c.dom.NamedNodeMap JavaDoc layoutAttr = layoutNode.getAttributes();
1457        org.w3c.dom.Node JavaDoc node = layoutAttr.getNamedItem(ATTR_LAYOUT_CLASS);
1458        if (node == null)
1459            return LAYOUT_NATURAL;
1460
1461        String JavaDoc layout31Name = PersistenceObjectRegistry.getClassName(
1462                                                            node.getNodeValue());
1463        int convIndex = -1;
1464        for (int i=0; i < layout31Names.length; i++)
1465            if (layout31Name.equals(layout31Names[i])) {
1466                convIndex = i;
1467                break;
1468            }
1469
1470        if (convIndex < 0)
1471            return -1; // unknown layout
1472

1473        org.w3c.dom.Node JavaDoc[] propNodes = findSubNodes(layoutNode, XML_PROPERTY);
1474        List propertyNames = null;
1475        List propertyValues = null;
1476        List propertyEditors = null;
1477
1478        if (propNodes != null && propNodes.length > 0) {
1479            propertyNames = new ArrayList(propNodes.length);
1480            propertyValues = new ArrayList(propNodes.length);
1481            propertyEditors = new ArrayList(propNodes.length);
1482
1483            for (int i=0; i < propNodes.length; i++) {
1484                node = propNodes[i];
1485
1486                Object JavaDoc editorOrValue = getPropertyEditorOrValue(node);
1487                if (editorOrValue == NO_VALUE)
1488                    continue;
1489
1490                propertyNames.add(getAttribute(node, ATTR_PROPERTY_NAME));
1491                if (editorOrValue instanceof PropertyEditor) {
1492                    propertyEditors.add(editorOrValue);
1493                    propertyValues.add(null);
1494                }
1495                else {
1496                    propertyValues.add(editorOrValue);
1497                    propertyEditors.add(null);
1498                }
1499            }
1500        }
1501
1502        CodeStructure codeStructure = layoutSupport.getCodeStructure();
1503        CodeExpression[] layoutParams = null;
1504        Class JavaDoc[] paramTypes = null;
1505        Class JavaDoc layoutClass = null;
1506
1507        String JavaDoc[] layoutPropNames = layout31PropertyNames[convIndex];
1508        if (convIndex == LAYOUT_BORDER) {
1509            int hgap = findName(layoutPropNames[0], propertyNames);
1510            int vgap = findName(layoutPropNames[1], propertyNames);
1511            if (hgap >= 0 || vgap >= 0) {
1512                layoutParams = new CodeExpression[2];
1513
1514                layoutParams[0] = createExpressionForProperty(
1515                    codeStructure,
1516                    Integer.TYPE,
1517                    hgap >= 0 ? propertyValues.get(hgap) : new Integer JavaDoc(0),
1518                    (PropertyEditor)
1519                        (hgap >= 0 ? propertyEditors.get(hgap) : null));
1520
1521                layoutParams[1] = createExpressionForProperty(
1522                    codeStructure,
1523                    Integer.TYPE,
1524                    vgap >= 0 ? propertyValues.get(vgap) : new Integer JavaDoc(0),
1525                    (PropertyEditor)
1526                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
1527            }
1528            else {
1529                layoutParams = CodeStructure.EMPTY_PARAMS;
1530            }
1531            layoutClass = java.awt.BorderLayout JavaDoc.class;
1532        }
1533
1534        else if (convIndex == LAYOUT_FLOW) {
1535            int alignment = findName(layoutPropNames[0], propertyNames);
1536            int hgap = findName(layoutPropNames[1], propertyNames);
1537            int vgap = findName(layoutPropNames[2], propertyNames);
1538            if (hgap >= 0 || vgap >= 0) {
1539                layoutParams = new CodeExpression[3];
1540
1541                layoutParams[0] = createExpressionForProperty(
1542                    codeStructure,
1543                    Integer.TYPE,
1544                    alignment >= 0 ? propertyValues.get(alignment) : new Integer JavaDoc(1),
1545                    (PropertyEditor)
1546                        (alignment >= 0 ? propertyEditors.get(alignment) : null));
1547
1548                layoutParams[1] = createExpressionForProperty(
1549                    codeStructure,
1550                    Integer.TYPE,
1551                    hgap >= 0 ? propertyValues.get(hgap) : new Integer JavaDoc(5),
1552                    (PropertyEditor)
1553                        (hgap >= 0 ? propertyEditors.get(hgap) : null));
1554
1555                layoutParams[2] = createExpressionForProperty(
1556                    codeStructure,
1557                    Integer.TYPE,
1558                    vgap >= 0 ? propertyValues.get(vgap) : new Integer JavaDoc(5),
1559                    (PropertyEditor)
1560                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
1561            }
1562            else if (alignment >= 0) {
1563                layoutParams = new CodeExpression[1];
1564
1565                layoutParams[0] = createExpressionForProperty(
1566                    codeStructure,
1567                    Integer.TYPE,
1568                    alignment >= 0 ? propertyValues.get(alignment) : new Integer JavaDoc(1),
1569                    (PropertyEditor)
1570                        (alignment >= 0 ? propertyEditors.get(alignment) : null));
1571            }
1572            else {
1573                layoutParams = CodeStructure.EMPTY_PARAMS;
1574            }
1575            layoutClass = java.awt.FlowLayout JavaDoc.class;
1576        }
1577
1578        else if (convIndex == LAYOUT_GRIDBAG) {
1579            layoutParams = CodeStructure.EMPTY_PARAMS;
1580            layoutClass = java.awt.GridBagLayout JavaDoc.class;
1581        }
1582
1583        else if (convIndex == LAYOUT_BOX) {
1584            int axis = findName(layoutPropNames[0],
1585                                propertyNames);
1586
1587            layoutParams = new CodeExpression[2];
1588            layoutParams[0] = layoutSupport.getContainerDelegateCodeExpression();
1589            layoutParams[1] = createExpressionForProperty(
1590                codeStructure,
1591                Integer.TYPE,
1592                axis >= 0 ? propertyValues.get(axis) : new Integer JavaDoc(javax.swing.BoxLayout.LINE_AXIS),
1593                (PropertyEditor)
1594                    (axis >= 0 ? propertyEditors.get(axis) : null));
1595
1596            paramTypes = new Class JavaDoc[] { java.awt.Container JavaDoc.class, Integer.TYPE };
1597            layoutClass = javax.swing.BoxLayout JavaDoc.class;
1598        }
1599
1600        else if (convIndex == LAYOUT_GRID) {
1601            int rows = findName(layoutPropNames[0], propertyNames);
1602            int columns = findName(layoutPropNames[1], propertyNames);
1603            int hgap = findName(layoutPropNames[2], propertyNames);
1604            int vgap = findName(layoutPropNames[3], propertyNames);
1605            if (hgap >= 0 || vgap >= 0) {
1606                layoutParams = new CodeExpression[4];
1607
1608                layoutParams[0] = createExpressionForProperty(
1609                    codeStructure,
1610                    Integer.TYPE,
1611                    rows >= 0 ? propertyValues.get(rows) : new Integer JavaDoc(1),
1612                    (PropertyEditor)
1613                        (rows >= 0 ? propertyEditors.get(rows) : null));
1614
1615                layoutParams[1] = createExpressionForProperty(
1616                    codeStructure,
1617                    Integer.TYPE,
1618                    columns >= 0 ? propertyValues.get(columns) : new Integer JavaDoc(0),
1619                    (PropertyEditor)
1620                        (columns >= 0 ? propertyEditors.get(columns) : null));
1621
1622                layoutParams[2] = createExpressionForProperty(
1623                    codeStructure,
1624                    Integer.TYPE,
1625                    hgap >= 0 ? propertyValues.get(hgap) : new Integer JavaDoc(0),
1626                    (PropertyEditor)
1627                        (hgap >= 0 ? propertyEditors.get(hgap) : null));
1628
1629                layoutParams[3] = createExpressionForProperty(
1630                    codeStructure,
1631                    Integer.TYPE,
1632                    vgap >= 0 ? propertyValues.get(vgap) : new Integer JavaDoc(0),
1633                    (PropertyEditor)
1634                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
1635            }
1636            else if (rows >= 0 || columns >= 0) {
1637                layoutParams = new CodeExpression[2];
1638
1639                layoutParams[0] = createExpressionForProperty(
1640                    codeStructure,
1641                    Integer.TYPE,
1642                    rows >= 0 ? propertyValues.get(rows) : new Integer JavaDoc(1),
1643                    (PropertyEditor)
1644                        (rows >= 0 ? propertyEditors.get(rows) : null));
1645
1646                layoutParams[1] = createExpressionForProperty(
1647                    codeStructure,
1648                    Integer.TYPE,
1649                    columns >= 0 ? propertyValues.get(columns) : new Integer JavaDoc(0),
1650                    (PropertyEditor)
1651                        (columns >= 0 ? propertyEditors.get(columns) : null));
1652            }
1653            else {
1654                layoutParams = CodeStructure.EMPTY_PARAMS;
1655            }
1656            layoutClass = java.awt.GridLayout JavaDoc.class;
1657        }
1658
1659        else if (convIndex == LAYOUT_CARD) {
1660            int hgap = findName(layoutPropNames[0], propertyNames);
1661            int vgap = findName(layoutPropNames[1], propertyNames);
1662            if (hgap >= 0 && vgap >= 0) {
1663                layoutParams = new CodeExpression[2];
1664
1665                layoutParams[0] = createExpressionForProperty(
1666                    codeStructure,
1667                    Integer.TYPE,
1668                    hgap >= 0 ? propertyValues.get(hgap) : new Integer JavaDoc(0),
1669                    (PropertyEditor)
1670                        (hgap >= 0 ? propertyEditors.get(hgap) : null));
1671
1672                layoutParams[1] = createExpressionForProperty(
1673                    codeStructure,
1674                    Integer.TYPE,
1675                    vgap >= 0 ? propertyValues.get(vgap) : new Integer JavaDoc(0),
1676                    (PropertyEditor)
1677                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
1678            }
1679            else {
1680                layoutParams = CodeStructure.EMPTY_PARAMS;
1681            }
1682            layoutClass = java.awt.CardLayout JavaDoc.class;
1683        }
1684
1685        else if (convIndex == LAYOUT_ABSOLUTE) {
1686            boolean nullLayout = false;
1687            int i = findName("useNullLayout", propertyNames); // NOI18N
1688
if (i >= 0)
1689                nullLayout = Boolean.TRUE.equals(propertyValues.get(i));
1690
1691            layoutParams = CodeStructure.EMPTY_PARAMS;
1692            layoutClass = nullLayout ? null :
1693                          org.netbeans.lib.awtextra.AbsoluteLayout.class;
1694        }
1695
1696        else return convIndex; // no layout manager
1697

1698        CodeExpression layoutExp;
1699        if (layoutClass != null) {
1700            if (paramTypes == null) {
1701                paramTypes = new Class JavaDoc[layoutParams.length];
1702                for (int i=0; i < layoutParams.length; i++)
1703                    paramTypes[i] = layoutParams[i].getOrigin().getType();
1704            }
1705
1706            Constructor layoutConstructor;
1707            try {
1708                layoutConstructor = layoutClass.getConstructor(paramTypes);
1709            }
1710            catch (NoSuchMethodException JavaDoc ex) { // should not happen
1711
ex.printStackTrace();
1712                return -1;
1713            }
1714            layoutExp = layoutSupport.getCodeStructure().createExpression(
1715                                layoutConstructor, layoutParams);
1716        }
1717        else {
1718            layoutExp = layoutSupport.getCodeStructure().createNullExpression(
1719                                                 java.awt.LayoutManager JavaDoc.class);
1720        }
1721
1722        CodeStructure.createStatement(
1723            layoutSupport.getContainerDelegateCodeExpression(),
1724            getSetLayoutMethod(),
1725            new CodeExpression[] { layoutExp });
1726
1727        return convIndex;
1728    }
1729
1730    private static CodeExpression createExpressionForProperty(
1731                                      CodeStructure codeStructure,
1732                                      Class JavaDoc type,
1733                                      Object JavaDoc value,
1734                                      PropertyEditor propEd)
1735    {
1736        return propEd != null ?
1737            codeStructure.createExpression(FormCodeSupport.createOrigin(
1738                                                           type, propEd)) :
1739            codeStructure.createExpression(type,
1740                                           value,
1741                                           value != null ?
1742                                               value.toString() : "null"); // NOI18N
1743
}
1744
1745    private static int findName(String JavaDoc name, List names) {
1746        return names != null ? names.indexOf(name) : -1;
1747    }
1748
1749    private void loadLayoutCode(org.w3c.dom.Node JavaDoc node) {
1750        org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
1751        if (childNodes != null) {
1752// codeFlow = true;
1753
for (int i=0, n=childNodes.getLength(); i < n; i++) {
1754                org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
1755
1756                if (XML_CODE_STATEMENT.equals(childNode.getNodeName()))
1757                    loadCodeStatement(childNode, null);
1758            }
1759        }
1760    }
1761
1762    private void loadComponentProperties(org.w3c.dom.Node JavaDoc node,
1763                                         RADComponent metacomp,
1764                                         String JavaDoc propCategory)
1765    {
1766
1767                
1768    FormProperty[] properties;
1769        org.w3c.dom.Node JavaDoc[] propNodes = findSubNodes(node, XML_PROPERTY);
1770        String JavaDoc[] propNames = getPropertyAttributes(propNodes, ATTR_PROPERTY_NAME);
1771    
1772        if(metacomp.isValid()) {
1773            properties = findProperties(propNames, metacomp, propCategory);
1774        } else {
1775            String JavaDoc[] propTypes = getPropertyAttributes(propNodes, ATTR_PROPERTY_TYPE);
1776            properties = getFakeProperties(propNames, propTypes, propNodes, metacomp, propCategory);
1777        }
1778
1779        for (int i=0; i < propNodes.length; i++) {
1780            if (propNames[i] == null)
1781                continue;
1782
1783            org.w3c.dom.Node JavaDoc propNode = propNodes[i];
1784            FormProperty property = properties[i];
1785
1786        loadProperty(propNode, metacomp, property);
1787        }
1788    }
1789    
1790    
1791    
1792    private void loadProperty(org.w3c.dom.Node JavaDoc propNode, RADComponent metacomp, FormProperty property) {
1793    
1794    Throwable JavaDoc t = null;
1795    org.w3c.dom.Node JavaDoc valueNode = null;
1796    
1797    if (property == null) {
1798        PersistenceException ex = new PersistenceException(
1799                         "Unknown property"); // NOI18N
1800
String JavaDoc msg = createLoadingErrorMessage(
1801        FormUtils.getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
1802
propNode);
1803        ErrorManager.getDefault().annotate(
1804        ex, ErrorManager.ERROR, null, msg, null, null);
1805        nonfatalErrors.add(ex);
1806        return;
1807    }
1808
1809    // read pre-init and post-init code of the property
1810
String JavaDoc preCode = getAttribute(propNode, ATTR_PROPERTY_PRE_CODE);
1811    if (preCode != null)
1812        property.setPreCode(preCode);
1813    String JavaDoc postCode = getAttribute(propNode, ATTR_PROPERTY_POST_CODE);
1814    if (postCode != null)
1815        property.setPostCode(postCode);
1816    
1817    String JavaDoc typeStr = getAttribute(propNode, ATTR_PROPERTY_TYPE);
1818    String JavaDoc editorStr = getAttribute(propNode, ATTR_PROPERTY_EDITOR);
1819    String JavaDoc valueStr = getAttribute(propNode, ATTR_PROPERTY_VALUE);
1820
1821    // get the type of stored property value
1822
Class JavaDoc propertyType = getPropertyType(typeStr, property, propNode);
1823    if(propertyType==null) {
1824        return;
1825    }
1826
1827    // load the property editor class and create an instance of it
1828
PropertyEditor prEd = null;
1829    if (editorStr != null) {
1830        prEd = getPropertyEditor(editorStr, property, propertyType, propNode);
1831        if(prEd==null) {
1832        return;
1833        }
1834    }
1835
1836    // load the property value
1837
Object JavaDoc value = NO_VALUE;
1838    if (valueStr != null) { // it is a primitive value
1839
try {
1840        value = decodePrimitiveValue(valueStr, propertyType);
1841        if (prEd != null) {
1842            prEd.setValue(value);
1843            value = prEd.getValue();
1844        }
1845        }
1846        catch (IllegalArgumentException JavaDoc ex) {
1847        String JavaDoc msg = createLoadingErrorMessage(
1848            FormUtils.getFormattedBundleString(
1849            "FMT_ERR_CannotDecodePrimitive", // NOI18N
1850
new Object JavaDoc[] { valueStr, propertyType.getName() }),
1851            propNode);
1852        ErrorManager.getDefault().annotate(ex, msg);
1853        nonfatalErrors.add(ex);
1854        return;
1855        }
1856    }
1857    else { // the value is serialized or saved by XMLPropertyEditor
1858
org.w3c.dom.NodeList JavaDoc children = propNode.getChildNodes();
1859        int n = children != null ? children.getLength() : 0;
1860        if (n > 0) {
1861        try {
1862            boolean serialized = false;
1863            // first try if the value is serialized
1864
for (int j=0; j < n; j++) {
1865            if (XML_SERIALIZED_PROPERTY_VALUE.equals(
1866                    children.item(j).getNodeName()))
1867            { // here is the value serialized in XML
1868
String JavaDoc serValue = getAttribute(children.item(j),
1869                            ATTR_PROPERTY_VALUE);
1870                if (serValue != null) {
1871                serialized = true;
1872                value = decodeValue(serValue);
1873                }
1874                break;
1875            }
1876            }
1877
1878            if (!serialized) {
1879            // the value is saved by XMLPropertyEditor
1880
for (int j=0; j < n; j++) {
1881                
1882                org.w3c.dom.Node JavaDoc node = children.item(j);
1883                
1884                if (node.getNodeType()
1885                == org.w3c.dom.Node.ELEMENT_NODE)
1886                { // here is the element of stored value
1887

1888                if(prEd instanceof BeanPropertyEditor &&
1889                   XML_PROPERTY_BEAN.equals(node.getNodeName()))
1890                {
1891                    loadBeanFromXML(node, (BeanPropertyEditor) prEd);
1892                    loadBeanProperty((BeanPropertyEditor) prEd, node);
1893                } else if (prEd instanceof XMLPropertyEditor) {
1894                    ((XMLPropertyEditor)prEd).readFromXML(node);
1895                }
1896                
1897                value = prEd.getValue();
1898                break;
1899                }
1900            }
1901            }
1902        }
1903        catch (Exception JavaDoc ex) {
1904            t = ex;
1905        }
1906        catch (LinkageError JavaDoc ex) {
1907            t = ex;
1908        }
1909        if (t != null) {
1910            String JavaDoc msg = createLoadingErrorMessage(
1911            FormUtils.getBundleString(
1912                "MSG_ERR_CannotReadPropertyValue"), // NOI18N
1913
propNode);
1914            ErrorManager.getDefault().annotate(t, msg);
1915            nonfatalErrors.add(t);
1916            return;
1917        }
1918        }
1919
1920        if (value == NO_VALUE) { // the value is missing
1921
if (preCode != null || postCode != null)
1922            return; // not an error
1923
PersistenceException ex = new PersistenceException(
1924                       "Missing property value"); // NOI18N
1925
String JavaDoc msg = createLoadingErrorMessage(
1926            FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
1927
propNode);
1928        ErrorManager.getDefault().annotate(
1929            ex, ErrorManager.ERROR, null, msg, null, null);
1930        nonfatalErrors.add(ex);
1931        return;
1932        }
1933    }
1934    
1935    // hack for properties that can't be set until all children
1936
// are added to the container
1937
if (metacomp != null) {
1938            List propList = null;
1939            if (FormUtils.isMarkedParentDependentProperty(property)) {
1940        if (parentDependentProperties != null) {
1941            propList = parentDependentProperties.get(metacomp);
1942        }
1943        else {
1944            parentDependentProperties = new HashMap();
1945            propList = null;
1946        }
1947        if (propList == null) {
1948            propList = new LinkedList();
1949            parentDependentProperties.put(metacomp, propList);
1950        }
1951        propList.add(property);
1952        propList.add(value);
1953            }
1954            if (FormUtils.isMarkedChildrenDependentProperty(property)) {
1955        if (childrenDependentProperties != null) {
1956            propList = childrenDependentProperties.get(metacomp);
1957        }
1958        else {
1959            childrenDependentProperties = new HashMap();
1960            propList = null;
1961        }
1962        if (propList == null) {
1963            propList = new LinkedList();
1964            childrenDependentProperties.put(metacomp, propList);
1965        }
1966        propList.add(property);
1967        propList.add(value);
1968            }
1969            if (propList != null)
1970                return;
1971    }
1972
1973    // set the value to the property
1974
try {
1975            if(value instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
1976                boolean accepted = setConnectedProperty(property,
1977                                                       (RADConnectionPropertyEditor.RADConnectionDesignValue) value,
1978                                                       metacomp.getName(),
1979                                                       propNode);
1980                if(!accepted) {
1981                    // makes sense only for PROPERTY, and METHOD type.
1982
// in case it wasn't set for further handling
1983
// we must set it now.
1984
property.setValue(value);
1985                }
1986            } else {
1987                if(prEd instanceof BeanPropertyEditor) {
1988                    // value is no RADConnection, but it still could have
1989
// properties which are RADConnection-s
1990
Property[] properties = ((BeanPropertyEditor)prEd).getProperties();
1991                    for (int i = 0; i < properties.length; i++) {
1992                        Object JavaDoc propValue = properties[i].getValue();
1993                        if(propValue instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
1994                            setConnectedProperty(properties[i],
1995                                                 (RADConnectionPropertyEditor.RADConnectionDesignValue)propValue,
1996                                                 value.toString(), // XXX getBeanName() ?
1997
propNode);
1998                            // value was already set, so don't care
1999
// if it also was or wasn't set for further handling.
2000
}
2001                    }
2002                }
2003                property.setValue(value);
2004            }
2005            if (prEd != null) {
2006                property.setCurrentEditor(prEd);
2007            }
2008        } catch (Exception JavaDoc ex) {
2009        createLoadingErrorMessage(ex, propNode);
2010        return;
2011    }
2012    }
2013    
2014    private boolean setConnectedProperty(Property property,
2015                                         RADConnectionPropertyEditor.RADConnectionDesignValue value,
2016                                         String JavaDoc beanName,
2017                                         org.w3c.dom.Node JavaDoc propNode) {
2018        if(connectedProperties==null) {
2019            connectedProperties = new ConnectedProperties();
2020        }
2021        int type = value.getType();
2022        if(type == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_PROPERTY ||
2023           type == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_METHOD)
2024        {
2025            // makes sense only for PROPERTY, and METHOD type ...
2026
connectedProperties.put(property, value, beanName, propNode);
2027            return true;
2028        }
2029        return false;
2030    }
2031    
2032    private void createLoadingErrorMessage(Exception JavaDoc ex, org.w3c.dom.Node JavaDoc propNode) {
2033       String JavaDoc msg = createLoadingErrorMessage(
2034        FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
2035
propNode);
2036        ErrorManager.getDefault().annotate(ex, msg);
2037        nonfatalErrors.add(ex);
2038    }
2039    
2040    private PropertyEditor getPropertyEditor(String JavaDoc editorStr, FormProperty property, Class JavaDoc propertyType, org.w3c.dom.Node JavaDoc propNode) {
2041    // load the property editor class and create an instance of it
2042
PropertyEditor prEd = null;
2043    Throwable JavaDoc t = null;
2044    if (editorStr != null) {
2045        Class JavaDoc editorClass = null;
2046        try {
2047        editorClass = PersistenceObjectRegistry.loadClass(editorStr, formFile);
2048        }
2049        catch (Exception JavaDoc ex) {
2050        t = ex;
2051        }
2052        catch (LinkageError JavaDoc ex) {
2053        t = ex;
2054        }
2055        if (t != null) {
2056                // fallback: try PropertyEditorManager
2057
prEd = PropertyEditorManager.findEditor(propertyType);
2058                if (prEd != null && prEd.getClass().getName().equals(editorStr))
2059                    return prEd;
2060
2061        String JavaDoc msg = createLoadingErrorMessage(
2062            FormUtils.getFormattedBundleString(
2063            "FMT_ERR_CannotLoadClass3", // NOI18N
2064
new Object JavaDoc[] { editorStr }),
2065            propNode);
2066        ErrorManager.getDefault().annotate(t, ErrorManager.USER, null, msg, null, null);
2067        nonfatalErrors.add(t);
2068        return null;
2069        }
2070
2071        try {
2072        prEd = createPropertyEditor(editorClass,
2073                        propertyType,
2074                        property);
2075        }
2076        catch (Exception JavaDoc ex) {
2077        t = ex;
2078        }
2079        catch (LinkageError JavaDoc ex) {
2080        t = ex;
2081        }
2082        if (t != null) {
2083        String JavaDoc msg = createLoadingErrorMessage(
2084            FormUtils.getFormattedBundleString(
2085            "FMT_ERR_CannotCreateInstance2", // NOI18N
2086
new Object JavaDoc[] { editorStr }),
2087            propNode);
2088        ErrorManager.getDefault().annotate(t, msg);
2089        nonfatalErrors.add(t);
2090        return null;
2091        }
2092    }
2093    return prEd;
2094    }
2095    
2096    private Class JavaDoc getPropertyType(String JavaDoc typeStr, FormProperty property, org.w3c.dom.Node JavaDoc propNode) {
2097    // get the type of stored property value
2098
Class JavaDoc propertyType = null;
2099    Throwable JavaDoc t = null;
2100
2101    if (typeStr != null) {
2102        try {
2103        propertyType = getClassFromString(typeStr);
2104        }
2105        catch (Exception JavaDoc ex) {
2106        t = ex;
2107        }
2108        catch (LinkageError JavaDoc ex) {
2109        t = ex;
2110        }
2111        if (t != null) {
2112        String JavaDoc msg = createLoadingErrorMessage(
2113            FormUtils.getFormattedBundleString(
2114            "FMT_ERR_CannotLoadClass2", // NOI18N
2115
new Object JavaDoc[] { typeStr }),
2116            propNode);
2117        ErrorManager.getDefault().annotate(t, msg);
2118        nonfatalErrors.add(t);
2119        return null;
2120        }
2121        if (!property.getValueType().isAssignableFrom(propertyType)) {
2122        PersistenceException ex = new PersistenceException(
2123                       "Incompatible property type"); // NOI18N
2124
String JavaDoc msg = createLoadingErrorMessage(
2125            FormUtils.getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
2126
propNode);
2127        ErrorManager.getDefault().annotate(
2128            ex, ErrorManager.ERROR, null, msg, null, null);
2129        nonfatalErrors.add(ex);
2130        return null;
2131        }
2132    }
2133    else propertyType = property.getValueType();
2134    return propertyType;
2135    }
2136    
2137    private void loadBeanFromXML(org.w3c.dom.Node JavaDoc node, BeanPropertyEditor beanPropertyEditor)
2138    throws Exception JavaDoc
2139    {
2140    String JavaDoc typeStr = node.getAttributes().getNamedItem(ATTR_PROPERTY_TYPE).getNodeValue();
2141    Class JavaDoc type = null;
2142    try {
2143        type = getClassFromString(typeStr);
2144    } catch (ClassNotFoundException JavaDoc ex) {
2145        String JavaDoc msg = createLoadingErrorMessage(
2146        FormUtils.getFormattedBundleString(
2147            "FMT_ERR_CannotLoadClass2", // NOI18N
2148
new Object JavaDoc[] { typeStr }),
2149            node);
2150        ErrorManager.getDefault().annotate(ex, msg);
2151        nonfatalErrors.add(ex);
2152        return;
2153    }
2154    
2155    beanPropertyEditor.intializeFromType(type);
2156    
2157    }
2158    
2159    private void loadBeanProperty(BeanPropertyEditor beanPropertyEditor, org.w3c.dom.Node JavaDoc valueNode) {
2160    if(beanPropertyEditor.valueIsBeanProperty()) {
2161        org.w3c.dom.NodeList JavaDoc children = valueNode.getChildNodes();
2162        Node.Property[] allBeanProperties = beanPropertyEditor.getProperties();
2163        org.w3c.dom.Node JavaDoc node;
2164        FormProperty prop;
2165
2166        for (int i=0; i<children.getLength(); i++) {
2167        node = children.item(i);
2168        if (node != null && node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
2169            prop = (FormProperty) getPropertyOfName(allBeanProperties, getAttribute(node, ATTR_PROPERTY_NAME));
2170            if(prop != null) {
2171            loadProperty(node, null, prop);
2172            }
2173        }
2174        }
2175    }
2176    }
2177    
2178    private String JavaDoc[] getPropertyAttributes(org.w3c.dom.Node JavaDoc[] propNodes, String JavaDoc attribute){
2179        String JavaDoc[] ret = new String JavaDoc[propNodes.length];
2180        for (int i=0; i < propNodes.length; i++) {
2181            org.w3c.dom.Node JavaDoc propNode = propNodes[i];
2182            String JavaDoc propAttribute = getAttribute(propNode, attribute);
2183            if (propAttribute != null)
2184                ret[i] = propAttribute;
2185            else {
2186                PersistenceException ex = new PersistenceException(
2187                                           "Missing property attribute " + attribute); // NOI18N
2188
String JavaDoc msg = FormUtils.getFormattedBundleString("MSG_ERR_MissingPropertyName", // NOI18N
2189
new Object JavaDoc[] { attribute });
2190                ErrorManager.getDefault().annotate(
2191                    ex, ErrorManager.ERROR, null, msg, null, null);
2192                nonfatalErrors.add(ex);
2193                continue;
2194            }
2195        }
2196        return ret;
2197    }
2198    
2199    private FormProperty[] findProperties(String JavaDoc[] propertyNames,
2200                                          RADComponent metacomp,
2201                                          String JavaDoc propCategory)
2202    { // [this is a bit ugly method, but don't have better way now...]
2203
if (XML_PROPERTIES.equals(propCategory)) // bean properties
2204
return metacomp.getBeanProperties(propertyNames);
2205
2206        if (XML_A11Y_PROPERTIES.equals(propCategory)) {
2207            return findPropertiesByName(propertyNames, metacomp);
2208        }
2209
2210        return new FormProperty[propertyNames.length]; // error
2211
}
2212
2213    private FormProperty[] findPropertiesByName(String JavaDoc[] propertyNames,
2214                                                RADComponent metacomp)
2215    {
2216        FormProperty[] properties = new FormProperty[propertyNames.length];
2217        for (int i=0; i < propertyNames.length; i++)
2218            properties[i] = (FormProperty) metacomp.getPropertyByName(
2219                                                      propertyNames[i],
2220                                                      FormProperty.class,
2221                                                      true);
2222
2223        return properties;
2224    }
2225    
2226    private FormProperty[] getFakeProperties(String JavaDoc[] propertyNames,
2227                                             String JavaDoc[] propertyTypes,
2228                                             org.w3c.dom.Node JavaDoc[] propNodes,
2229                                             RADComponent metacomp,
2230                                             String JavaDoc propCategory)
2231    {
2232        if (XML_PROPERTIES.equals(propCategory)) {
2233            Class JavaDoc[] propertyClasses = new Class JavaDoc[propertyTypes.length];
2234            for (int i=0; i < propertyNames.length; i++) {
2235                propertyClasses[i] = getClassByName(propertyTypes[i], propNodes[i]);
2236            }
2237            return metacomp.getFakeBeanProperties(propertyNames, propertyClasses);
2238        
2239        }
2240        if (XML_A11Y_PROPERTIES.equals(propCategory)) {
2241            findPropertiesByName(propertyNames, metacomp);
2242        }
2243
2244        return new FormProperty[propertyNames.length]; // error
2245
}
2246
2247    private Class JavaDoc getClassByName(String JavaDoc className, org.w3c.dom.Node JavaDoc node) {
2248        Class JavaDoc clazz = null;
2249        Throwable JavaDoc t = null;
2250        try {
2251            clazz = PersistenceObjectRegistry.loadClass(className, formFile);
2252        }
2253        catch (Exception JavaDoc ex) {
2254            t = ex;
2255        }
2256        catch (LinkageError JavaDoc ex) {
2257            t = ex;
2258        }
2259        if (t != null) { // loading the component class failed
2260
String JavaDoc msg = createLoadingErrorMessage(
2261                FormUtils.getFormattedBundleString("FMT_ERR_CannotLoadClass", // NOI18N
2262
new Object JavaDoc[] { className }),
2263                                                   node);
2264            ErrorManager.getDefault().annotate(t, msg);
2265            nonfatalErrors.add(t);
2266        }
2267        return clazz;
2268    }
2269        
2270    private Node.Property getPropertyOfName(Node.Property[] props, String JavaDoc name) {
2271        for (int i=0; i < props.length; i++)
2272            if (props[i].getName().equals(name))
2273                return props[i];
2274
2275        return null;
2276    }
2277       
2278    private void loadSyntheticProperties(org.w3c.dom.Node JavaDoc node,
2279                                         RADComponent metacomp)
2280    {
2281        org.w3c.dom.Node JavaDoc[] propNodes = findSubNodes(node, XML_SYNTHETIC_PROPERTY);
2282        for (int i=0; i < propNodes.length; i++) {
2283            org.w3c.dom.Node JavaDoc propNode = propNodes[i];
2284            // get the attributes of property node element
2285
org.w3c.dom.NamedNodeMap JavaDoc attrs = propNode.getAttributes();
2286            if (attrs == null)
2287                continue; // no attributes, ignore property
2288

2289            // get the property name from attributes
2290
org.w3c.dom.Node JavaDoc nameNode = attrs.getNamedItem(ATTR_PROPERTY_NAME);
2291            if (nameNode == null) {
2292                PersistenceException ex = new PersistenceException(
2293                                 "Missing synthetic property name"); // NOI18N
2294
String JavaDoc msg = createLoadingErrorMessage(
2295                    FormUtils.getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
2296
propNode);
2297                ErrorManager.getDefault().annotate(
2298                    ex, ErrorManager.ERROR, null, msg, null, null);
2299                nonfatalErrors.add(ex);
2300                continue;
2301            }
2302
2303            // find the property in the metacomponent
2304
String JavaDoc propName = nameNode.getNodeValue();
2305            Node.Property [] props = metacomp.getSyntheticProperties();
2306            Node.Property property = null;
2307            Class JavaDoc expectedPropertyType = null;
2308            for (int j=0; j < props.length; j++) {
2309                if (props[j].getName().equals(propName)) {
2310                    property = props[j];
2311                    break;
2312                }
2313            }
2314
2315            if (property == null) {
2316                if ("menuBar".equals(propName) // NOI18N
2317
&& metacomp instanceof RADVisualFormContainer)
2318                { // compatibility hack for loading form's menu bar, part 1
2319
// (menubar is no longer a synthetic property, but it was
2320
// in NB 3.2)
2321
expectedPropertyType = String JavaDoc.class;
2322                }
2323                else if ("encoding".equals(propName)) // NOI18N
2324
continue; // there used to be "encoding" property in NB 3.1
2325
else { // unknown synthetic property
2326
PersistenceException ex = new PersistenceException(
2327                                           "Unknown synthetic property"); // NOI18N
2328
String JavaDoc msg = createLoadingErrorMessage(
2329                        FormUtils.getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
2330
propNode);
2331                    ErrorManager.getDefault().annotate(
2332                        ex, ErrorManager.ERROR, null, msg, null, null);
2333                    nonfatalErrors.add(ex);
2334                    continue;
2335                }
2336            }
2337            else expectedPropertyType = property.getValueType();
2338
2339            org.w3c.dom.Node JavaDoc typeNode = attrs.getNamedItem(ATTR_PROPERTY_TYPE);
2340            org.w3c.dom.Node JavaDoc valueNode = attrs.getNamedItem(ATTR_PROPERTY_VALUE);
2341
2342            // get the type of stored property value
2343
Class JavaDoc propertyType = null;
2344            Throwable JavaDoc t = null;
2345
2346            if (typeNode != null) {
2347                try {
2348                    propertyType = getClassFromString(typeNode.getNodeValue());
2349                }
2350                catch (Exception JavaDoc ex) {
2351                    t = ex;
2352                }
2353                catch (LinkageError JavaDoc ex) {
2354                    t = ex;
2355                }
2356                if (t != null) {
2357                    String JavaDoc msg = createLoadingErrorMessage(
2358                        FormUtils.getFormattedBundleString(
2359                            "FMT_ERR_CannotLoadClass2", // NOI18N
2360
new Object JavaDoc[] { typeNode.getNodeValue() }),
2361                        propNode);
2362                    ErrorManager.getDefault().annotate(t, msg);
2363                    nonfatalErrors.add(t);
2364                    continue;
2365                }
2366                if (!expectedPropertyType.isAssignableFrom(propertyType)) {
2367                    PersistenceException ex = new PersistenceException(
2368                                           "Incompatible property type"); // NOI18N
2369
String JavaDoc msg = createLoadingErrorMessage(
2370                        FormUtils.getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
2371
propNode);
2372                    ErrorManager.getDefault().annotate(
2373                        ex, ErrorManager.ERROR, null, msg, null, null);
2374                    nonfatalErrors.add(ex);
2375                    continue;
2376                }
2377            }
2378            else propertyType = property.getValueType();
2379
2380            // load the property value
2381
if (valueNode == null) { // the value is missing
2382
PersistenceException ex = new PersistenceException(
2383                                 "Missing synthetic property value"); // NOI18N
2384
String JavaDoc msg = createLoadingErrorMessage(
2385                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
2386
propNode);
2387                ErrorManager.getDefault().annotate(
2388                    ex, ErrorManager.ERROR, null, msg, null, null);
2389                nonfatalErrors.add(ex);
2390                continue;
2391            }
2392
2393            Object JavaDoc value = null;
2394            try {
2395                try {
2396                    value = decodePrimitiveValue(valueNode.getNodeValue(),
2397                                                 propertyType);
2398                }
2399                catch (IllegalArgumentException JavaDoc ex) {
2400                    // not a primitive value
2401
value = decodeValue(valueNode.getNodeValue());
2402                }
2403            }
2404            catch (Exception JavaDoc ex) {
2405                t = ex;
2406            }
2407            catch (LinkageError JavaDoc ex) {
2408                t = ex;
2409            }
2410            if (t != null) {
2411                String JavaDoc msg = createLoadingErrorMessage(
2412                    FormUtils.getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
2413
propNode);
2414                ErrorManager.getDefault().annotate(t, msg);
2415                nonfatalErrors.add(t);
2416                continue;
2417            }
2418
2419            // compatibility hack for loading form's menu bar, part 2
2420
if ("menuBar".equals(propName) // NOI18N
2421
&& value instanceof String JavaDoc
2422                && metacomp instanceof RADVisualFormContainer)
2423            {
2424                for (RADComponent mc : metacomp.getFormModel().getOtherComponents()) {
2425                    if (mc instanceof RADMenuComponent && value.equals(mc.getName())) {
2426                        RADMenuComponent menuComp = (RADMenuComponent) mc;
2427                        RADVisualFormContainer formCont =
2428                            (RADVisualFormContainer) metacomp;
2429                        menuComp.getFormModel().removeComponentImpl(menuComp, false);
2430                        formCont.add(menuComp);
2431                        menuComp.setParentComponent(formCont);
2432                        break;
2433                    }
2434                }
2435                continue;
2436            }
2437
2438            // set the value to the property
2439
try {
2440                property.setValue(value);
2441            }
2442            catch (Exception JavaDoc ex) {
2443                String JavaDoc msg = createLoadingErrorMessage(
2444                    FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
2445
propNode);
2446                ErrorManager.getDefault().annotate(ex, msg);
2447                nonfatalErrors.add(ex);
2448                continue;
2449            }
2450        }
2451    }
2452
2453    private void loadEvents(org.w3c.dom.Node JavaDoc node, RADComponent metacomp) {
2454        org.w3c.dom.Node JavaDoc[] eventNodes = findSubNodes(node, XML_EVENT);
2455        String JavaDoc[] eventNames = new String JavaDoc[eventNodes.length];
2456
2457        for (int i=0; i < eventNodes.length; i++) {
2458            org.w3c.dom.Node JavaDoc eventNode = eventNodes[i];
2459            String JavaDoc eventName = getAttribute(eventNode, ATTR_EVENT_NAME);
2460            String JavaDoc eventListener = getAttribute(eventNode, ATTR_EVENT_LISTENER);
2461            String JavaDoc paramTypes = getAttribute(eventNode, ATTR_EVENT_PARAMS);
2462            String JavaDoc eventHandlers = getAttribute(eventNode, ATTR_EVENT_HANDLER);
2463
2464            if (eventName == null || eventHandlers == null)
2465                continue; // [missing data error - should be reported!!]
2466

2467            eventNames[i] = getEventIdName(eventListener, eventName, paramTypes);
2468        }
2469
2470        FormEvents formEvents = formModel.getFormEvents();
2471
2472        Event[] events = metacomp.getEvents(eventNames);
2473        for (int i=0; i < eventNodes.length; i++) {
2474            if (eventNames[i] == null)
2475                continue;
2476
2477            Event event = events[i];
2478            if (event == null)
2479                continue; // [uknown event error - should be reported!]
2480

2481            String JavaDoc eventHandlers = getAttribute(eventNodes[i], ATTR_EVENT_HANDLER);
2482            StringTokenizer tok = new StringTokenizer(eventHandlers, ","); // NOI18N
2483
while (tok.hasMoreTokens()) {
2484                try {
2485                    formEvents.attachEvent(event, tok.nextToken(), null);
2486                }
2487                catch (IllegalArgumentException JavaDoc ex) {
2488                    // [incompatible handler error - should be reported!]
2489
}
2490            }
2491        }
2492    }
2493
2494    private static String JavaDoc getEventIdName(String JavaDoc eventListener,
2495                                         String JavaDoc eventName,
2496                                         String JavaDoc paramTypes)
2497    {
2498        if (eventListener == null || paramTypes == null)
2499            return eventName;
2500
2501        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
2502        buf.append("$"); // NOI18N
2503
buf.append(eventListener);
2504        buf.append("."); // NOI18N
2505
buf.append(eventName);
2506        buf.append("("); // NOI18N
2507

2508        StringTokenizer tok = new StringTokenizer(paramTypes, ","); // NOI18N
2509
while (tok.hasMoreTokens()) {
2510            buf.append(tok.nextToken());
2511            if (tok.hasMoreTokens())
2512                buf.append(", "); // NOI18N
2513
}
2514
2515        buf.append(")"); // NOI18N
2516
return buf.toString();
2517    }
2518
2519    private void loadAuxValues(org.w3c.dom.Node JavaDoc node, RADComponent comp) {
2520        org.w3c.dom.Node JavaDoc[] auxNodes = findSubNodes(node, XML_AUX_VALUE);
2521        for (int i=0; i < auxNodes.length; i++) {
2522            org.w3c.dom.Node JavaDoc auxNode = auxNodes[i];
2523            // get the attributes of property node element
2524
org.w3c.dom.NamedNodeMap JavaDoc attrs = auxNode.getAttributes();
2525            if (attrs == null)
2526                continue; // no attributes, ignore
2527

2528            // get the property name from attributes
2529
org.w3c.dom.Node JavaDoc nameNode = attrs.getNamedItem(ATTR_AUX_NAME);
2530            if (nameNode == null) {
2531                PersistenceException ex = new PersistenceException(
2532                                           "Missing aux value name"); // NOI18N
2533
String JavaDoc msg = createLoadingErrorMessage(
2534                    FormUtils.getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
2535
auxNode);
2536                ErrorManager.getDefault().annotate(
2537                    ex, ErrorManager.ERROR, null, msg, null, null);
2538                nonfatalErrors.add(ex);
2539                continue;
2540            }
2541            String JavaDoc name = nameNode.getNodeValue();
2542
2543            org.w3c.dom.Node JavaDoc typeNode = attrs.getNamedItem(ATTR_AUX_VALUE_TYPE);
2544            org.w3c.dom.Node JavaDoc valueNode = attrs.getNamedItem(ATTR_AUX_VALUE);
2545
2546            // get the type of stored aux value
2547
if (typeNode == null) {
2548                PersistenceException ex = new PersistenceException(
2549                                           "Missing aux value type"); // NOI18N
2550
String JavaDoc msg = createLoadingErrorMessage(
2551                    FormUtils.getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
2552
auxNode);
2553                ErrorManager.getDefault().annotate(
2554                    ex, ErrorManager.ERROR, null, msg, null, null);
2555                nonfatalErrors.add(ex);
2556                continue;
2557            }
2558
2559            Class JavaDoc auxValueType = null;
2560            Throwable JavaDoc t = null;
2561            try {
2562                auxValueType = getClassFromString(typeNode.getNodeValue());
2563            }
2564            catch (Exception JavaDoc ex) {
2565                t = ex;
2566            }
2567            catch (LinkageError JavaDoc ex) {
2568                t = ex;
2569            }
2570            if (t != null) {
2571                String JavaDoc msg = createLoadingErrorMessage(
2572                    FormUtils.getFormattedBundleString(
2573                        "FMT_ERR_CannotLoadClass2", // NOI18N
2574
new Object JavaDoc[] { typeNode.getNodeValue() }),
2575                    auxNode);
2576                ErrorManager.getDefault().annotate(t, msg);
2577                nonfatalErrors.add(t);
2578                continue;
2579            }
2580
2581            // load the aux value
2582
if (valueNode == null) { // the value is missing
2583
PersistenceException ex = new PersistenceException(
2584                                                "Missing aux value"); // NOI18N
2585
String JavaDoc msg = createLoadingErrorMessage(
2586                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
2587
auxNode);
2588                ErrorManager.getDefault().annotate(
2589                    ex, ErrorManager.ERROR, null, msg, null, null);
2590                nonfatalErrors.add(ex);
2591                continue;
2592            }
2593
2594            Object JavaDoc value = null;
2595            try {
2596                try {
2597                    value = decodePrimitiveValue(valueNode.getNodeValue(),
2598                                                 auxValueType);
2599                }
2600                catch (IllegalArgumentException JavaDoc ex) {
2601                    // not a primitive value
2602
value = decodeValue(valueNode.getNodeValue());
2603                }
2604            }
2605            catch (Exception JavaDoc ex) {
2606                t = ex;
2607            }
2608            catch (LinkageError JavaDoc ex) {
2609                t = ex;
2610            }
2611            if (t != null) {
2612                String JavaDoc msg = createLoadingErrorMessage(
2613                    FormUtils.getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
2614
auxNode);
2615                ErrorManager.getDefault().annotate(t, msg);
2616                nonfatalErrors.add(t);
2617                continue;
2618            }
2619
2620            // Form settings are stored in AuxValues of top-level container
2621
if ((comp == formModel.getTopRADComponent() && (name.startsWith(FORM_SETTINGS_PREFIX)))) {
2622                String JavaDoc settingName = name.substring(FORM_SETTINGS_PREFIX.length());
2623                formModel.getSettings().set(settingName, value);
2624            } else {
2625                // we have a valid name / value pair
2626
comp.setAuxValue(name, value);
2627            }
2628        }
2629
2630        // we must care about some aux values specially ...
2631

2632        // VALUE_SERIALIZE indicates serialized component
2633
if (JavaCodeGenerator.VALUE_SERIALIZE.equals(
2634                comp.getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION)))
2635        { // the component has a serialized instance => deserialize it
2636
try {
2637                String JavaDoc serFile = (String JavaDoc) comp.getAuxValue(
2638                                          JavaCodeGenerator.AUX_SERIALIZE_TO);
2639                if (serFile == null)
2640                    serFile = formFile.getName() + "_" + comp.getName(); // NOI18N
2641

2642                ClassPath sourcePath = ClassPath.getClassPath(formFile, ClassPath.SOURCE);
2643                String JavaDoc serName = sourcePath.getResourceName(formFile.getParent());
2644                if (!"".equals(serName)) // NOI18N
2645
serName += "."; // NOI18N
2646
serName += serFile;
2647
2648                Object JavaDoc instance = null;
2649                try {
2650                    instance = Beans.instantiate(sourcePath.getClassLoader(true), serName);
2651                } catch (ClassNotFoundException JavaDoc cnfe) {
2652                    ClassPath executionPath = ClassPath.getClassPath(formFile, ClassPath.EXECUTE);
2653                    instance = Beans.instantiate(executionPath.getClassLoader(true), serName);
2654                }
2655
2656                comp.setInstance(instance);
2657            }
2658            catch (Exception JavaDoc ex) { // ignore
2659
org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
2660            }
2661        }
2662
2663        // AUX_VARIABLE_MODIFIER and AUX_VARIABLE_LOCAL require changing
2664
// type of component's variable
2665
Object JavaDoc val = comp.getAuxValue(JavaCodeGenerator.AUX_VARIABLE_MODIFIER);
2666        int newType = val instanceof Integer JavaDoc ?
2667                        ((Integer JavaDoc)val).intValue() : -1;
2668
2669        val = comp.getAuxValue(JavaCodeGenerator.AUX_VARIABLE_LOCAL);
2670        if (val instanceof Boolean JavaDoc) {
2671            if (newType == -1)
2672                newType = 0;
2673            newType |= Boolean.TRUE.equals(val) ?
2674                       CodeVariable.LOCAL | CodeVariable.EXPLICIT_DECLARATION :
2675                       CodeVariable.FIELD;
2676        }
2677
2678        if (newType > -1) { // set variable type
2679
CodeExpression exp = comp.getCodeExpression();
2680            int varType = exp.getVariable().getType();
2681
2682            varType &= ~CodeVariable.ALL_MODIF_MASK;
2683            varType |= newType & CodeVariable.ALL_MODIF_MASK;
2684
2685            if ((newType & CodeVariable.SCOPE_MASK) != 0) {
2686                varType &= ~CodeVariable.SCOPE_MASK;
2687                varType |= newType & CodeVariable.SCOPE_MASK;
2688            }
2689
2690            if ((newType & CodeVariable.DECLARATION_MASK) != 0) {
2691                varType &= ~CodeVariable.DECLARATION_MASK;
2692                varType |= newType & CodeVariable.DECLARATION_MASK;
2693            }
2694
2695            CodeStructure codeStructure = formModel.getCodeStructure();
2696            String JavaDoc varName = comp.getName(); // get the original name
2697
codeStructure.removeExpressionFromVariable(exp);
2698            codeStructure.createVariableForExpression(exp, varType, varName);
2699        }
2700        
2701        // Default variable modifiers for form
2702
if (comp == formModel.getTopRADComponent()) {
2703            FormSettings settings = formModel.getSettings();
2704            boolean local = settings.getVariablesLocal();
2705            int modifiers = settings.getVariablesModifier();
2706            int type = local ? (CodeVariable.LOCAL | (modifiers & CodeVariable.FINAL)
2707                | CodeVariable.EXPLICIT_DECLARATION) : modifiers | CodeVariable.FIELD;
2708            formModel.getCodeStructure().setDefaultVariableType(type);
2709        }
2710    }
2711
2712    // -----------
2713

2714    /** This method saves the form to given data object.
2715     * @param formObject FormDataObject representing the form files
2716     * @param formModel FormModel to be saved
2717     * @param nonfatalErrors List to be filled with errors occurred during
2718     * saving which are not fatal (but should be reported)
2719     * @exception PersistenceException if some fatal problem occurred which
2720     * prevents saving the form
2721     */

2722    public void saveForm(FormDataObject formObject,
2723                         FormModel formModel,
2724                         List nonfatalErrors)
2725        throws PersistenceException
2726    {
2727        FileObject formFile = formObject.getFormEntry().getFile();
2728        if (!formFile.canWrite()) { // should not happen
2729
PersistenceException ex = new PersistenceException(
2730                                 "Tried to save read-only form"); // NOI18N
2731
String JavaDoc msg = FormUtils.getFormattedBundleString(
2732                             "FMT_ERR_SaveToReadOnly", // NOI18N
2733
new Object JavaDoc[] { formFile.getNameExt() });
2734            ErrorManager.getDefault().annotate(
2735                ex, ErrorManager.ERROR, null, msg, null, null);
2736            throw ex;
2737        }
2738
2739        StringBuffer JavaDoc buf1 = new StringBuffer JavaDoc();
2740        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
2741
2742        // initial cleanup
2743
lastExpId = 0; // CodeExpression ID counter
2744
if (expressions != null)
2745            expressions.clear();
2746        if (savedVariables != null)
2747            savedVariables.clear();
2748
2749        this.formFile = formFile;
2750        this.formModel = formModel;
2751        this.nonfatalErrors = nonfatalErrors;
2752
2753        // start with the lowest version; if there is nothing in the
2754
// form that requires higher format version, then the form file
2755
// is compatible with NB 3.2
2756
formatVersion = NB32_VERSION;
2757
2758        RADComponent topComp = formModel.getTopRADComponent();
2759        RADVisualFormContainer formCont =
2760            topComp instanceof RADVisualFormContainer ?
2761                (RADVisualFormContainer) topComp : null;
2762
2763        // store XML file header
2764
final String JavaDoc encoding = "UTF-8"; // NOI18N
2765
buf1.append("<?xml version=\"1.0\" encoding=\""); // NOI18N
2766
buf1.append(encoding);
2767        buf1.append("\" ?>\n\n"); // NOI18N
2768

2769        // store "Other Components"
2770
Collection<RADComponent> otherComps = formModel.getOtherComponents();
2771
2772        // compatibility hack for saving form's menu bar (part I)
2773
RADComponent formMenuComp = formCont != null ? formCont.getContainerMenu() : null;
2774
2775        if (otherComps.size() > 0 || formMenuComp != null) {
2776            buf2.append(ONE_INDENT);
2777            addElementOpen(buf2, XML_NON_VISUAL_COMPONENTS);
2778            for (RADComponent metacomp : otherComps) {
2779                saveAnyComponent(metacomp,
2780                                 buf2, ONE_INDENT + ONE_INDENT,
2781                                 true);
2782            }
2783            if (formMenuComp != null) {
2784                saveAnyComponent(formMenuComp,
2785                                 buf2, ONE_INDENT + ONE_INDENT,
2786                                 true);
2787            }
2788            buf2.append(ONE_INDENT);
2789            addElementClose(buf2, XML_NON_VISUAL_COMPONENTS);
2790        }
2791
2792        // store form main hierarchy
2793
if (topComp != null) {
2794            saveAnyComponent(topComp, buf2, ONE_INDENT, false);
2795
2796            if (!(topComp instanceof RADVisualContainer))
2797                raiseFormatVersion(NB33_VERSION);
2798        }
2799        addElementClose(buf2, XML_FORM);
2800
2801        // determine FormInfo type (for backward compatibility)
2802
String JavaDoc compatFormInfo = getFormInfoForKnownClass(
2803                                    formModel.getFormBaseClass());
2804        // [if some non-standard FormInfo was used, it is lost]
2805

2806        // add form specification element at the beginning of the form file
2807
// (this is done in the end because the required form version is
2808
// not determined until all data is saved)
2809
if (compatFormInfo == null) {
2810            raiseFormatVersion(NB33_VERSION);
2811
2812            addElementOpenAttr(buf1, XML_FORM,
2813                new String JavaDoc[] { ATTR_FORM_VERSION },
2814                new String JavaDoc[] { formatVersion });
2815        }
2816        else {
2817            addElementOpenAttr(buf1, XML_FORM,
2818                new String JavaDoc[] { ATTR_FORM_VERSION, ATTR_FORM_TYPE },
2819                new String JavaDoc[] { formatVersion, compatFormInfo });
2820        }
2821
2822        // final cleanup
2823
if (expressions != null)
2824            expressions.clear();
2825        if (savedVariables != null)
2826            savedVariables.clear();
2827
2828        // write the data
2829
FileLock lock = null;
2830        try {
2831            lock = formFile.lock();
2832        }
2833        catch (IOException ex) {
2834            PersistenceException pe = new PersistenceException(
2835                                        ex, "Cannot obtain lock on form file"); // NOI18N
2836
ErrorManager.getDefault().annotate(
2837                ex,
2838                FormUtils.getFormattedBundleString("FMT_ERR_CannotLockFormFile", // NOI18N
2839
new Object JavaDoc[] { formFile.getNameExt() }));
2840            throw pe;
2841        }
2842
2843        java.io.OutputStream JavaDoc os = null;
2844        try {
2845            os = formFile.getOutputStream(lock);
2846            os.write(buf1.toString().getBytes(encoding));
2847            os.write(buf2.toString().getBytes(encoding));
2848        }
2849        catch (Exception JavaDoc ex) {
2850            PersistenceException pe = new PersistenceException(
2851                                          ex, "Cannot write to form file"); // NOI18N
2852
ErrorManager.getDefault().annotate(
2853                ex,
2854                FormUtils.getFormattedBundleString("FMT_ERR_CannotWrtiteToFile", // NOI18N
2855
new Object JavaDoc[] { formFile.getNameExt() }));
2856            throw pe;
2857        }
2858        finally {
2859            try {
2860                if (os != null)
2861                    os.close();
2862            }
2863            catch (IOException ex) {} // ignore
2864
lock.releaseLock();
2865            this.formModel = null;
2866        }
2867    }
2868
2869    private void saveAnyComponent(RADComponent comp,
2870                                  StringBuffer JavaDoc buf,
2871                                  String JavaDoc indent,
2872                                  boolean createElement) {
2873        String JavaDoc elementType = null;
2874        String JavaDoc elementIndent = indent;
2875        if (createElement) {
2876            if (comp instanceof RADMenuComponent)
2877                elementType = XML_MENU_CONTAINER;
2878            else if (comp instanceof RADMenuItemComponent)
2879                elementType = XML_MENU_COMPONENT;
2880            else if (comp instanceof ComponentContainer)
2881                elementType = XML_CONTAINER;
2882            else elementType = XML_COMPONENT;
2883
2884            buf.append(elementIndent);
2885            addElementOpenAttr(buf, elementType,
2886                new String JavaDoc[] { ATTR_COMPONENT_CLASS,
2887                               ATTR_COMPONENT_NAME },
2888                new String JavaDoc[] { comp.getBeanClass().getName(),
2889                               comp.getName() });
2890
2891            indent += ONE_INDENT;
2892        }
2893
2894        if (comp instanceof RADMenuItemComponent) {
2895            saveMenuComponent((RADMenuItemComponent) comp, buf, indent);
2896        }
2897        else if (comp instanceof ComponentContainer) {
2898            saveContainer((ComponentContainer) comp, buf, indent);
2899        }
2900        else if (comp instanceof RADVisualComponent) {
2901            saveVisualComponent((RADVisualComponent) comp, buf, indent);
2902        }
2903        else {
2904            saveComponent(comp, buf, indent);
2905        }
2906
2907        if (createElement) {
2908            buf.append(elementIndent);
2909            addElementClose(buf, elementType);
2910        }
2911    }
2912
2913    private void saveContainer(ComponentContainer container,
2914                               StringBuffer JavaDoc buf, String JavaDoc indent)
2915    {
2916        RADVisualContainer visualContainer =
2917            container instanceof RADVisualContainer ?
2918                (RADVisualContainer) container : null;
2919
2920        RADComponent[] children = null;
2921        int convIndex = -1; // index of layout in conversion table
2922

2923        if (visualContainer != null) {
2924            saveVisualComponent(visualContainer, buf, indent);
2925            convIndex = saveLayout(visualContainer, buf, indent);
2926
2927            // compatibility hack for saving form's menu bar (part II)
2928
if (container instanceof RADVisualFormContainer)
2929                children = visualContainer.getSubComponents();
2930        }
2931        else saveComponent((RADComponent)container, buf, indent);
2932
2933        if (children == null)
2934            children = container.getSubBeans();
2935
2936        if (children.length > 0) {
2937            buf.append(indent);
2938            addElementOpen(buf, XML_SUB_COMPONENTS);
2939            for (int i = 0; i < children.length; i++) {
2940                if (children[i] instanceof RADMenuItemComponent)
2941                    raiseFormatVersion(NB33_VERSION);
2942
2943                saveAnyComponent(children[i], buf, indent+ONE_INDENT, true);
2944            }
2945            buf.append(indent);
2946            addElementClose(buf, XML_SUB_COMPONENTS);
2947        }
2948
2949        if (visualContainer != null && convIndex == LAYOUT_FROM_CODE)
2950            saveLayoutCode(visualContainer.getLayoutSupport(), buf, indent);
2951    }
2952
2953    private int saveLayout(RADVisualContainer container,
2954                           StringBuffer JavaDoc buf, String JavaDoc indent)
2955    {
2956        LayoutSupportManager layoutSupport = container.getLayoutSupport();
2957
2958        if (layoutSupport == null) {
2959            raiseFormatVersion(NB42_VERSION);
2960            RADVisualComponent[] subComponents = container.getSubComponents();
2961            Map JavaDoc idToNameMap = new HashMap();
2962            for (int i=0; i<subComponents.length; i++) {
2963                RADVisualComponent comp = subComponents[i];
2964                idToNameMap.put(comp.getId(), comp.getName());
2965            }
2966            buf.append("\n"); // NOI18N
2967
buf.append(indent);
2968            addElementOpen(buf, XML_LAYOUT);
2969            LayoutModel layoutModel = formModel.getLayoutModel();
2970            int indentation = indent.length()/ONE_INDENT.length() + 1;
2971            LayoutComponent layoutComp = layoutModel.getLayoutComponent(container.getId());
2972            buf.append(layoutModel.dumpLayout(indentation, layoutComp, idToNameMap, false));
2973            buf.append(indent);
2974            addElementClose(buf, XML_LAYOUT);
2975            return LAYOUT_NATURAL;
2976        } // end of hack
2977

2978        if (layoutSupport.isUnknownLayout())
2979            return LAYOUT_UNKNOWN;
2980
2981        int convIndex = -1; // index in conversion table
2982

2983        Class JavaDoc layoutClass = layoutSupport.getLayoutDelegate().getSupportedClass();
2984        if (layoutClass == null)
2985            convIndex = LAYOUT_NULL;
2986        else {
2987            String JavaDoc className = layoutClass.getName();
2988            for (int i=0; i < supportedClassNames.length; i++)
2989                if (className.equals(supportedClassNames[i])) {
2990                    convIndex = i;
2991                    break;
2992                }
2993
2994            if (convIndex < 0) // not a standard layout
2995
return LAYOUT_FROM_CODE;
2996        }
2997
2998        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
2999
3000        if (convIndex != LAYOUT_ABSOLUTE && convIndex != LAYOUT_NULL) {
3001            Node.Property[] properties = layoutSupport.getAllProperties();
3002            for (int i=0; i < properties.length; i++) {
3003                FormProperty property = (FormProperty) properties[i];
3004                if (property.isChanged()
3005                    // NB 3.1 considered special values as default for
3006
// GridLayout, so we must always save rows and columns
3007
|| (convIndex == LAYOUT_GRID
3008                        && ("rows".equals(property.getName()) // NOI18N
3009
|| "columns".equals(property.getName())))) // NOI18N
3010
{
3011                    String JavaDoc delegatePropName = property.getName();
3012                    String JavaDoc layout31PropName = null;
3013                    String JavaDoc[] delPropNames = layoutDelegatePropertyNames[convIndex];
3014                    for (int j=0; j < delPropNames.length; j++)
3015                        if (delegatePropName.equals(delPropNames[j])) {
3016                            layout31PropName = layout31PropertyNames[convIndex][j];
3017                            break;
3018                        }
3019
3020                    if (layout31PropName != null) {
3021                        saveProperty(property, layout31PropName,
3022                                     buf2, indent + ONE_INDENT);
3023                    }
3024                }
3025            }
3026        }
3027        else { // AbsoluteLayout and null layout are special...
3028
String JavaDoc nullLayout = convIndex == LAYOUT_NULL ? "true" : "false"; // NOI18N
3029
buf2.append(indent);
3030            buf2.append(ONE_INDENT);
3031            addLeafElementOpenAttr(
3032                buf2,
3033                XML_PROPERTY,
3034                new String JavaDoc[] { ATTR_PROPERTY_NAME,
3035                               ATTR_PROPERTY_TYPE,
3036                               ATTR_PROPERTY_VALUE },
3037                new String JavaDoc[] { "useNullLayout", "boolean", nullLayout } // NOI18N
3038
);
3039        }
3040
3041        buf.append("\n"); // NOI18N
3042
buf.append(indent);
3043        if (buf2.length() > 0) {
3044            addElementOpenAttr(
3045                buf,
3046                XML_LAYOUT,
3047                new String JavaDoc[] { ATTR_LAYOUT_CLASS },
3048                new String JavaDoc[] { PersistenceObjectRegistry.getPrimaryName(
3049                                   layout31Names[convIndex]) }
3050            );
3051            buf.append(buf2);
3052            buf.append(indent);
3053            addElementClose(buf, XML_LAYOUT);
3054        }
3055        else {
3056            addLeafElementOpenAttr(
3057                buf,
3058                XML_LAYOUT,
3059                new String JavaDoc[] { ATTR_LAYOUT_CLASS },
3060                new String JavaDoc[] { PersistenceObjectRegistry.getPrimaryName(
3061                                   layout31Names[convIndex]) }
3062            );
3063        }
3064
3065        return convIndex;
3066    }
3067
3068    private void saveLayoutCode(LayoutSupportManager layoutSupport,
3069                                StringBuffer JavaDoc buf, String JavaDoc indent)
3070    {
3071        raiseFormatVersion(NB33_VERSION);
3072
3073        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
3074        String JavaDoc subIndent = indent + ONE_INDENT;
3075// codeFlow = true;
3076

3077        // layout manager code
3078
CodeGroup code = layoutSupport.getLayoutCode();
3079        if (code != null) {
3080            Iterator it = code.getStatementsIterator();
3081            while (it.hasNext()) {
3082                saveCodeStatement((CodeStatement) it.next(), buf2, subIndent);
3083            }
3084        }
3085
3086        // components code
3087
for (int i=0, n=layoutSupport.getComponentCount(); i < n; i++) {
3088            code = layoutSupport.getComponentCode(i);
3089            if (code != null) {
3090                Iterator it = code.getStatementsIterator();
3091                while (it.hasNext()) {
3092                    saveCodeStatement((CodeStatement) it.next(), buf2, subIndent);
3093                }
3094            }
3095        }
3096
3097        if (buf2.length() > 0) {
3098            buf.append(indent);
3099            addElementOpen(buf, XML_LAYOUT_CODE);
3100
3101            buf.append(buf2.toString());
3102
3103            buf.append(indent);
3104            addElementClose(buf, XML_LAYOUT_CODE);
3105        }
3106    }
3107
3108    private void saveVisualComponent(RADVisualComponent component,
3109                                     StringBuffer JavaDoc buf, String JavaDoc indent)
3110    {
3111        saveComponent(component, buf, indent);
3112
3113        RADVisualContainer container = component.getParentContainer();
3114        if (container == null || container.getLayoutSupport() == null)
3115            return;
3116
3117        int componentIndex = container.getIndexOf(component);
3118        LayoutConstraints constr =
3119            container.getLayoutSupport().getConstraints(componentIndex);
3120        if (constr == null)
3121            return; // no constraints
3122

3123        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc(); // [might be not used at all]
3124
int convIndex = saveConstraints(constr, buf2,
3125                                        indent + ONE_INDENT + ONE_INDENT);
3126        if (convIndex >= 0) { // standard constraints (saved in buf2)
3127
buf.append(indent);
3128            addElementOpen(buf, XML_CONSTRAINTS);
3129            buf.append(indent + ONE_INDENT);
3130            addElementOpenAttr(
3131                buf,
3132                XML_CONSTRAINT,
3133                new String JavaDoc[] { ATTR_CONSTRAINT_LAYOUT, ATTR_CONSTRAINT_VALUE },
3134                new String JavaDoc[] { PersistenceObjectRegistry.getPrimaryName(
3135                                   layout31Names[convIndex]),
3136                               PersistenceObjectRegistry.getPrimaryName(
3137                                   layout31ConstraintsNames[convIndex]) }
3138            );
3139            buf.append(buf2);
3140            buf.append(indent + ONE_INDENT);
3141            addElementClose(buf, XML_CONSTRAINT);
3142            buf.append(indent);
3143            addElementClose(buf, XML_CONSTRAINTS);
3144        }
3145    }
3146
3147    private int saveConstraints(LayoutConstraints constr,
3148                                StringBuffer JavaDoc buf,
3149                                String JavaDoc indent)
3150    {
3151        // constraints of BorderLayout
3152
if (constr instanceof BorderLayoutSupport.BorderConstraints) {
3153            String JavaDoc position = (String JavaDoc) constr.getConstraintsObject();
3154            buf.append(indent);
3155            addLeafElementOpenAttr(
3156                buf,
3157                "BorderConstraints", // NOI18N
3158
new String JavaDoc[] { "direction" }, // NOI18N
3159
new String JavaDoc[] { position });
3160
3161            return LAYOUT_BORDER;
3162        }
3163
3164        // constraints of GridBagLayout
3165
if (constr instanceof GridBagLayoutSupport.GridBagLayoutConstraints) {
3166            java.awt.GridBagConstraints JavaDoc gbConstr =
3167                (java.awt.GridBagConstraints JavaDoc) constr.getConstraintsObject();
3168
3169            buf.append(indent);
3170            addLeafElementOpenAttr(
3171                buf,
3172                "GridBagConstraints", // NOI18N
3173
new String JavaDoc[] { "gridX", "gridY", "gridWidth", "gridHeight", // NOI18N
3174
"fill", "ipadX", "ipadY", // NOI18N
3175
"insetsTop", "insetsLeft", // NOI18N
3176
"insetsBottom", "insetsRight", // NOI18N
3177
"anchor", "weightX", "weightY" }, // NOI18N
3178
new String JavaDoc[] { Integer.toString(gbConstr.gridx),
3179                               Integer.toString(gbConstr.gridy),
3180                               Integer.toString(gbConstr.gridwidth),
3181                               Integer.toString(gbConstr.gridheight),
3182                               Integer.toString(gbConstr.fill),
3183                               Integer.toString(gbConstr.ipadx),
3184                               Integer.toString(gbConstr.ipady),
3185                               Integer.toString(gbConstr.insets.top),
3186                               Integer.toString(gbConstr.insets.left),
3187                               Integer.toString(gbConstr.insets.bottom),
3188                               Integer.toString(gbConstr.insets.right),
3189                               Integer.toString(gbConstr.anchor),
3190                               Double.toString(gbConstr.weightx),
3191                               Double.toString(gbConstr.weighty) });
3192
3193            return LAYOUT_GRIDBAG;
3194        }
3195
3196        // constraints of JTabbedPane
3197
if (constr instanceof JTabbedPaneSupport.TabConstraints) {
3198            JTabbedPaneSupport.TabConstraints tabConstr =
3199                (JTabbedPaneSupport.TabConstraints) constr;
3200
3201            StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
3202            Node.Property[] tabProperties = constr.getProperties();
3203
3204            for (int i=0; i < tabProperties.length; i++) {
3205                FormProperty prop = (FormProperty) tabProperties[i];
3206                if (prop.isChanged())
3207                    saveProperty(
3208                        prop,
3209                        prop.getName().substring("TabConstraints ".length()), // NOI18N
3210
buf2,
3211                        indent + ONE_INDENT);
3212            }
3213
3214            buf.append(indent);
3215            if (buf2.length() > 0) {
3216                addElementOpenAttr(
3217                    buf,
3218                    "JTabbedPaneConstraints", // NOI18N
3219
new String JavaDoc[] { "tabName", "toolTip" }, // NOI18N
3220
new String JavaDoc[] { tabConstr.getTitle(),
3221                                   tabConstr.getToolTip() });
3222                buf.append(buf2);
3223                buf.append(indent);
3224                addElementClose(buf, "JTabbedPaneConstraints"); // NOI18N
3225
}
3226            else {
3227                addLeafElementOpenAttr(
3228                    buf,
3229                    "JTabbedPaneConstraints", // NOI18N
3230
new String JavaDoc[] { "tabName", "toolTip" }, // NOI18N
3231
new String JavaDoc[] { tabConstr.getTitle(),
3232                                   tabConstr.getToolTip() });
3233            }
3234
3235            return LAYOUT_JTAB;
3236        }
3237
3238        // constraints of JSplitPane
3239
if (constr instanceof JSplitPaneSupport.SplitConstraints) {
3240            Object JavaDoc constrObject = constr.getConstraintsObject();
3241            String JavaDoc position;
3242
3243            if (javax.swing.JSplitPane.TOP.equals(constrObject))
3244                position = "top"; // NOI18N
3245
else if (javax.swing.JSplitPane.BOTTOM.equals(constrObject))
3246                position = "bottom"; // NOI18N
3247
else if (javax.swing.JSplitPane.LEFT.equals(constrObject))
3248                position = "left"; // NOI18N
3249
else
3250                position = "right"; // NOI18N
3251

3252            buf.append(indent);
3253            addLeafElementOpenAttr(
3254                buf,
3255                "JSplitPaneConstraints", // NOI18N
3256
new String JavaDoc[] { "position" }, // NOI18N
3257
new String JavaDoc[] { position });
3258
3259            return LAYOUT_JSPLIT;
3260        }
3261
3262        // constraints of CardLayout
3263
if (constr instanceof CardLayoutSupport.CardConstraints) {
3264            String JavaDoc card = (String JavaDoc) constr.getConstraintsObject();
3265            buf.append(indent);
3266            addLeafElementOpenAttr(
3267                buf,
3268                "CardConstraints", // NOI18N
3269
new String JavaDoc[] { "cardName" }, // NOI18N
3270
new String JavaDoc[] { card });
3271
3272            return LAYOUT_CARD;
3273        }
3274
3275        // constraints of JLayeredPane (must be tested before AbsoluteLayout)
3276
if (constr instanceof JLayeredPaneSupport.LayeredConstraints) {
3277            int layer =
3278                ((JLayeredPaneSupport.LayeredConstraints)constr).getLayer();
3279            java.awt.Rectangle JavaDoc r =
3280                ((JLayeredPaneSupport.LayeredConstraints)constr).getBounds();
3281
3282            buf.append(indent);
3283            addLeafElementOpenAttr(
3284                buf,
3285                "JLayeredPaneConstraints", // NOI18N
3286
new String JavaDoc[] { "x", "y", "width", "height", // NOI18N
3287
"layer", "position" }, // NOI18N
3288
new String JavaDoc[] { Integer.toString(r.x),
3289                               Integer.toString(r.y),
3290                               Integer.toString(r.width),
3291                               Integer.toString(r.height),
3292                               Integer.toString(layer),
3293                               "-1" }); // NOI18N
3294

3295            return LAYOUT_JLAYER;
3296        }
3297
3298        // constraints of AbsoluteLayout
3299
if (constr instanceof AbsoluteLayoutSupport.AbsoluteLayoutConstraints) {
3300            java.awt.Rectangle JavaDoc r =
3301                ((AbsoluteLayoutSupport.AbsoluteLayoutConstraints)constr)
3302                    .getBounds();
3303
3304            buf.append(indent);
3305            addLeafElementOpenAttr(
3306                buf,
3307                "AbsoluteConstraints", // NOI18N
3308
new String JavaDoc[] { "x", "y", "width", "height" }, // NOI18N
3309
new String JavaDoc[] { Integer.toString(r.x),
3310                               Integer.toString(r.y),
3311                               Integer.toString(r.width),
3312                               Integer.toString(r.height) });
3313
3314            return LAYOUT_ABSOLUTE;
3315        }
3316
3317        return -1;
3318    }
3319
3320    private void saveMenuComponent(RADMenuItemComponent component, StringBuffer JavaDoc buf, String JavaDoc indent) {
3321        saveComponent(component, buf, indent);
3322
3323        if (component instanceof RADMenuComponent) {
3324            RADComponent[] children =((RADMenuComponent)component).getSubBeans();
3325            if (children.length > 0) {
3326                buf.append(indent); addElementOpen(buf, XML_SUB_COMPONENTS);
3327                for (int i = 0; i < children.length; i++) {
3328                    String JavaDoc elementType;
3329                    if (children[i] instanceof RADMenuComponent) elementType = XML_MENU_CONTAINER;
3330                    else if (children[i] instanceof RADMenuItemComponent) elementType = XML_MENU_COMPONENT;
3331                    else elementType = XML_COMPONENT;
3332
3333                    buf.append(indent + ONE_INDENT);
3334                    addElementOpenAttr(
3335                        buf,
3336                        elementType,
3337                        new String JavaDoc[] { ATTR_COMPONENT_CLASS, ATTR_COMPONENT_NAME },
3338                        new String JavaDoc[] { children[i].getBeanClass().getName(),
3339                                       children[i].getName() });
3340                    // [PENDING - RADComponents which are not menu???]
3341
saveMenuComponent((RADMenuItemComponent)children[i], buf, indent + ONE_INDENT + ONE_INDENT);
3342                    buf.append(indent + ONE_INDENT); addElementClose(buf, elementType);
3343                }
3344                buf.append(indent); addElementClose(buf, XML_SUB_COMPONENTS);
3345            }
3346        }
3347    }
3348
3349    private void saveComponent(RADComponent component, StringBuffer JavaDoc buf, String JavaDoc indent) {
3350        // 1. Properties
3351
if (!JavaCodeGenerator.VALUE_SERIALIZE.equals(
3352                component.getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION)))
3353        { // save properties only if the component is not to be serialized
3354
saveProperties(component.getKnownBeanProperties(),
3355                           XML_PROPERTIES, buf, indent);
3356
3357            if (component instanceof RADVisualComponent) {
3358                // try to save accessibility properties
3359
FormProperty[] accProps = ((RADVisualComponent)component)
3360                                            .getAccessibilityProperties();
3361                if (saveProperties(accProps,
3362                                   XML_A11Y_PROPERTIES, buf, indent))
3363                    raiseFormatVersion(NB34_VERSION);
3364            }
3365            else if (component instanceof RADMenuItemComponent) {
3366                // try to save accessibility properties
3367
FormProperty[] accProps = ((RADMenuItemComponent)component)
3368                                            .getAccessibilityProperties();
3369                if (saveProperties(accProps,
3370                                   XML_A11Y_PROPERTIES, buf, indent))
3371                    raiseFormatVersion(NB34_VERSION);
3372            }
3373        }
3374
3375        // 1. Synthetic properties
3376
if (component instanceof RADVisualFormContainer)
3377            saveSyntheticProperties(component, buf, indent);
3378
3379        // 2. Events
3380
saveEvents(component.getKnownEvents(), buf, indent);
3381
3382        // 3. Aux Values
3383
Map JavaDoc auxValues = component.getAuxValues();
3384        // Form settings are stored as a part of AuxValues of top-level container
3385
if (component == formModel.getTopRADComponent()) {
3386            auxValues = (auxValues == null) ? new TreeMap() : new TreeMap(auxValues);
3387            Map JavaDoc settings = formModel.getSettings().allSettings();
3388            Iterator iter = settings.entrySet().iterator();
3389            while (iter.hasNext()) {
3390                Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iter.next();
3391                auxValues.put(FORM_SETTINGS_PREFIX + entry.getKey(), entry.getValue());
3392            }
3393        }
3394        if (auxValues != null && auxValues.size() > 0) {
3395// buf.append("\n"); // NOI18N
3396
buf.append(indent); addElementOpen(buf, XML_AUX_VALUES);
3397            saveAuxValues(auxValues, buf, indent + ONE_INDENT);
3398            buf.append(indent); addElementClose(buf, XML_AUX_VALUES);
3399        }
3400    }
3401
3402    private boolean saveProperties(FormProperty[] props,
3403                                   String JavaDoc blockName,
3404                                   StringBuffer JavaDoc buf,
3405                                   String JavaDoc indent)
3406    {
3407        int i=0;
3408        do {
3409            if (i >= props.length)
3410                return false; // nothing saved
3411
FormProperty prop = props[i];
3412            if (prop.isChanged() || prop.getPreCode() != null
3413                                 || prop.getPostCode() != null)
3414                break;
3415            i++;
3416        }
3417        while (true);
3418
3419        buf.append(indent);
3420        addElementOpen(buf, blockName);
3421
3422        for (i=0; i < props.length; i++) {
3423            FormProperty prop = props[i];
3424            if (!prop.isChanged()) {
3425                if (prop.getPreCode() != null || prop.getPostCode() != null) {
3426                    buf.append(indent + ONE_INDENT);
3427                    // in this case save only the pre/post code
3428
addLeafElementOpenAttr(
3429                        buf,
3430                        XML_PROPERTY,
3431                        new String JavaDoc[] {
3432                            ATTR_PROPERTY_NAME,
3433                            ATTR_PROPERTY_PRE_CODE,
3434                            ATTR_PROPERTY_POST_CODE,
3435                        },
3436                        new String JavaDoc[] {
3437                            prop.getName(),
3438                            prop.getPreCode(),
3439                            prop.getPostCode(),
3440                        });
3441                }
3442                continue; // not changed, so do not save value
3443
}
3444
3445            saveProperty(prop, prop.getName(), buf, indent + ONE_INDENT);
3446        }
3447
3448        buf.append(indent);
3449        addElementClose(buf, blockName);
3450
3451        return true;
3452    }
3453
3454    private boolean saveProperty(FormProperty property,
3455                                 String JavaDoc propertyName,
3456                                 StringBuffer JavaDoc buf,
3457                                 String JavaDoc indent)
3458    {
3459        Object JavaDoc value;
3460        Object JavaDoc realValue;
3461        try {
3462            value = property.getValue();
3463            realValue = property.getRealValue();
3464        }
3465        catch (Exception JavaDoc ex) {
3466            ErrorManager.getDefault().annotate(
3467                ex,
3468                FormUtils.getFormattedBundleString(
3469                    "FMT_ERR_CannotGetPropertyValue", // NOI18N
3470
new Object JavaDoc[] { property.getName() }));
3471            nonfatalErrors.add(ex);
3472            return false;
3473        }
3474
3475        String JavaDoc encodedValue = null;
3476        String JavaDoc encodedSerializeValue = null;
3477        org.w3c.dom.Node JavaDoc valueNode = null;
3478
3479        PropertyEditor prEd = property.getCurrentEditor();
3480        
3481        if (prEd instanceof FontEditor) { // Issue 82465: new prEd in NB 6.0
3482
raiseFormatVersion(NB60_VERSION);
3483        }
3484        
3485    if ( prEd instanceof BeanPropertyEditor ||
3486         prEd instanceof XMLPropertyEditor ) {
3487        prEd.setValue(value);
3488    }
3489    
3490    if ( prEd instanceof BeanPropertyEditor &&
3491         ((BeanPropertyEditor) prEd).valueIsBeanProperty())
3492    {
3493        valueNode = saveBeanToXML(realValue.getClass(), topDocument);
3494    } else if (prEd instanceof XMLPropertyEditor) {
3495            valueNode = ((XMLPropertyEditor)prEd).storeToXML(topDocument);
3496            if (valueNode == null) { // property editor refused to save the value
3497
// XXX quick hack for JDNC to serialize custom borders XXX
3498
encodedValue = encodePrimitiveValue(realValue);
3499                if (encodedValue == null) {
3500                    try {
3501                        encodedSerializeValue = encodeValue(realValue);
3502                    }
3503                    catch (Exception JavaDoc ex) {
3504                        ErrorManager.getDefault().annotate(
3505                            ex,
3506                            FormUtils.getFormattedBundleString(
3507                                "FMT_ERR_CannotSaveProperty", // NOI18N
3508
new Object JavaDoc[] { property.getName() }));
3509                        nonfatalErrors.add(ex);
3510                        return false;
3511                    }
3512                }
3513
3514// PersistenceException ex = new PersistenceException(
3515
// "Cannot save the property value"); // NOI18N
3516
// String msg = FormUtils.getFormattedBundleString(
3517
// "FMT_ERR_CannotSaveProperty", // NOI18N
3518
// new Object[] { property.getName() });
3519
// ErrorManager.getDefault().annotate(
3520
// ex, ErrorManager.ERROR, null, msg, null, null);
3521
// nonfatalErrors.add(ex);
3522
// return false;
3523
// XXX quick hack for JDNC to serialize custom borders XXX
3524
}
3525        }
3526        else {
3527            encodedValue = encodePrimitiveValue(value);
3528            if (encodedValue == null) {
3529                try {
3530                    encodedSerializeValue = encodeValue(value);
3531                }
3532                catch (Exception JavaDoc ex) {
3533                    ErrorManager.getDefault().annotate(
3534                        ex,
3535                        FormUtils.getFormattedBundleString(
3536                            "FMT_ERR_CannotSaveProperty", // NOI18N
3537
new Object JavaDoc[] { property.getName() }));
3538                    nonfatalErrors.add(ex);
3539                    return false;
3540                }
3541            }
3542        }
3543
3544        buf.append(indent);
3545
3546        if (encodedValue != null) {
3547            addLeafElementOpenAttr(
3548                buf,
3549                XML_PROPERTY,
3550                new String JavaDoc[] {
3551                    ATTR_PROPERTY_NAME,
3552                    ATTR_PROPERTY_TYPE,
3553                    ATTR_PROPERTY_VALUE,
3554                    ATTR_PROPERTY_PRE_CODE,
3555                    ATTR_PROPERTY_POST_CODE },
3556                new String JavaDoc[] {
3557                    propertyName,
3558                    property.getValueType().getName(),
3559                    encodedValue,
3560                    property.getPreCode(),
3561                    property.getPostCode() });
3562        }
3563        else {
3564            addElementOpenAttr(
3565                buf,
3566                XML_PROPERTY,
3567                new String JavaDoc[] {
3568                    ATTR_PROPERTY_NAME,
3569                    ATTR_PROPERTY_TYPE,
3570                    ATTR_PROPERTY_EDITOR,
3571                    ATTR_PROPERTY_PRE_CODE,
3572                    ATTR_PROPERTY_POST_CODE },
3573                new String JavaDoc[] {
3574                    propertyName,
3575                    property.getValueType().getName(),
3576                    prEd.getClass().getName(),
3577                    property.getPreCode(),
3578                    property.getPostCode() });
3579
3580        if (valueNode != null) {
3581        if( prEd instanceof BeanPropertyEditor
3582            && ((BeanPropertyEditor) prEd).valueIsBeanProperty() )
3583        {
3584            // the property is a bean,
3585
// so there could be some children nodes ...
3586
saveBeanProperty((BeanPropertyEditor) prEd, valueNode, buf, indent + ONE_INDENT);
3587        } else {
3588            saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
3589        }
3590            }
3591            else {
3592                buf.append(indent + ONE_INDENT);
3593                addLeafElementOpenAttr(
3594                    buf,
3595                    XML_SERIALIZED_PROPERTY_VALUE,
3596                    new String JavaDoc[] { ATTR_PROPERTY_VALUE },
3597                    new String JavaDoc[] { encodedSerializeValue });
3598            }
3599            buf.append(indent);
3600            addElementClose(buf, XML_PROPERTY);
3601        }
3602        return true;
3603    }
3604    
3605    private org.w3c.dom.Node JavaDoc saveBeanToXML(Class JavaDoc type, org.w3c.dom.Document JavaDoc doc) {
3606    org.w3c.dom.Element JavaDoc el = doc.createElement(XML_PROPERTY_BEAN);
3607    el.setAttribute(ATTR_PROPERTY_TYPE, type.getName());
3608    return el;
3609    }
3610    
3611    private void saveBeanProperty(BeanPropertyEditor beanPropertyEditor, org.w3c.dom.Node JavaDoc valueNode, StringBuffer JavaDoc buf, String JavaDoc indent) {
3612    boolean children = false;
3613    FormProperty[] props = (FormProperty[]) beanPropertyEditor.getProperties();
3614
3615    NamedNodeMap JavaDoc attributes = valueNode.getAttributes();
3616    String JavaDoc[] attrNames = new String JavaDoc[attributes.getLength()];
3617    String JavaDoc[] attrValues = new String JavaDoc[attributes.getLength()];
3618
3619    for (int i = 0; i < attrValues.length; i++) {
3620        attrNames[i] = attributes.item(i).getNodeName();
3621        attrValues[i] = attributes.item(i).getNodeValue();
3622    }
3623            
3624    for (int i=0; i<props.length; i++) {
3625        if( props[i].isChanged() ) {
3626        if(!children) {
3627            // we found the first child property,
3628
// let's start the element tag
3629
buf.append(indent);
3630            addElementOpenAttr(buf,
3631                    valueNode.getNodeName(),
3632                    attrNames,
3633                    attrValues);
3634            children = true;
3635        }
3636        saveProperty(props[i],
3637             props[i].getName(),
3638             buf,
3639             indent + ONE_INDENT);
3640        }
3641    }
3642
3643    if(children) {
3644        // there were children properties,
3645
// we should close the element tag
3646
buf.append(indent);
3647        addElementClose(buf, valueNode.getNodeName());
3648    } else {
3649        // there were no children properties,
3650
// let's save the node as it is
3651
saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
3652    }
3653    }
3654    
3655    private boolean saveValue(Object JavaDoc value,
3656                              Class JavaDoc valueType,
3657                              PropertyEditor prEd,
3658                              StringBuffer JavaDoc buf,
3659                              String JavaDoc indent)
3660    {
3661        String JavaDoc encodedValue = null;
3662        String JavaDoc encodedSerializeValue = null;
3663        org.w3c.dom.Node JavaDoc valueNode = null;
3664
3665        if (prEd instanceof XMLPropertyEditor) {
3666            prEd.setValue(value);
3667            valueNode = ((XMLPropertyEditor)prEd).storeToXML(topDocument);
3668            if (valueNode == null) { // property editor refused to save the value
3669
PersistenceException ex = new PersistenceException(
3670                                   "Cannot save the property value"); // NOI18N
3671
String JavaDoc msg = FormUtils.getFormattedBundleString(
3672                                 "FMT_ERR_CannotSaveProperty2", // NOI18N
3673
new Object JavaDoc[] { prEd.getClass().getName() });
3674                ErrorManager.getDefault().annotate(
3675                    ex, ErrorManager.ERROR, null, msg, null, null);
3676                nonfatalErrors.add(ex);
3677                return false;
3678            }
3679        }
3680        else {
3681            encodedValue = encodePrimitiveValue(value);
3682            if (encodedValue == null) {
3683                try {
3684                    encodedSerializeValue = encodeValue(value);
3685                }
3686                catch (Exception JavaDoc ex) {
3687                    ErrorManager.getDefault().annotate(
3688                        ex,
3689                        FormUtils.getFormattedBundleString(
3690                            "FMT_ERR_CannotSaveProperty3", // NOI18N
3691
new Object JavaDoc[] { valueType.getClass().getName() }));
3692                    nonfatalErrors.add(ex);
3693                    return false;
3694                }
3695            }
3696        }
3697
3698        buf.append(indent);
3699
3700        if (encodedValue != null) {
3701            addLeafElementOpenAttr(
3702                buf,
3703                XML_VALUE,
3704                new String JavaDoc[] { ATTR_PROPERTY_TYPE, ATTR_PROPERTY_VALUE },
3705                new String JavaDoc[] { valueType.getName(), encodedValue });
3706        }
3707        else {
3708            addElementOpenAttr(
3709                buf,
3710                XML_VALUE,
3711                new String JavaDoc[] { ATTR_PROPERTY_TYPE, ATTR_PROPERTY_EDITOR },
3712                new String JavaDoc[] { valueType.getName(), prEd.getClass().getName() });
3713
3714            if (valueNode != null) {
3715                saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
3716            }
3717            else {
3718                buf.append(indent + ONE_INDENT);
3719                addLeafElementOpenAttr(
3720                    buf,
3721                    XML_SERIALIZED_PROPERTY_VALUE,
3722                    new String JavaDoc[] { ATTR_PROPERTY_VALUE },
3723                    new String JavaDoc[] { encodedSerializeValue });
3724            }
3725            buf.append(indent);
3726            addElementClose(buf, XML_VALUE);
3727        }
3728        return true;
3729    }
3730
3731    private void saveSyntheticProperties(RADComponent component, StringBuffer JavaDoc buf, String JavaDoc indent) {
3732        boolean anyProp = false;
3733        String JavaDoc indent2 = null;
3734
3735        // compatibility hack for saving form's menu bar (part III)
3736
if (component instanceof RADVisualFormContainer) {
3737            RADMenuComponent menuComp =
3738                ((RADVisualFormContainer)component).getContainerMenu();
3739            if (menuComp != null) {
3740                buf.append(indent);
3741                addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
3742                indent2 = indent + ONE_INDENT;
3743                anyProp = true;
3744
3745                buf.append(indent2);
3746                addLeafElementOpenAttr(buf,
3747                    XML_SYNTHETIC_PROPERTY,
3748                    new String JavaDoc[] { ATTR_PROPERTY_NAME,
3749                                   ATTR_PROPERTY_TYPE,
3750                                   ATTR_PROPERTY_VALUE },
3751                    new String JavaDoc[] { "menuBar", // NOI18N
3752
"java.lang.String", // NOI18N
3753
menuComp.getName() });
3754            }
3755        }
3756
3757        Node.Property[] props = component.getSyntheticProperties();
3758        for (int i=0; i < props.length; i++) {
3759            Node.Property prop = props[i];
3760
3761            if (!prop.canWrite())
3762                continue; // don't save read-only properties
3763

3764            if (Boolean.TRUE.equals(prop.getValue("defaultValue"))) // NOI18N
3765
continue; // don't save default values
3766

3767            Object JavaDoc value = null;
3768            try {
3769                value = prop.getValue();
3770            }
3771            catch (Exception JavaDoc ex) {
3772                ErrorManager.getDefault().annotate(
3773                    ex,
3774                    FormUtils.getFormattedBundleString(
3775                        "FMT_ERR_CannotGetPropertyValue", // NOI18N
3776
new Object JavaDoc[] { prop.getName() }));
3777                nonfatalErrors.add(ex);
3778                continue;
3779            }
3780            String JavaDoc valueType = prop.getValueType().getName();
3781            String JavaDoc encodedValue = encodePrimitiveValue(value);
3782            if (encodedValue == null) {
3783                try {
3784                    encodedValue = encodeValue(value);
3785                }
3786                catch (Exception JavaDoc ex) {
3787                    ErrorManager.getDefault().annotate(
3788                        ex,
3789                        FormUtils.getFormattedBundleString(
3790                            "FMT_ERR_CannotSaveProperty", // NOI18N
3791
new Object JavaDoc[] { prop.getName() }));
3792                    nonfatalErrors.add(ex);
3793                    continue;
3794                }
3795            }
3796
3797            if (!anyProp) {
3798                buf.append(indent);
3799                addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
3800                indent2 = indent + ONE_INDENT;
3801                anyProp = true;
3802            }
3803
3804            buf.append(indent2);
3805            addLeafElementOpenAttr(
3806                buf,
3807                XML_SYNTHETIC_PROPERTY,
3808                new String JavaDoc[] {
3809                    ATTR_PROPERTY_NAME,
3810                    ATTR_PROPERTY_TYPE,
3811                    ATTR_PROPERTY_VALUE,
3812                },
3813                new String JavaDoc[] {
3814                    prop.getName(),
3815                    valueType,
3816                    encodedValue,
3817                }
3818                );
3819        }
3820
3821        if (anyProp) {
3822            buf.append(indent);
3823            addElementClose(buf, XML_SYNTHETIC_PROPERTIES);
3824        }
3825    }
3826
3827    private void saveEvents(Event[] events, StringBuffer JavaDoc buf, String JavaDoc indent) {
3828        boolean anyEvent = false;
3829        String JavaDoc indent2 = null;
3830        StringBuffer JavaDoc strbuf;
3831
3832        for (int i=0; i < events.length; i++) {
3833            Event event = events[i];
3834            if (!event.hasEventHandlers())
3835                continue;
3836
3837            if (!anyEvent) {
3838                buf.append(indent);
3839                addElementOpen(buf, XML_EVENTS);
3840                indent2 = indent + ONE_INDENT;
3841                anyEvent = true;
3842            }
3843
3844            strbuf = new StringBuffer JavaDoc(50);
3845            Class JavaDoc[] params = event.getListenerMethod().getParameterTypes();
3846            for (int j=0; j < params.length; j++) {
3847                strbuf.append(params[j].getName());
3848                if (j + 1 < params.length)
3849                    strbuf.append(","); // NOI18N
3850
}
3851            String JavaDoc paramString = strbuf.toString();
3852
3853            strbuf = new StringBuffer JavaDoc(50);
3854            String JavaDoc[] handlers = event.getEventHandlers();
3855            for (int j=0; j < handlers.length; j++) {
3856                strbuf.append(handlers[j]);
3857                if (j + 1 < handlers.length)
3858                    strbuf.append(","); // NOI18N
3859
}
3860            String JavaDoc handlerString = strbuf.toString();
3861
3862            buf.append(indent2);
3863            addLeafElementOpenAttr(
3864                buf,
3865                XML_EVENT,
3866                new String JavaDoc[] {
3867                    ATTR_EVENT_NAME,
3868                    ATTR_EVENT_LISTENER,
3869                    ATTR_EVENT_PARAMS,
3870                    ATTR_EVENT_HANDLER
3871                },
3872                new String JavaDoc[] {
3873                    event.getListenerMethod().getName(),
3874                    event.getListenerMethod().getDeclaringClass().getName(),
3875                    paramString,
3876                    handlerString
3877                }
3878            );
3879        }
3880
3881        if (anyEvent) {
3882            buf.append(indent);
3883            addElementClose(buf, XML_EVENTS);
3884        }
3885    }
3886
3887    private void saveAuxValues(Map JavaDoc auxValues, StringBuffer JavaDoc buf, String JavaDoc indent) {
3888        for (Iterator it = auxValues.entrySet().iterator(); it.hasNext();) {
3889            Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
3890            String JavaDoc valueName = (String JavaDoc)entry.getKey();
3891            Object JavaDoc value = entry.getValue();
3892            if (value == null) continue; // such values are not saved
3893
String JavaDoc valueType = value.getClass().getName();
3894            String JavaDoc encodedValue = encodePrimitiveValue(value);
3895            if (encodedValue == null) {
3896                try {
3897                    encodedValue = encodeValue(value);
3898                }
3899                catch (Exception JavaDoc ex) {
3900                    ErrorManager.getDefault().annotate(
3901                        ex,
3902                        FormUtils.getFormattedBundleString(
3903                            "FMT_ERR_CannotSaveProperty", // NOI18N
3904
new Object JavaDoc[] { valueName }));
3905                    nonfatalErrors.add(ex);
3906                    continue;
3907                }
3908            }
3909
3910            buf.append(indent);
3911            addLeafElementOpenAttr(
3912                buf,
3913                XML_AUX_VALUE,
3914                new String JavaDoc[] {
3915                    ATTR_AUX_NAME,
3916                    ATTR_AUX_VALUE_TYPE,
3917                    ATTR_AUX_VALUE },
3918                new String JavaDoc[] {
3919                    valueName,
3920                    valueType,
3921                    encodedValue
3922                }
3923            );
3924        }
3925    }
3926
3927    private PropertyEditor createPropertyEditor(Class JavaDoc editorClass,
3928                                                Class JavaDoc propertyType,
3929                                                FormProperty property)
3930        throws InstantiationException JavaDoc,
3931               IllegalAccessException JavaDoc
3932    {
3933        PropertyEditor ed;
3934        if (editorClass.equals(RADConnectionPropertyEditor.class)) {
3935            ed = new RADConnectionPropertyEditor(propertyType);
3936        } else if (editorClass.equals(ComponentChooserEditor.class)) {
3937            ed = new ComponentChooserEditor(new Class JavaDoc[] {propertyType});
3938        } else {
3939            ed = (PropertyEditor) editorClass.newInstance();
3940        }
3941
3942        if (property != null)
3943            property.getPropertyContext().initPropertyEditor(ed);
3944        else if (ed instanceof FormAwareEditor)
3945            ((FormAwareEditor)ed).setFormModel(formModel);
3946
3947        return ed;
3948    }
3949
3950    // ---------------------
3951
// The following code ensures persistence of code structure in XML. The
3952
// code is quite general except special hacks for meta components which
3953
// must be handled specially (as references) - as we don't save full code
3954
// yet but only its parts; components are saved separately. [This feature
3955
// is used only for saving/loading code of non-standard layout supports.]
3956
//
3957
// There are two possible ways how to save the code structure - to save
3958
// the code flow or the static structure.
3959
//
3960
// In the first case (code flow), a sequence of code statements is saved
3961
// (together with epxressions used by the statements). In the second case
3962
// (static structure), root code expressions are saved as trees including
3963
// all used expressions and all defined statements. Which style is used
3964
// is controlled by the codeFlow variable. [We use only code flow now.]
3965

3966    // XML persistence of code structure - saving
3967

3968    private void saveCodeExpression(CodeExpression exp,
3969                                    StringBuffer JavaDoc buf, String JavaDoc indent)
3970    {
3971        buf.append(indent);
3972
3973        Object JavaDoc value = getExpressionsMap().get(exp);
3974        if (value != null) { // save expression reference only
3975
addLeafElementOpenAttr(buf,
3976                                   XML_CODE_EXPRESSION,
3977                                   new String JavaDoc[] { ATTR_EXPRESSION_ID },
3978                                   new String JavaDoc[] { value.toString() });
3979        }
3980        else { // save complete expression
3981
// create expression ID
3982
lastExpId++;
3983            String JavaDoc expId = Integer.toString(lastExpId);
3984            CodeVariable var = exp.getVariable();
3985            if (var != null)
3986                expId += "_" + var.getName(); // NOI18N
3987
getExpressionsMap().put(exp, expId);
3988
3989            addElementOpenAttr(buf,
3990                               XML_CODE_EXPRESSION,
3991                               new String JavaDoc[] { ATTR_EXPRESSION_ID },
3992                               new String JavaDoc[] { expId });
3993
3994            String JavaDoc subIndent = indent + ONE_INDENT;
3995
3996            if (var != null)
3997                saveCodeVariable(var, buf, subIndent);
3998
3999            saveExpressionOrigin(exp.getOrigin(), buf, subIndent);
4000
4001            if (!codeFlow) {
4002                // if static code structure is being saved, statements are
4003
// saved inside their parent expressions
4004
Iterator it = CodeStructure.getDefinedStatementsIterator(exp);
4005                if (it.hasNext()) {
4006                    buf.append(subIndent);
4007                    addElementOpen(buf, XML_CODE_STATEMENTS);
4008
4009                    String JavaDoc subSubIndent = subIndent + ONE_INDENT;
4010                    do {
4011                        saveCodeStatement((CodeStatement) it.next(),
4012                                          buf, subSubIndent);
4013                    }
4014                    while (it.hasNext());
4015
4016                    buf.append(subIndent);
4017                    addElementClose(buf, XML_CODE_STATEMENTS);
4018                }
4019            }
4020
4021            buf.append(indent);
4022            addElementClose(buf, XML_CODE_EXPRESSION);
4023        }
4024    }
4025
4026    private void saveCodeVariable(CodeVariable var,
4027                                  StringBuffer JavaDoc buf, String JavaDoc indent)
4028    {
4029        buf.append(indent);
4030        if (getVariablesMap().get(var) != null) {
4031            addLeafElementOpenAttr(buf,
4032                                   XML_CODE_VARIABLE,
4033                                   new String JavaDoc[] { ATTR_VAR_NAME },
4034                                   new String JavaDoc[] { var.getName() });
4035        }
4036        else {
4037            addLeafElementOpenAttr(
4038                buf,
4039                XML_CODE_VARIABLE,
4040                new String JavaDoc[] { ATTR_VAR_NAME,
4041                               ATTR_VAR_TYPE,
4042                               ATTR_VAR_DECLARED_TYPE },
4043                new String JavaDoc[] { var.getName(),
4044                               Integer.toString(var.getType()),
4045                               var.getDeclaredType().getName() });
4046
4047            getVariablesMap().put(var, var);
4048        }
4049    }
4050
4051    private void saveExpressionOrigin(CodeExpressionOrigin origin,
4052                                      StringBuffer JavaDoc buf, String JavaDoc indent)
4053    {
4054        buf.append(indent);
4055        addElementOpen(buf, XML_CODE_ORIGIN);
4056
4057        String JavaDoc subIndent = indent + ONE_INDENT;
4058
4059        CodeExpression parentExp = origin.getParentExpression();
4060        if (parentExp != null)
4061            saveCodeExpression(parentExp, buf, subIndent);
4062
4063        Object JavaDoc metaObject = origin.getMetaObject();
4064        if (metaObject != null)
4065            saveOriginMetaObject(metaObject, buf, subIndent);
4066        else
4067            saveValue(origin.getValue(), origin.getType(), null,
4068                      buf, subIndent);
4069
4070        saveParameters(origin.getCreationParameters(), buf, subIndent);
4071
4072        buf.append(indent);
4073        addElementClose(buf, XML_CODE_ORIGIN);
4074    }
4075
4076    private void saveCodeStatement(CodeStatement statement,
4077                                   StringBuffer JavaDoc buf, String JavaDoc indent)
4078    {
4079        buf.append(indent);
4080        addElementOpen(buf, XML_CODE_STATEMENT);
4081
4082        String JavaDoc subIndent = indent + ONE_INDENT;
4083
4084        if (codeFlow) {
4085            // if code flow is being saved, also the parent expression of
4086
// the statement must be saved for it
4087
CodeExpression parentExp = statement.getParentExpression();
4088            if (parentExp != null)
4089                saveCodeExpression(parentExp, buf, subIndent);
4090        }
4091
4092        Object JavaDoc metaObject = statement.getMetaObject();
4093        if (metaObject != null)
4094            saveStatementMetaObject(metaObject, buf, subIndent);
4095
4096        saveParameters(statement.getStatementParameters(), buf, subIndent);
4097
4098        buf.append(indent);
4099        addElementClose(buf, XML_CODE_STATEMENT);
4100    }
4101
4102    private void saveOriginMetaObject(Object JavaDoc metaObject,
4103                                      StringBuffer JavaDoc buf, String JavaDoc indent)
4104    {
4105        if (metaObject instanceof Node.Property) {
4106            Node.Property property = (Node.Property) metaObject;
4107            Object JavaDoc value;
4108            try {
4109                value = property.getValue();
4110            }
4111            catch (Exception JavaDoc ex) { // should not happen
4112
org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4113                return;
4114            }
4115
4116            PropertyEditor prEd = property instanceof FormProperty ?
4117                                  ((FormProperty)property).getCurrentEditor() :
4118                                  property.getPropertyEditor();
4119            saveValue(value, property.getValueType(), prEd, buf,indent);
4120            return;
4121        }
4122
4123        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
4124        String JavaDoc subIndent = indent + ONE_INDENT;
4125        String JavaDoc originType = null;
4126
4127        if (metaObject instanceof Constructor) {
4128            Constructor ctor = (Constructor) metaObject;
4129            StringBuffer JavaDoc buf3 = new StringBuffer JavaDoc();
4130            Class JavaDoc[] paramTypes = ctor.getParameterTypes();
4131
4132            for (int i=0; i < paramTypes.length; i++) {
4133                buf3.append(paramTypes[i].getName());
4134                if (i+1 < paramTypes.length)
4135                    buf3.append(", "); // NOI18N
4136
}
4137
4138            buf2.append(subIndent);
4139            addLeafElementOpenAttr(
4140                buf2,
4141                XML_CODE_CONSTRUCTOR,
4142                new String JavaDoc[] { ATTR_MEMBER_CLASS,
4143                               ATTR_MEMBER_PARAMS },
4144                new String JavaDoc[] { ctor.getDeclaringClass().getName(),
4145                               buf3.toString() });
4146
4147            originType = XML_CODE_CONSTRUCTOR;
4148        }
4149
4150        // special code for handling meta component references
4151
else if (metaObject instanceof RADComponent) {
4152            RADComponent metacomp = (RADComponent) metaObject;
4153
4154            buf2.append(subIndent);
4155            addLeafElementOpenAttr(
4156                buf2,
4157                XML_COMPONENT_REF,
4158                new String JavaDoc[] { ATTR_COMPONENT_NAME },
4159                new String JavaDoc[] { metacomp != formModel.getTopRADComponent() ?
4160                               metacomp.getName() : "." }); // NOI18N
4161

4162            originType = XML_COMPONENT_REF;
4163        }
4164
4165        else if (metaObject instanceof Method) {
4166            saveMethod((Method) metaObject, buf2, subIndent);
4167            originType = XML_CODE_METHOD;
4168        }
4169
4170        else if (metaObject instanceof Field) {
4171            saveField((Field) metaObject, buf2, subIndent);
4172            originType = XML_CODE_FIELD;
4173        }
4174
4175        if (originType == null)
4176            return; // unknown origin
4177

4178        buf.append(indent);
4179        addElementOpenAttr(buf,
4180                           XML_ORIGIN_META_OBJECT,
4181                           new String JavaDoc[] { ATTR_META_OBJECT_TYPE },
4182                           new String JavaDoc[] { originType } );
4183        buf.append(buf2);
4184        buf.append(indent);
4185        addElementClose(buf, XML_ORIGIN_META_OBJECT);
4186    }
4187
4188    private void saveStatementMetaObject(Object JavaDoc metaObject,
4189                                         StringBuffer JavaDoc buf, String JavaDoc indent)
4190    {
4191        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
4192        String JavaDoc subIndent = indent + ONE_INDENT;
4193        String JavaDoc statementType = null;
4194
4195        if (metaObject instanceof Method) {
4196            saveMethod((Method) metaObject, buf2, subIndent);
4197            statementType = XML_CODE_METHOD;
4198        }
4199        else if (metaObject instanceof Field) {
4200            saveField((Field) metaObject, buf2, subIndent);
4201            statementType = XML_CODE_FIELD;
4202        }
4203        else if (metaObject instanceof CodeExpression) { // variable assignment
4204
CodeExpression exp = (CodeExpression) metaObject;
4205            if (exp.getVariable() != null) {
4206                saveCodeExpression(exp, buf2, subIndent);
4207                statementType = XML_CODE_EXPRESSION;
4208            }
4209        }
4210        // [... variable declaration statement]
4211

4212        if (statementType == null)
4213            return; // unknown statement
4214

4215        buf.append(indent);
4216        addElementOpenAttr(buf,
4217                           XML_STATEMENT_META_OBJECT,
4218                           new String JavaDoc[] { ATTR_META_OBJECT_TYPE },
4219                           new String JavaDoc[] { statementType } );
4220        buf.append(buf2);
4221        buf.append(indent);
4222        addElementClose(buf, XML_STATEMENT_META_OBJECT);
4223    }
4224
4225    private void saveParameters(CodeExpression[] parameters,
4226                                StringBuffer JavaDoc buf, String JavaDoc indent)
4227    {
4228        if (parameters.length > 0) {
4229            buf.append(indent);
4230            addElementOpen(buf, XML_CODE_PARAMETERS);
4231
4232            String JavaDoc subIndent = indent + ONE_INDENT;
4233            for (int i=0; i < parameters.length; i++)
4234                saveCodeExpression(parameters[i], buf, subIndent);
4235
4236            buf.append(indent);
4237            addElementClose(buf, XML_CODE_PARAMETERS);
4238        }
4239    }
4240
4241    private static void saveMethod(Method method,
4242                                   StringBuffer JavaDoc buf, String JavaDoc indent)
4243    {
4244        StringBuffer JavaDoc buf2 = new StringBuffer JavaDoc();
4245        Class JavaDoc[] paramTypes = method.getParameterTypes();
4246
4247        for (int i=0; i < paramTypes.length; i++) {
4248            buf2.append(paramTypes[i].getName());
4249            if (i+1 < paramTypes.length)
4250                buf2.append(", "); // NOI18N
4251
}
4252
4253        buf.append(indent);
4254        addLeafElementOpenAttr(
4255            buf,
4256            XML_CODE_METHOD,
4257            new String JavaDoc[] { ATTR_MEMBER_NAME,
4258                           ATTR_MEMBER_CLASS,
4259                           ATTR_MEMBER_PARAMS },
4260            new String JavaDoc[] { method.getName(),
4261                           method.getDeclaringClass().getName(),
4262                           buf2.toString() });
4263    }
4264
4265    private static void saveField(Field field, StringBuffer JavaDoc buf, String JavaDoc indent)
4266    {
4267        buf.append(indent);
4268        addLeafElementOpenAttr(
4269            buf,
4270            XML_CODE_FIELD,
4271            new String JavaDoc[] { ATTR_MEMBER_NAME,
4272                           ATTR_MEMBER_CLASS },
4273            new String JavaDoc[] { field.getName(),
4274                           field.getDeclaringClass().getName() });
4275    }
4276
4277    // -----------
4278
// XML persistence of code structure - loading
4279

4280    private CodeExpression loadCodeExpression(org.w3c.dom.Node JavaDoc node) {
4281        String JavaDoc expId = getAttribute(node, ATTR_EXPRESSION_ID);
4282        if (expId == null)
4283            return null; // missing ID error
4284

4285        CodeExpression exp = (CodeExpression) getExpressionsMap().get(expId);
4286        if (exp != null)
4287            return exp;
4288
4289        org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
4290        if (childNodes == null)
4291            return null; // missing subnodes (expression content) error
4292

4293        org.w3c.dom.Node JavaDoc variableNode = null;
4294        org.w3c.dom.Node JavaDoc originNode = null;
4295        org.w3c.dom.Node JavaDoc statementsNode = null;
4296
4297        for (int i=0, n=childNodes.getLength(); i < n; i++) {
4298            org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4299            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
4300                continue; // ignore text nodes
4301

4302            String JavaDoc nodeName = childNode.getNodeName();
4303
4304            if (XML_CODE_VARIABLE.equals(nodeName))
4305                variableNode = childNode;
4306            else if (XML_CODE_ORIGIN.equals(nodeName))
4307                originNode = childNode;
4308            else if (!codeFlow && XML_CODE_STATEMENTS.equals(nodeName))
4309                statementsNode = childNode;
4310        }
4311
4312        if (originNode == null)
4313            return null; // missing origin error
4314

4315        CodeExpressionOrigin origin = loadExpressionOrigin(originNode);
4316        if (origin == null)
4317            return null; // origin loading error
4318

4319        // special code for handling meta component references
4320
Object JavaDoc originMetaObject = origin.getMetaObject();
4321        if (originMetaObject instanceof RADComponent) {
4322            // use the expression from meta component
4323
exp = ((RADComponent)originMetaObject).getCodeExpression();
4324        }
4325        else { // create a new expression normally
4326
exp = getCodeStructure().createExpression(origin);
4327
4328            CodeVariable var = variableNode != null ?
4329                               loadCodeVariable(variableNode) : null;
4330            if (var != null)
4331                getCodeStructure().attachExpressionToVariable(exp, var);
4332        }
4333
4334        getExpressionsMap().put(expId, exp);
4335
4336        if (statementsNode != null) {
4337            childNodes = statementsNode.getChildNodes();
4338            if (childNodes != null) {
4339                for (int i=0, n=childNodes.getLength(); i < n; i++) {
4340                    org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4341
4342                    if (XML_CODE_STATEMENT.equals(childNode.getNodeName()))
4343                        loadCodeStatement(childNode, exp);
4344                }
4345            }
4346        }
4347
4348        return exp;
4349    }
4350
4351    private CodeVariable loadCodeVariable(org.w3c.dom.Node JavaDoc node) {
4352        org.w3c.dom.NamedNodeMap JavaDoc attr = node.getAttributes();
4353        if (attr == null)
4354            return null; // no attributes error
4355

4356        node = attr.getNamedItem(ATTR_VAR_NAME);
4357        if (node == null)
4358            return null; // missing variable name error
4359
String JavaDoc name = node.getNodeValue();
4360
4361        CodeVariable var = getCodeStructure().getVariable(name);
4362        if (var != null)
4363            return var;
4364
4365        node = attr.getNamedItem(ATTR_VAR_TYPE);
4366        if (node == null)
4367            return null; // missing variable type error
4368
int type = Integer.parseInt(node.getNodeValue());
4369
4370        node = attr.getNamedItem(ATTR_VAR_DECLARED_TYPE);
4371        if (node == null)
4372            return null; // missing variable declared type error
4373
Class JavaDoc declaredType = null;
4374
4375        try {
4376            declaredType = getClassFromString(node.getNodeValue());
4377        }
4378        catch (ClassNotFoundException JavaDoc ex) {
4379            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4380        }
4381        if (declaredType == null)
4382            return null; // variable declared type loading error
4383

4384        return getCodeStructure().createVariable(type, declaredType, name);
4385    }
4386
4387    private CodeExpressionOrigin loadExpressionOrigin(org.w3c.dom.Node JavaDoc node) {
4388        org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
4389        if (childNodes == null)
4390            return null; // missing subnodes (origin content) error
4391

4392        org.w3c.dom.Node JavaDoc parentExpNode = null;
4393        org.w3c.dom.Node JavaDoc metaObjectNode = null;
4394        org.w3c.dom.Node JavaDoc valueNode = null;
4395        org.w3c.dom.Node JavaDoc parametersNode = null;
4396
4397        for (int i=0, n=childNodes.getLength(); i < n; i++) {
4398            org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4399            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
4400                continue; // ignore text nodes
4401

4402            String JavaDoc nodeName = childNode.getNodeName();
4403
4404            if (XML_CODE_EXPRESSION.equals(nodeName))
4405                parentExpNode = childNode;
4406            else if (XML_ORIGIN_META_OBJECT.equals(nodeName))
4407                metaObjectNode = childNode;
4408            else if (XML_VALUE.equals(nodeName))
4409                valueNode = childNode;
4410            else if (XML_CODE_PARAMETERS.equals(nodeName))
4411                parametersNode = childNode;
4412        }
4413
4414        if (metaObjectNode == null && valueNode == null)
4415            return null; // missing origin metaobject or value error
4416

4417        CodeExpression parentExp;
4418        if (parentExpNode != null) {
4419            parentExp = loadCodeExpression(parentExpNode);
4420            if (parentExp == null)
4421                return null; // parent expression loading error
4422
}
4423        else parentExp = null; // origin without parent expression
4424

4425        CodeExpression[] parameters = parametersNode != null ?
4426                                        loadParameters(parametersNode) :
4427                                        CodeStructure.EMPTY_PARAMS;
4428        if (parameters == null)
4429            return null; // error loading parameters
4430

4431        CodeExpressionOrigin origin = null;
4432
4433        if (metaObjectNode != null) {
4434            String JavaDoc metaObjectType = getAttribute(metaObjectNode,
4435                                                  ATTR_META_OBJECT_TYPE);
4436            childNodes = metaObjectNode.getChildNodes();
4437            if (metaObjectType != null && childNodes != null) {
4438                for (int i=0, n=childNodes.getLength(); i < n; i++) {
4439                    org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4440
4441                    String JavaDoc nodeName = childNode.getNodeName();
4442                    if (!metaObjectType.equals(nodeName))
4443                        continue;
4444
4445                    if (XML_VALUE.equals(nodeName)) {
4446                        valueNode = childNode;
4447                        break;
4448                    }
4449
4450                    if (XML_CODE_CONSTRUCTOR.equals(nodeName)) {
4451                        org.w3c.dom.NamedNodeMap JavaDoc attr = childNode.getAttributes();
4452                        if (attr == null)
4453                            return null; // no attributes error
4454

4455                        node = attr.getNamedItem(ATTR_MEMBER_CLASS);
4456                        if (node == null)
4457                            return null; // missing constructor class error
4458

4459                        Class JavaDoc ctorClass;
4460                        try {
4461                            ctorClass = getClassFromString(node.getNodeValue());
4462                        }
4463                        catch (ClassNotFoundException JavaDoc ex) {
4464                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4465                            return null; // constructor class loading error
4466
}
4467
4468                        node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
4469                        if (node == null)
4470                            return null; // missing constructor parameter types error
4471

4472                        Class JavaDoc[] paramTypes;
4473                        StringTokenizer paramTokens =
4474                            new StringTokenizer(node.getNodeValue(), ", "); // NOI18N
4475
List typeList = new ArrayList();
4476                        try {
4477                            while (paramTokens.hasMoreTokens()) {
4478                                typeList.add(getClassFromString(
4479                                                 paramTokens.nextToken()));
4480                            }
4481                            paramTypes = new Class JavaDoc[typeList.size()];
4482                            typeList.toArray(paramTypes);
4483                        }
4484                        catch (ClassNotFoundException JavaDoc ex) {
4485                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4486                            return null; // parameters classes loading error
4487
}
4488
4489                        Constructor ctor;
4490                        try {
4491                            ctor = ctorClass.getConstructor(paramTypes);
4492                        }
4493                        catch (NoSuchMethodException JavaDoc ex) {
4494                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4495                            return null; // constructor not found error
4496
}
4497
4498                        origin = CodeStructure.createOrigin(ctor, parameters);
4499                        break;
4500                    }
4501
4502                    // special code for handling meta component references
4503
if (XML_COMPONENT_REF.equals(nodeName)) {
4504                        String JavaDoc name = getAttribute(childNode,
4505                                                    ATTR_COMPONENT_NAME);
4506                        if (name == null)
4507                            return null; // missing component name error
4508

4509                        RADComponent comp = name.equals(".") ? // NOI18N
4510
formModel.getTopRADComponent() :
4511                                (RADComponent) getComponentsMap().get(name);
4512                        if (comp == null)
4513                            return null; // no such component error
4514

4515                        origin = comp.getCodeExpression().getOrigin();
4516                        break;
4517                    }
4518
4519                    if (XML_CODE_METHOD.equals(nodeName)) {
4520                        Method m = loadMethod(childNode);
4521                        if (m == null)
4522                            return null; // method loading error
4523

4524                        origin = CodeStructure.createOrigin(
4525                                                   parentExp, m, parameters);
4526                        break;
4527                    }
4528
4529                    if (XML_CODE_FIELD.equals(nodeName)) {
4530                        Field f = loadField(childNode);
4531                        if (f == null)
4532                            return null; // field loading error
4533

4534                        origin = CodeStructure.createOrigin(parentExp, f);
4535                        break;
4536                    }
4537                }
4538            }
4539        }
4540
4541        if (origin == null) {
4542            if (valueNode == null)
4543                return null; // origin metaobject loading error
4544

4545            String JavaDoc typeStr = getAttribute(valueNode, ATTR_PROPERTY_TYPE);
4546            if (typeStr == null)
4547                return null; // missing value type error
4548

4549            Object JavaDoc editorOrValue = getPropertyEditorOrValue(valueNode);
4550            if (editorOrValue == NO_VALUE)
4551                return null; // value loading error
4552

4553            Class JavaDoc valueType;
4554            try {
4555                valueType = getClassFromString(typeStr);
4556            }
4557            catch (Exception JavaDoc ex) { // does not happen
4558
return null; // value loading error
4559
}
4560
4561            origin = editorOrValue instanceof PropertyEditor ?
4562                     FormCodeSupport.createOrigin(
4563                         valueType,
4564                         (PropertyEditor) editorOrValue) :
4565                     CodeStructure.createOrigin(
4566                         valueType,
4567                         editorOrValue,
4568                         editorOrValue != null ?
4569                             editorOrValue.toString() : "null"); // NOI18N
4570
}
4571
4572        return origin;
4573    }
4574
4575    private CodeStatement loadCodeStatement(org.w3c.dom.Node JavaDoc node,
4576                                            CodeExpression parentExp)
4577    {
4578        org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
4579        if (childNodes == null)
4580            return null; // missing subnodes (statement content) error
4581

4582        org.w3c.dom.Node JavaDoc parentExpNode = null;
4583        org.w3c.dom.Node JavaDoc metaObjectNode = null;
4584        org.w3c.dom.Node JavaDoc parametersNode = null;
4585
4586        for (int i=0, n=childNodes.getLength(); i < n; i++) {
4587            org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4588            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
4589                continue; // ignore text nodes
4590

4591            String JavaDoc nodeName = childNode.getNodeName();
4592
4593            if (XML_CODE_EXPRESSION.equals(nodeName)) {
4594                if (parentExp == null)
4595                    parentExpNode = childNode;
4596            }
4597            else if (XML_STATEMENT_META_OBJECT.equals(nodeName))
4598                metaObjectNode = childNode;
4599            else if (XML_CODE_PARAMETERS.equals(nodeName))
4600                parametersNode = childNode;
4601        }
4602
4603        if (metaObjectNode == null)
4604            return null; // missing statement metaobject error
4605

4606        if (parentExpNode != null) {
4607            parentExp = loadCodeExpression(parentExpNode);
4608            if (parentExp == null)
4609                return null; // parent expression loading error
4610
}
4611
4612        CodeExpression[] parameters = parametersNode != null ?
4613                                        loadParameters(parametersNode) :
4614                                        CodeStructure.EMPTY_PARAMS;
4615        if (parameters == null)
4616            return null; // error loading parameters
4617

4618        CodeStatement statement = null;
4619
4620        String JavaDoc metaObjectType = getAttribute(metaObjectNode,
4621                                              ATTR_META_OBJECT_TYPE);
4622        childNodes = metaObjectNode.getChildNodes();
4623        if (metaObjectType != null && childNodes != null) {
4624            for (int i=0, n=childNodes.getLength(); i < n; i++) {
4625                org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4626
4627                String JavaDoc nodeName = childNode.getNodeName();
4628                if (!metaObjectType.equals(nodeName))
4629                    continue;
4630
4631                if (XML_CODE_METHOD.equals(nodeName)) {
4632                    Method m = loadMethod(childNode);
4633                    if (m == null)
4634                        return null; // method loading error
4635

4636                    statement = CodeStructure.createStatement(
4637                                                parentExp, m, parameters);
4638                    break;
4639                }
4640
4641                if (XML_CODE_FIELD.equals(nodeName)) {
4642                    Field f = loadField(childNode);
4643                    if (f == null)
4644                        return null; // field loading error
4645

4646                    if (parameters.length != 1)
4647                        return null; // inconsistent data error
4648

4649                    statement = CodeStructure.createStatement(
4650                                                  parentExp, f, parameters[0]);
4651                    break;
4652                }
4653
4654                if (XML_CODE_EXPRESSION.equals(nodeName)) {
4655                    // variable assignment
4656
CodeExpression exp = loadCodeExpression(childNode);
4657                    if (exp != parentExp)
4658                        return null; // inconsistent data error
4659

4660                    CodeVariable var = exp.getVariable();
4661                    if (var == null)
4662                        return null; // non-existing variable error
4663

4664                    statement = var.getAssignment(exp);
4665                    break;
4666                }
4667            }
4668        }
4669
4670        return statement;
4671    }
4672
4673    private CodeExpression[] loadParameters(org.w3c.dom.Node JavaDoc node) {
4674        List paramList = new ArrayList();
4675        org.w3c.dom.NodeList JavaDoc childNodes = node.getChildNodes();
4676        if (childNodes != null) {
4677            for (int i=0, n=childNodes.getLength(); i < n; i++) {
4678                org.w3c.dom.Node JavaDoc childNode = childNodes.item(i);
4679
4680                if (XML_CODE_EXPRESSION.equals(childNode.getNodeName())) {
4681                    CodeExpression exp = loadCodeExpression(childNode);
4682                    if (exp == null)
4683                        return null; // parameter loading error
4684

4685                    paramList.add(exp);
4686                }
4687            }
4688
4689            CodeExpression[] params = new CodeExpression[paramList.size()];
4690            paramList.toArray(params);
4691            return params;
4692        }
4693        else return CodeStructure.EMPTY_PARAMS;
4694    }
4695
4696    private /*static */Method loadMethod(org.w3c.dom.Node JavaDoc node) {
4697        org.w3c.dom.NamedNodeMap JavaDoc attr = node.getAttributes();
4698        if (attr == null)
4699            return null; // no attributes error
4700

4701        node = attr.getNamedItem(ATTR_MEMBER_NAME);
4702        if (node == null)
4703            return null; // missing method name error
4704
String JavaDoc name = node.getNodeValue();
4705
4706        node = attr.getNamedItem(ATTR_MEMBER_CLASS);
4707        if (node == null)
4708            return null; // missing method class error
4709

4710        Class JavaDoc methodClass;
4711        try {
4712            methodClass = getClassFromString(node.getNodeValue());
4713        }
4714        catch (ClassNotFoundException JavaDoc ex) {
4715            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4716            return null; // method class loading error
4717
}
4718
4719        node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
4720        if (node == null)
4721            return null; // missing method parameter types error
4722

4723        Class JavaDoc[] paramTypes;
4724        StringTokenizer paramTokens =
4725            new StringTokenizer(node.getNodeValue(), ", "); // NOI18N
4726
List typeList = new ArrayList();
4727        try {
4728            while (paramTokens.hasMoreTokens()) {
4729                typeList.add(getClassFromString(
4730                                 paramTokens.nextToken()));
4731            }
4732            paramTypes = new Class JavaDoc[typeList.size()];
4733            typeList.toArray(paramTypes);
4734        }
4735        catch (ClassNotFoundException JavaDoc ex) {
4736            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4737            return null; // parameters classes loading error
4738
}
4739
4740        try {
4741            return methodClass.getMethod(name, paramTypes);
4742        }
4743        catch (NoSuchMethodException JavaDoc ex) {
4744            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4745            return null; // method not found error
4746
}
4747    }
4748
4749    private /*static */Field loadField(org.w3c.dom.Node JavaDoc node) {
4750        org.w3c.dom.NamedNodeMap JavaDoc attr = node.getAttributes();
4751        if (attr == null)
4752            return null; // no attributes error
4753

4754        node = attr.getNamedItem(ATTR_MEMBER_NAME);
4755        if (node == null)
4756            return null; // missing field name error
4757
String JavaDoc name = node.getNodeValue();
4758
4759        node = attr.getNamedItem(ATTR_MEMBER_CLASS);
4760        if (node == null)
4761            return null; // missing field class error
4762

4763        Class JavaDoc fieldClass;
4764        try {
4765            fieldClass = getClassFromString(node.getNodeValue());
4766        }
4767        catch (ClassNotFoundException JavaDoc ex) {
4768            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4769            return null; // field class loading error
4770
}
4771
4772        try {
4773            return fieldClass.getField(name);
4774        }
4775        catch (NoSuchFieldException JavaDoc ex) {
4776            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
4777            return null; // field not found error
4778
}
4779    }
4780
4781    // -------
4782

4783    private CodeStructure getCodeStructure() {
4784        return formModel.getCodeStructure();
4785    }
4786
4787    // -------
4788

4789    private Map JavaDoc getExpressionsMap() {
4790        if (expressions == null)
4791            expressions = new HashMap(100);
4792        return expressions;
4793    }
4794
4795    private Map JavaDoc getVariablesMap() {
4796        if (savedVariables == null)
4797            savedVariables = new HashMap(50);
4798        return savedVariables;
4799    }
4800
4801    private Map JavaDoc getComponentsMap() {
4802        if (loadedComponents == null)
4803            loadedComponents = new HashMap(50);
4804        return loadedComponents;
4805    }
4806
4807    // -----------------
4808
// Value encoding and decoding methods
4809

4810    private Object JavaDoc getPropertyEditorOrValue(org.w3c.dom.Node JavaDoc node) {
4811        org.w3c.dom.NamedNodeMap JavaDoc attrs = node.getAttributes();
4812        if (attrs == null)
4813            return NO_VALUE; // no attributes, ignore property
4814

4815        org.w3c.dom.Node JavaDoc typeNode = attrs.getNamedItem(ATTR_PROPERTY_TYPE);
4816        org.w3c.dom.Node JavaDoc editorNode = attrs.getNamedItem(ATTR_PROPERTY_EDITOR);
4817        org.w3c.dom.Node JavaDoc valueNode = attrs.getNamedItem(ATTR_PROPERTY_VALUE);
4818
4819        // get the type of stored property value
4820
if (typeNode == null) {
4821            PersistenceException ex = new PersistenceException(
4822                                        "Missing property type"); // NOI18N
4823
String JavaDoc msg = createLoadingErrorMessage(
4824                FormUtils.getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
4825
node);
4826            ErrorManager.getDefault().annotate(
4827                ex, ErrorManager.ERROR, null, msg, null, null);
4828            nonfatalErrors.add(ex);
4829            return NO_VALUE;
4830        }
4831
4832        Class JavaDoc propertyType = null;
4833        Throwable JavaDoc t = null;
4834        try {
4835            propertyType = getClassFromString(typeNode.getNodeValue());
4836        }
4837        catch (Exception JavaDoc ex) {
4838            t = ex;
4839        }
4840        catch (LinkageError JavaDoc ex) {
4841            t = ex;
4842        }
4843        if (t != null) {
4844            String JavaDoc msg = createLoadingErrorMessage(
4845                FormUtils.getFormattedBundleString("FMT_ERR_CannotLoadClass2", // NOI18N
4846
new Object JavaDoc[] { typeNode.getNodeValue() }),
4847                node);
4848            ErrorManager.getDefault().annotate(t, msg);
4849            nonfatalErrors.add(t);
4850            return NO_VALUE;
4851        }
4852
4853        // load the property editor class and create an instance of it
4854
PropertyEditor prEd = null;
4855        if (editorNode != null) {
4856            Class JavaDoc editorClass = null;
4857            try {
4858                editorClass = PersistenceObjectRegistry.loadClass(
4859                                         editorNode.getNodeValue(), formFile);
4860            }
4861            catch (Exception JavaDoc ex) {
4862                t = ex;
4863            }
4864            catch (LinkageError JavaDoc ex) {
4865                t = ex;
4866            }
4867            if (t != null) {
4868                String JavaDoc msg = createLoadingErrorMessage(
4869                    FormUtils.getFormattedBundleString(
4870                        "FMT_ERR_CannotLoadClass3", // NOI18N
4871
new Object JavaDoc[] { editorNode.getNodeValue() }),
4872                    node);
4873                ErrorManager.getDefault().annotate(t, msg);
4874                nonfatalErrors.add(t);
4875                return NO_VALUE;
4876            }
4877
4878            try {
4879                prEd = createPropertyEditor(editorClass, propertyType, null);
4880            }
4881            catch (Exception JavaDoc ex) {
4882                t = ex;
4883            }
4884            catch (LinkageError JavaDoc ex) {
4885                t = ex;
4886            }
4887            if (t != null) {
4888                String JavaDoc msg = createLoadingErrorMessage(
4889                    FormUtils.getFormattedBundleString(
4890                        "FMT_ERR_CannotCreateInstance2", // NOI18N
4891
new Object JavaDoc[] { editorNode.getNodeValue() }),
4892                    node);
4893                ErrorManager.getDefault().annotate(t, msg);
4894                nonfatalErrors.add(t);
4895                return NO_VALUE;
4896            }
4897        }
4898
4899        // load the property value
4900
Object JavaDoc value = NO_VALUE;
4901        if (valueNode != null) { // it is a primitive value
4902
try {
4903                value = decodePrimitiveValue(valueNode.getNodeValue(),
4904                                             propertyType);
4905                if (prEd != null)
4906                    prEd.setValue(value);
4907            }
4908            catch (IllegalArgumentException JavaDoc ex) {
4909                String JavaDoc msg = createLoadingErrorMessage(
4910                    FormUtils.getFormattedBundleString(
4911                        "FMT_ERR_CannotDecodePrimitive", // NOI18N
4912
new Object JavaDoc[] { valueNode.getNodeValue(),
4913                                       propertyType.getName() }),
4914                    node);
4915                ErrorManager.getDefault().annotate(ex, msg);
4916                nonfatalErrors.add(ex);
4917                return NO_VALUE;
4918            }
4919        }
4920        else { // the value is serialized or saved by XMLPropertyEditor
4921
org.w3c.dom.NodeList JavaDoc children = node.getChildNodes();
4922            int n = children != null ? children.getLength() : 0;
4923            if (n > 0) {
4924                try {
4925                    boolean serialized = false;
4926                    // first try if the value is serialized
4927
for (int i=0; i < n; i++) {
4928                        if (XML_SERIALIZED_PROPERTY_VALUE.equals(
4929                                    children.item(i).getNodeName()))
4930                        { // here is the value serialized in XML
4931
String JavaDoc serValue = getAttribute(children.item(i),
4932                                                        ATTR_PROPERTY_VALUE);
4933                            if (serValue != null) {
4934                                serialized = true;
4935                                value = decodeValue(serValue);
4936                                prEd = null;
4937                            }
4938                            break;
4939                        }
4940                    }
4941
4942                    if (!serialized) {
4943                        if (prEd instanceof XMLPropertyEditor) {
4944                            // the value is saved by XMLPropertyEditor
4945
for (int i=0; i < n; i++) {
4946                                if (children.item(i).getNodeType()
4947                                    == org.w3c.dom.Node.ELEMENT_NODE)
4948                                { // here is the element of stored value
4949
((XMLPropertyEditor)prEd).readFromXML(
4950                                                          children.item(i));
4951                                    value = prEd.getValue();
4952                                    break;
4953                                }
4954                            }
4955                        }
4956                    }
4957                }
4958                catch (Exception JavaDoc ex) {
4959                    t = ex;
4960                }
4961                catch (LinkageError JavaDoc ex) {
4962                    t = ex;
4963                }
4964                if (t != null) {
4965                    String JavaDoc msg = createLoadingErrorMessage(
4966                        FormUtils.getBundleString(
4967                            "MSG_ERR_CannotReadPropertyValue"), // NOI18N
4968
node);
4969                    ErrorManager.getDefault().annotate(t, msg);
4970                    nonfatalErrors.add(t);
4971                    return NO_VALUE;
4972                }
4973            }
4974
4975            if (value == NO_VALUE) { // the value is missing
4976
PersistenceException ex = new PersistenceException(
4977                                           "Missing property value"); // NOI18N
4978
String JavaDoc msg = createLoadingErrorMessage(
4979                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
4980
node);
4981                ErrorManager.getDefault().annotate(
4982                    ex, ErrorManager.ERROR, null, msg, null, null);
4983                nonfatalErrors.add(ex);
4984                return NO_VALUE;
4985            }
4986        }
4987
4988        if (prEd != null)
4989            return prEd;
4990
4991        return value;
4992    }
4993
4994    private /*static */Class JavaDoc getClassFromString(String JavaDoc type)
4995        throws ClassNotFoundException JavaDoc
4996    {
4997        if ("int".equals(type)) // NOI18N
4998
return Integer.TYPE;
4999        else if ("short".equals(type)) // NOI18N
5000
return Short.TYPE;
5001        else if ("byte".equals(type)) // NOI18N
5002
return Byte.TYPE;
5003        else if ("long".equals(type)) // NOI18N
5004
return Long.TYPE;
5005        else if ("float".equals(type)) // NOI18N
5006
return Float.TYPE;
5007        else if ("double".equals(type)) // NOI18N
5008
return Double.TYPE;
5009        else if ("boolean".equals(type)) // NOI18N
5010
return Boolean.TYPE;
5011        else if ("char".equals(type)) // NOI18N
5012
return Character.TYPE;
5013        else {
5014            if (type.startsWith("[")) { // NOI18N
5015
// load array element class first to avoid failure
5016
for (int i=1, n=type.length(); i < n; i++) {
5017                    char c = type.charAt(i);
5018                    if (c == 'L' && type.endsWith(";")) { // NOI18N
5019
String JavaDoc clsName = type.substring(i+1, n-1);
5020                        PersistenceObjectRegistry.loadClass(clsName, formFile);
5021                        break;
5022                    }
5023                    else if (c != '[')
5024                        break;
5025                }
5026            }
5027
5028            return PersistenceObjectRegistry.loadClass(type, formFile);
5029        }
5030    }
5031
5032    /** Decodes a primitive value of given type from the specified String.
5033     * @return decoded value
5034     * @exception IllegalArgumentException thrown if specified object is not
5035     * of supported type
5036     */

5037    private Object JavaDoc decodePrimitiveValue(String JavaDoc encoded, Class JavaDoc type) {
5038        if ("null".equals(encoded)) // NOI18N
5039
return null;
5040
5041        if (Integer JavaDoc.class.isAssignableFrom(type) || Integer.TYPE.equals(type))
5042            return Integer.valueOf(encoded);
5043        if (Short JavaDoc.class.isAssignableFrom(type) || Short.TYPE.equals(type))
5044            return Short.valueOf(encoded);
5045        if (Byte JavaDoc.class.isAssignableFrom(type) || Byte.TYPE.equals(type))
5046            return Byte.valueOf(encoded);
5047        if (Long JavaDoc.class.isAssignableFrom(type) || Long.TYPE.equals(type))
5048            return Long.valueOf(encoded);
5049        if (Float JavaDoc.class.isAssignableFrom(type) || Float.TYPE.equals(type))
5050            return Float.valueOf(encoded);
5051        if (Double JavaDoc.class.isAssignableFrom(type) || Double.TYPE.equals(type))
5052            return Double.valueOf(encoded);
5053        if (Boolean JavaDoc.class.isAssignableFrom(type) || Boolean.TYPE.equals(type))
5054            return Boolean.valueOf(encoded);
5055        if (Character JavaDoc.class.isAssignableFrom(type) || Character.TYPE.equals(type))
5056            return new Character JavaDoc(encoded.charAt(0));
5057        if (String JavaDoc.class.isAssignableFrom(type))
5058            return encoded;
5059
5060        if (Class JavaDoc.class.isAssignableFrom(type)) {
5061            Throwable JavaDoc t;
5062            try {
5063                return PersistenceObjectRegistry.loadClass(encoded, formFile);
5064            }
5065            catch (Exception JavaDoc ex) {
5066                t = ex;
5067            }
5068            catch (LinkageError JavaDoc ex) {
5069                t = ex;
5070            }
5071            IllegalArgumentException JavaDoc ex = new IllegalArgumentException JavaDoc(
5072                                          "Cannot load class: "+encoded); // NOI18N
5073
ErrorManager.getDefault().annotate(ex, t);
5074            throw ex;
5075        }
5076
5077        throw new IllegalArgumentException JavaDoc();
5078    }
5079
5080    /** Encodes specified value into a String. Supported types are: <UL>
5081     * <LI> Class
5082     * <LI> String
5083     * <LI> Integer, Short, Byte, Long, Float, Double, Boolean, Character </UL>
5084     * @return String containing encoded value or null if specified object is not of supported type
5085     */

5086    public static String JavaDoc encodePrimitiveValue(Object JavaDoc value) {
5087        if (value instanceof Integer JavaDoc || value instanceof Short JavaDoc
5088                || value instanceof Byte JavaDoc || value instanceof Long JavaDoc
5089                || value instanceof Float JavaDoc || value instanceof Double JavaDoc
5090                || value instanceof Boolean JavaDoc || value instanceof Character JavaDoc)
5091            return value.toString();
5092
5093        if (value instanceof String JavaDoc)
5094            return (String JavaDoc)value;
5095
5096        if (value instanceof Class JavaDoc)
5097            return ((Class JavaDoc)value).getName();
5098
5099        if (value == null)
5100            return "null"; // NOI18N
5101

5102        return null; // is not a primitive type
5103
}
5104
5105    /** Decodes a value from String containing textual representation of
5106     * serialized stream.
5107     * @return decoded object
5108     * @exception IOException thrown if an error occurres during deserializing
5109     * the object
5110     */

5111    public Object JavaDoc decodeValue(String JavaDoc strValue)
5112        throws IOException, ClassNotFoundException JavaDoc
5113    {
5114        if (strValue == null || strValue.length() == 0)
5115            return null;
5116
5117        char[] bisChars = strValue.toCharArray();
5118        byte[] bytes = new byte[bisChars.length];
5119        StringBuffer JavaDoc singleNum = new StringBuffer JavaDoc();
5120        int count = 0;
5121        for (int i = 0; i < bisChars.length; i++) {
5122            if (',' == bisChars[i]) {
5123                bytes[count++] = Byte.parseByte(singleNum.toString());
5124                singleNum = new StringBuffer JavaDoc();
5125            } else {
5126                singleNum.append(bisChars[i]);
5127            }
5128        }
5129
5130        // add the last byte
5131
bytes[count++] = Byte.parseByte(singleNum.toString());
5132        ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 0, count);
5133        return new OIS(bis).readObject();
5134    }
5135
5136    /** Encodes specified value to a String containing textual representation of serialized stream.
5137     * @return String containing textual representation of the serialized object
5138     */

5139    public static String JavaDoc encodeValue(Object JavaDoc value) throws IOException {
5140        ByteArrayOutputStream bos = new ByteArrayOutputStream();
5141        ObjectOutputStream oos = new ObjectOutputStream(bos);
5142
5143        oos.writeObject(value);
5144        oos.close();
5145
5146        byte[] bosBytes = bos.toByteArray();
5147        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(bosBytes.length*4);
5148        for (int i=0; i < bosBytes.length; i++) {
5149            if (i+1 < bosBytes.length)
5150                buf.append(bosBytes[i]+","); // NOI18N
5151
else
5152                buf.append(""+bosBytes[i]); // NOI18N
5153
}
5154        return buf.toString();
5155    }
5156
5157    // ObjectInputStream subclass for reading serialized property values
5158
private class OIS extends ObjectInputStream {
5159        public OIS(InputStream is) throws IOException {
5160            super(is);
5161        }
5162
5163        protected Class JavaDoc resolveClass(ObjectStreamClass streamCls)
5164            throws IOException, ClassNotFoundException JavaDoc
5165        {
5166            String JavaDoc name = streamCls.getName();
5167            if (name.startsWith("[")) { // NOI18N
5168
// load array element class first to avoid failure
5169
for (int i=1, n=name.length(); i < n; i++) {
5170                    char c = name.charAt(i);
5171                    if (c == 'L' && name.endsWith(";")) { // NOI18N
5172
String JavaDoc clsName = name.substring(i+1, n-1);
5173                        PersistenceObjectRegistry.loadClass(clsName, formFile);
5174                        break;
5175                    }
5176                    else if (c != '[')
5177                        return super.resolveClass(streamCls);
5178                }
5179            }
5180            return PersistenceObjectRegistry.loadClass(name, formFile);
5181        }
5182    }
5183
5184    // --------------------------------------------------------------------------------------
5185
// Utility formatting methods
5186

5187    private static void addElementOpen(StringBuffer JavaDoc buf, String JavaDoc elementName) {
5188        buf.append("<"); // NOI18N
5189
buf.append(elementName);
5190        buf.append(">\n"); // NOI18N
5191
}
5192
5193    private static void addElementOpenAttr(StringBuffer JavaDoc buf,
5194                                           String JavaDoc elementName,
5195                                           String JavaDoc[] attrNames,
5196                                           String JavaDoc[] attrValues)
5197    {
5198        buf.append("<"); // NOI18N
5199
buf.append(elementName);
5200        for (int i = 0; i < attrNames.length; i++) {
5201            if (attrValues[i] == null) continue;
5202            buf.append(" "); // NOI18N
5203
buf.append(attrNames[i]);
5204            buf.append("=\""); // NOI18N
5205
buf.append(encodeToProperXML(attrValues[i]));
5206            buf.append("\""); // NOI18N
5207
}
5208        buf.append(">\n"); // NOI18N
5209
}
5210
5211    private static void addLeafElementOpenAttr(StringBuffer JavaDoc buf,
5212                                               String JavaDoc elementName,
5213                                               String JavaDoc[] attrNames,
5214                                               String JavaDoc[] attrValues)
5215    {
5216        buf.append("<"); // NOI18N
5217
buf.append(elementName);
5218        for (int i = 0; i < attrNames.length; i++) {
5219            if (attrValues[i] == null) continue;
5220            buf.append(" "); // NOI18N
5221
buf.append(attrNames[i]);
5222            buf.append("=\""); // NOI18N
5223
buf.append(encodeToProperXML(attrValues[i]));
5224            buf.append("\""); // NOI18N
5225
}
5226        buf.append("/>\n"); // NOI18N
5227
}
5228
5229    private static void addElementClose(StringBuffer JavaDoc buf, String JavaDoc elementName) {
5230        buf.append("</"); // NOI18N
5231
buf.append(elementName);
5232        buf.append(">\n"); // NOI18N
5233
}
5234
5235    private void saveNodeIntoText(StringBuffer JavaDoc buf, org.w3c.dom.Node JavaDoc valueNode, String JavaDoc indent) {
5236        buf.append(indent);
5237        buf.append("<"); // NOI18N
5238
buf.append(valueNode.getNodeName());
5239
5240        org.w3c.dom.NamedNodeMap JavaDoc attributes = valueNode.getAttributes();
5241
5242        if (attributes != null) {
5243            ArrayList attribList = new ArrayList(attributes.getLength());
5244            for (int i = 0; i < attributes.getLength(); i++) {
5245                attribList.add(attributes.item(i));
5246            }
5247
5248            // sort the attributes by attribute name
5249
// probably not necessary, but there is no guarantee that
5250
// the order of attributes will remain the same in DOM
5251
Collections.sort(attribList, new Comparator() {
5252                public int compare(Object JavaDoc o1, Object JavaDoc o2) {
5253                    org.w3c.dom.Node JavaDoc n1 =(org.w3c.dom.Node JavaDoc)o1;
5254                    org.w3c.dom.Node JavaDoc n2 =(org.w3c.dom.Node JavaDoc)o2;
5255                    return n1.getNodeName().compareTo(n2.getNodeName());
5256                }
5257            }
5258                             );
5259
5260            for (Iterator it = attribList.iterator(); it.hasNext();) {
5261                org.w3c.dom.Node JavaDoc attrNode =(org.w3c.dom.Node JavaDoc)it.next();
5262                String JavaDoc attrName = attrNode.getNodeName();
5263                String JavaDoc attrValue = attrNode.getNodeValue();
5264
5265                buf.append(" "); // NOI18N
5266
buf.append(encodeToProperXML(attrName));
5267                buf.append("=\""); // NOI18N
5268
buf.append(encodeToProperXML(attrValue));
5269                buf.append("\""); // NOI18N
5270
}
5271        }
5272        // [PENDING - CNODES, TEXT NODES, ...]
5273

5274        org.w3c.dom.NodeList JavaDoc children = valueNode.getChildNodes();
5275        if ((children == null) ||(children.getLength() == 0)) {
5276            buf.append("/>\n"); // NOI18N
5277
} else {
5278            buf.append(">\n"); // NOI18N
5279
for (int i = 0; i < children.getLength(); i++) {
5280                if (children.item(i).getNodeType() == org.w3c.dom.Node.TEXT_NODE) continue; // ignore text nodes
5281
saveNodeIntoText(buf, children.item(i), indent + ONE_INDENT);
5282            }
5283            buf.append(indent);
5284            buf.append("</"); // NOI18N
5285
buf.append(encodeToProperXML(valueNode.getNodeName()));
5286            buf.append(">\n"); // NOI18N
5287
}
5288    }
5289
5290    // --------------------------------------------------------------------------------------
5291
// Utility DOM access methods
5292

5293    private static String JavaDoc encodeToProperXML(String JavaDoc text) {
5294        if (text == null)
5295            return ""; // NOI18N
5296

5297        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(text.length());
5298        for (int i=0; i<text.length(); i++) {
5299            char c = text.charAt(i);
5300            if (c >= 0x0020 && c <= 0x007f) {
5301                switch (c) {
5302                    case '&': sb.append("&amp;"); break; // NOI18N
5303
case '<': sb.append("&lt;"); break; // NOI18N
5304
case '>': sb.append("&gt;"); break; // NOI18N
5305
case '\'': sb.append("&apos;"); break; // NOI18N
5306
case '\"': sb.append("&quot;"); break; // NOI18N
5307
default: sb.append(c); break;
5308                }
5309            } else {
5310                sb.append("&#x" + Integer.toHexString(c) + ";"); // NOI18N
5311
}
5312        }
5313
5314        return sb.toString();
5315    }
5316
5317    /** Finds first subnode of given node with specified name.
5318     * @param node the node whose subnode we are looking for
5319