alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.form;

import java.beans.*;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;

import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import org.openide.*;
import org.openide.xml.XMLUtil;

import org.netbeans.modules.form.layoutsupport.*;
import org.netbeans.modules.form.layoutsupport.delegates.*;
import org.netbeans.modules.form.codestructure.*;

import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.modules.javacore.api.JavaModel;
import org.netbeans.jmi.javamodel.Resource;
import org.netbeans.jmi.javamodel.ClassDefinition;

/**
 * XML persistence manager - responsible for saving/loading forms to/from XML.
 * The class contains lots of complicated code with many hacks ensuring full
 * compatibility of the format despite that many original classes already don't
 * exist (e.g. FormInfo and DesignLayout and subclasses).
 *
 * @author Ian Formanek, Tomas Pavek
 */

public class GandalfPersistenceManager extends PersistenceManager {
    static final String NB32_VERSION = "1.0"; // NOI18N
    static final String NB33_VERSION = "1.1"; // NOI18N
    static final String NB34_VERSION = "1.2"; // NOI18N

    // XML elements names
    static final String XML_FORM = "Form"; // NOI18N
    static final String XML_NON_VISUAL_COMPONENTS = "NonVisualComponents"; // NOI18N
    static final String XML_CONTAINER = "Container"; // NOI18N
    static final String XML_COMPONENT = "Component"; // NOI18N
    static final String XML_COMPONENT_REF = "ComponentRef"; // NOI18N
    static final String XML_MENU_COMPONENT = "MenuItem"; // NOI18N
    static final String XML_MENU_CONTAINER = "Menu"; // NOI18N
    static final String XML_LAYOUT = "Layout"; // NOI18N
    static final String XML_LAYOUT_CODE = "LayoutCode"; // NOI18N
    static final String XML_CONSTRAINTS = "Constraints"; // NOI18N
    static final String XML_CONSTRAINT = "Constraint"; // NOI18N
    static final String XML_SUB_COMPONENTS = "SubComponents"; // NOI18N
    static final String XML_EVENTS = "Events"; // NOI18N
    static final String XML_EVENT = "EventHandler"; // NOI18N
    static final String XML_PROPERTIES = "Properties"; // NOI18N
    static final String XML_PROPERTY = "Property"; // NOI18N
    static final String XML_VALUE = "Value"; // NOI18N
    static final String XML_SYNTHETIC_PROPERTY = "SyntheticProperty"; // NOI18N
    static final String XML_SYNTHETIC_PROPERTIES = "SyntheticProperties"; // NOI18N
    static final String XML_AUX_VALUES = "AuxValues"; // NOI18N
    static final String XML_AUX_VALUE = "AuxValue"; // NOI18N
    static final String XML_A11Y_PROPERTIES = "AccessibilityProperties"; // NOI18N
    static final String XML_SERIALIZED_PROPERTY_VALUE = "SerializedValue"; // NOI18N
    static final String XML_CODE_EXPRESSION = "CodeExpression"; // NOI18N
    static final String XML_CODE_VARIABLE = "CodeVariable"; // NOI18N
    static final String XML_CODE_ORIGIN = "ExpressionOrigin"; // NOI18N
    static final String XML_CODE_STATEMENT = "CodeStatement"; // NOI18N
    static final String XML_CODE_PARAMETERS = "Parameters"; // NOI18N
    static final String XML_CODE_STATEMENTS = "Statements"; // NOI18N
    static final String XML_ORIGIN_META_OBJECT = "ExpressionProvider"; // NOI18N
    static final String XML_STATEMENT_META_OBJECT = "StatementProvider"; // NOI18N
    static final String XML_CODE_CONSTRUCTOR = "CodeConstructor"; // NOI18N
    static final String XML_CODE_METHOD = "CodeMethod"; // NOI18N
    static final String XML_CODE_FIELD = "CodeField"; // NOI18N

    // XML attributes names
    static final String ATTR_FORM_VERSION = "version"; // NOI18N
    static final String ATTR_FORM_TYPE = "type"; // NOI18N
    static final String ATTR_COMPONENT_NAME = "name"; // NOI18N
    static final String ATTR_COMPONENT_CLASS = "class"; // NOI18N
    static final String ATTR_PROPERTY_NAME = "name"; // NOI18N
    static final String ATTR_PROPERTY_TYPE = "type"; // NOI18N
    static final String ATTR_PROPERTY_EDITOR = "editor"; // NOI18N
    static final String ATTR_PROPERTY_VALUE = "value"; // NOI18N
    static final String ATTR_PROPERTY_PRE_CODE = "preCode"; // NOI18N
    static final String ATTR_PROPERTY_POST_CODE = "postCode"; // NOI18N
    static final String ATTR_EVENT_NAME = "event"; // NOI18N
    static final String ATTR_EVENT_LISTENER = "listener"; // NOI18N
    static final String ATTR_EVENT_PARAMS = "parameters"; // NOI18N
    static final String ATTR_EVENT_HANDLER = "handler"; // NOI18N
    static final String ATTR_AUX_NAME = "name"; // NOI18N
    static final String ATTR_AUX_VALUE = "value"; // NOI18N
    static final String ATTR_AUX_VALUE_TYPE = "type"; // NOI18N
    static final String ATTR_LAYOUT_CLASS = "class"; // NOI18N
    static final String ATTR_CONSTRAINT_LAYOUT = "layoutClass"; // NOI18N
    static final String ATTR_CONSTRAINT_VALUE = "value"; // NOI18N
    static final String ATTR_EXPRESSION_ID = "id"; // NOI18N
    static final String ATTR_VAR_NAME = "name"; // NOI18N
    static final String ATTR_VAR_TYPE = "type"; // NOI18N
    static final String ATTR_VAR_DECLARED_TYPE = "declaredType"; // NOI18N
    static final String ATTR_META_OBJECT_TYPE = "type"; // NOI18N
    static final String ATTR_MEMBER_CLASS = "class"; // NOI18N
    static final String ATTR_MEMBER_PARAMS = "parameterTypes"; // NOI18N
    static final String ATTR_MEMBER_NAME = "name"; // NOI18N

    private static final String ONE_INDENT =  "  "; // NOI18N
    private static final Object NO_VALUE = new Object();

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

    private FileObject formFile;

    private FormModel formModel;

    private List nonfatalErrors;

    // map of properties that cannot be loaded before a container is filled
    private Map containerDependentProperties;

    // map of loaded components (not necessarily added to FormModel yet)
    private Map loadedComponents;

    // XML persistence of code structure
    private Map expressions; // map of expressions/IDs already saved/loaded
    private int lastExpId; // CodeExpression ID counter (for saving)
    private Map savedVariables; // set of code variables already saved
    private boolean codeFlow = true; // we can save/load either code flow
                                     // or static code structure

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


    /** This method is used to check if the persistence manager can read the
     * given form (if it understands the form file format).
     * @return true if this persistence manager can load the form
     * @exception PersistenceException if any unexpected problem occurred
     */
    public boolean canLoadForm(FormDataObject formObject)
        throws PersistenceException
    {
        FileObject formFile = formObject.getFormEntry().getFile();
        org.w3c.dom.Element mainElement;
        try {
            org.w3c.dom.Document doc = XMLUtil.parse(
                new org.xml.sax.InputSource(formFile.getURL().toExternalForm()),
                false, false, null, null);

            mainElement = doc.getDocumentElement();
        }
        catch (IOException ex) {
            throw new PersistenceException(ex, "Cannot open form file"); // NOI18N
        }
        catch (org.xml.sax.SAXException e) {
            // ignore SAXException?
            e.printStackTrace();
            return false;
        }

        return mainElement != null && XML_FORM.equals(mainElement.getTagName());
    }

    /** This method loads the form from given data object.
     * @param formObject FormDataObject representing the form files
     * @param formModel FormModel to be filled with loaded data
     * @param nonfatalErrors List to be filled with errors occurred during
     *        loading which are not fatal (but should be reported)
     * @exception PersistenceException if some fatal problem occurred which
     *            prevents loading the form
     */
    public void loadForm(FormDataObject formObject,
                         FormModel formModel,
                         List nonfatalErrors)
        throws PersistenceException
    {
        FileObject formFile = formObject.getFormEntry().getFile();

        org.w3c.dom.Element mainElement;
        try { // parse document, get the main element
            mainElement = XMLUtil.parse(new org.xml.sax.InputSource(
                                            formFile.getURL().toExternalForm()),
                                        false, false, null, null)
                          .getDocumentElement();
        }
        catch (IOException ex) {
            PersistenceException pe = new PersistenceException(
                                          ex, "Cannot open form file"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                FormUtils.getBundleString("MSG_ERR_LoadingErrors")); // NOI18N
            throw pe;
        }
        catch (org.xml.sax.SAXException ex) {
            PersistenceException pe = new PersistenceException(
                                          ex, "Invalid XML in form file"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex, 
                FormUtils.getBundleString("MSG_ERR_InvalidXML")); // NOI18N
            throw pe;
        }

        // check the main element
        if (mainElement == null || !XML_FORM.equals(mainElement.getTagName())) {
            PersistenceException ex = new PersistenceException(
                            "Missing expected main XML element"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                ErrorManager.ERROR,
                null,
                FormUtils.getBundleString("MSG_ERR_MissingMainElement"), // NOI18N
                null,
                null);
            throw ex;
        }

        // check the form version
        if (!isSupportedFormatVersion(mainElement.getAttribute(ATTR_FORM_VERSION))) {
            PersistenceException ex = new PersistenceException(
                                     "Unsupported form version"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                ErrorManager.ERROR,
                null,
                FormUtils.getFormattedBundleString(
                    "FMT_ERR_UnsupportedVersion", // NOI18N
                    new Object[] { mainElement.getAttribute(ATTR_FORM_VERSION) }),
                null,
                null);
            throw ex;
        }

        // --------
        // get the form base class and set it to FormModel
        String declaredSuperclassName = null;
        Class formBaseClass = null;
        Throwable formBaseClassEx = null;

        // get the formerly used FormInfo type (to be used as fallback alternative)
        String formInfoName = mainElement.getAttribute(ATTR_FORM_TYPE);
        if ("".equals(formInfoName)) // NOI18N
            formInfoName = null; // not available

        try { // try declared superclass from java source first
            FileObject javaFile = formObject.getPrimaryFile();
            ClassPath classPath = ClassPath.getClassPath(javaFile, ClassPath.SOURCE);
            Resource resource = JavaModel.getResource(classPath.findOwnerRoot(javaFile),
                classPath.getResourceName(javaFile));
            List classifiers = resource.getClassifiers();
            Iterator classIter = classifiers.iterator();
            
            while (classIter.hasNext()) {
                ClassDefinition javaClass = (ClassDefinition)classIter.next();
                String className = javaClass.getName();
                int dotIndex = className.lastIndexOf('.');
                className = (dotIndex == -1) ? className : className.substring(dotIndex+1);
                if (className.equals(formObject.getName())) {
                    declaredSuperclassName = javaClass.getSuperClass().getName();
                    break;
                }
            }
            
            Class superclass = (declaredSuperclassName != null) ?
                FormUtils.loadClass(declaredSuperclassName, formFile) : Object.class;
            formBaseClass = checkDeclaredSuperclass(superclass, formInfoName);

            if (formBaseClass != superclass)
                System.err.println(FormUtils.getFormattedBundleString(
                    "FMT_IncompatibleFormTypeWarning", // NOI18N
                    new Object[] { formObject.getName() }));

            formModel.setFormBaseClass(formBaseClass);
        }
        catch (Exception ex) {
            formBaseClassEx = ex;
        }
        catch (LinkageError ex) {
            formBaseClassEx = ex;
        }

        if (formModel.getFormBaseClass() == null) {
            // using superclass declared in java source failed, so try to use
            // some well-known substitute class instead
            Class substClass = null;

            if (formBaseClass != null) // try to honor the declared superclass
                substClass = getCompatibleFormClass(formBaseClass);
 
            if (substClass == null && formInfoName != null) // fall back to FormInfo type
                substClass = getCompatibleFormClass(formInfoName);

            if (substClass != null) { // succeeded, there is a substitute class
                try {
                    formModel.setFormBaseClass(substClass);

                    // print a warning about using fallback type
                    String msg = FormUtils.getFormattedBundleString(
                        "FMT_FormTypeWarning", // NOI18N
                        new Object[] { formObject.getName(),
                                       substClass.getName(),
                                       declaredSuperclassName != null ?
                                         declaredSuperclassName : "" }); // NOI18N
                    System.err.println(msg);
                    if (formBaseClassEx != null)
                        formBaseClassEx.printStackTrace();
                }
                catch (Exception ex) { // should not happen for the substitute types
                    ex.printStackTrace();
                }
                catch (LinkageError ex) { // should not happen for the substitute types
                    ex.printStackTrace();
                }
            }

            if (formModel.getFormBaseClass() == null) {
                // after all, we still cannot determine the form base class
                String annotation;
                if (declaredSuperclassName != null) {
                    // the class from java source at least can be loaded, but
                    // cannot be used as the form type; no substitute available
                    annotation = FormUtils.getFormattedBundleString(
                                     "FMT_ERR_InvalidBaseClass", // NOI18N
                                     new Object[] { declaredSuperclassName });
                }
                else { // cannot determine form base class at all;
                       // no substitute available
                    annotation = FormUtils.getBundleString(
                         "MSG_ERR_CannotDetermineBaseClass"); // NOI18N
                }

                PersistenceException ex;
                if (formBaseClassEx != null) {
                    ex = new PersistenceException(formBaseClassEx,
                                                  "Invalid form base class"); // NOI18N
                    ErrorManager.getDefault().annotate(formBaseClassEx,
                                                       annotation);
                }
                else {
                    ex = new PersistenceException("Invalid form base class"); // NOI18N
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, annotation, null, null);
                }
                throw ex;
            }
        }
        // base class set
        // ---------

        // initial cleanup
        if (loadedComponents != null)
            loadedComponents.clear();
        if (expressions != null)
            expressions.clear();
        containerDependentProperties = null;

        this.formFile = formFile;
        this.formModel = formModel;
        this.nonfatalErrors = nonfatalErrors;

        formModel.setName(formObject.getName());

        // load "Other Components" first
        loadNonVisuals(mainElement);

        RADComponent topComp = formModel.getTopRADComponent();
        if (topComp != null) // load the main form component
            loadComponent(mainElement, topComp, null);

        // final cleanup
        containerDependentProperties = null;
        if (expressions != null)
            expressions.clear();
        if (loadedComponents != null)
            loadedComponents.clear();
        this.formModel = null;
    }

    private void loadNonVisuals(org.w3c.dom.Node node) {
        org.w3c.dom.Node nonVisualsNode =
                                findSubNode(node, XML_NON_VISUAL_COMPONENTS);
        org.w3c.dom.NodeList childNodes = nonVisualsNode == null ? null :
                                          nonVisualsNode.getChildNodes();
        ArrayList list = new ArrayList();

        if (childNodes != null) {
            for (int i = 0; i < childNodes.getLength(); i++) {
                org.w3c.dom.Node subnode = childNodes.item(i);
                if (subnode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                    continue; // ignore text nodes

                RADComponent comp = restoreComponent(subnode, null);
                if (comp != null)
                    list.add(comp);
            }
        }

        RADComponent[] nonVisualComps = new RADComponent[list.size()];
        list.toArray(nonVisualComps);
        formModel.getModelContainer().initSubComponents(nonVisualComps);
    }

    // recognizes, creates, initializes and loads a meta component
    private RADComponent restoreComponent(org.w3c.dom.Node node,
                                          RADComponent parentComponent)
    {
        org.w3c.dom.NamedNodeMap attrs = node.getAttributes();
        if (attrs == null) { // should not be null even if there are no attributes
            PersistenceException ex = new PersistenceException(
                      "Missing attributes of component element"); // NOI18N
            nonfatalErrors.add(ex);
            return null;
        }

        org.w3c.dom.Node classNode = attrs.getNamedItem(ATTR_COMPONENT_CLASS);
        org.w3c.dom.Node nameNode = attrs.getNamedItem(ATTR_COMPONENT_NAME);
        String className = classNode != null ? classNode.getNodeValue() : null;
        String compName = nameNode != null ? nameNode.getNodeValue() : null;

        if (className == null) {
            PersistenceException ex = new PersistenceException(
                                 "Missing component class name"); // NOI18N
            String msg = createLoadingErrorMessage(
                           FormUtils.getBundleString("MSG_ERR_MissingClass"), // NOI18N
                                                     node);
            ErrorManager.getDefault().annotate(
                ex, ErrorManager.ERROR, null, msg, null, null);
            nonfatalErrors.add(ex);
            return null;
        }

        // first load the component class
        Class compClass = null;
        Throwable compEx = null;
        try {
            compClass = PersistenceObjectRegistry.loadClass(className, formFile);
        }
        catch (Exception ex) {
            compEx = ex;
        }
        catch (LinkageError ex) {
            compEx = ex;
        }
        if (compEx != null) { // loading the component class failed
            String msg = createLoadingErrorMessage(
                FormUtils.getFormattedBundleString("FMT_ERR_CannotLoadClass", // NOI18N
                                                   new Object[] { className }),
                node);
            ErrorManager.getDefault().annotate(compEx, msg);
            nonfatalErrors.add(compEx);
            return null;
        }

        // create a new metacomponent
        RADComponent newComponent;
        String nodeName = node.getNodeName();

        if (XML_COMPONENT.equals(nodeName)) {
            if (java.awt.Component.class.isAssignableFrom(compClass))
                newComponent = new RADVisualComponent();
            else newComponent = new RADComponent();
        }
        else if (XML_MENU_COMPONENT.equals(nodeName)) {
            newComponent = new RADMenuItemComponent();
        }
        else if (XML_MENU_CONTAINER.equals(nodeName)) {
            newComponent = new RADMenuComponent();
        }
        else if (XML_CONTAINER.equals(nodeName)) {
            if (java.awt.Container.class.isAssignableFrom(compClass))
                newComponent = new RADVisualContainer();
            else newComponent = new RADContainer();
        }
        else {
            PersistenceException ex = new PersistenceException(
                                    "Unknown component element"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                ErrorManager.ERROR,
                null,
                FormUtils.getFormattedBundleString("FMT_ERR_UnknownElement", // NOI18N
                                                   new Object[] { nodeName }),
                null,
                null);
            nonfatalErrors.add(ex);
            return null;
        }

        // initialize the metacomponent
        try {
            newComponent.initialize(formModel);
            newComponent.initInstance(compClass);
            newComponent.setInModel(true);
            newComponent.setName(compName);
        }
        catch (Exception ex) {
            compEx = ex;
        }
        catch (LinkageError ex) {
            compEx = ex;
        }
        if (compEx != null) { // creating component instance failed
            String msg = createLoadingErrorMessage(
                FormUtils.getFormattedBundleString("FMT_ERR_CannotCreateInstance", // NOI18N
                                                   new Object[] { className }),
                node);
            ErrorManager.getDefault().annotate(compEx, msg);
            nonfatalErrors.add(compEx);
            return null;
        }

        getComponentsMap().put(compName, newComponent);

        // load the metacomponent (properties, events, layout, etc)
        loadComponent(node, newComponent, parentComponent);

        return newComponent;
    }

    private void loadComponent(org.w3c.dom.Node node,
                               RADComponent component,
                               RADComponent parentComponent)
    {
        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes == null)
            return;

        org.w3c.dom.Node layoutNode = null;
        org.w3c.dom.Node layoutCodeNode = null;
        org.w3c.dom.Node subCompsNode = null;
        org.w3c.dom.Node constraintsNode = null;

        for (int i = 0; i < childNodes.getLength(); i++) {
            org.w3c.dom.Node childNode = childNodes.item(i);
            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                continue; // ignore text nodes

            String nodeName = childNode.getNodeName();

            if (XML_PROPERTIES.equals(nodeName)
                || XML_A11Y_PROPERTIES.equals(nodeName))
            {
                loadComponentProperties(childNode, component, nodeName);
            }
            else if (XML_EVENTS.equals(nodeName)) {
                loadEvents(childNode, component);
            }
            else if (XML_CONSTRAINTS.equals(nodeName)) {
                constraintsNode = childNode;
            }
            else if (XML_LAYOUT.equals(nodeName)) {
                if (layoutCodeNode == null)
                    layoutNode = childNode;
            }
            else if (XML_LAYOUT_CODE.equals(nodeName)) {
                layoutCodeNode = childNode;
                layoutNode = null;
            }
            else if (XML_SUB_COMPONENTS.equals(nodeName)) {
                subCompsNode = childNode;
            }
            else if (XML_AUX_VALUES.equals(nodeName)) {
                loadAuxValues(childNode, component);
            }
            else if (XML_SYNTHETIC_PROPERTIES.equals(nodeName)) {
                loadSyntheticProperties(childNode, component);
            }
            // ignore unknown elements?
        }

        // if the loaded component is a visual component in a visual contianer,
        // then load NB 3.1 layout constraints for it
        if (component instanceof RADVisualComponent
            && parentComponent instanceof RADVisualContainer
            && layoutConvIndex != LAYOUT_FROM_CODE)
        {
            CodeExpression compExp = component.getCodeExpression();
            LayoutSupportManager layoutSupport =
                ((RADVisualContainer)parentComponent).getLayoutSupport();

            org.w3c.dom.Node[] constrNodes = constraintsNode != null ?
                findSubNodes(constraintsNode, XML_CONSTRAINT) : null;

            boolean constraintsLoaded = false;

            if (constrNodes != null && constrNodes.length > 0) {
                // NB 3.1 used to save all constraints ever set. We must
                // go through all of them, but only those of current layout
                // will be loaded.
                for (int i=0; !constraintsLoaded && i < constrNodes.length; i++)
                    constraintsLoaded = loadConstraints(constrNodes[i],
                                                        compExp,
                                                        layoutSupport);
            }

            if (!constraintsLoaded)
                setupDefaultComponentCode(compExp, layoutSupport);
        }

        ComponentContainer container = // is this component a container?
                component instanceof ComponentContainer ?
                       (ComponentContainer) component : null;
        if (container == null)
            return; // this component is not a container

        // we continue in loading container

        RADVisualContainer visualContainer = // is it a visual container?
                component instanceof RADVisualContainer ?
                        (RADVisualContainer) component : null;

        int convIndex = LAYOUT_FROM_CODE;
        if (visualContainer != null && layoutNode != null) {
            // load container layout properties saved in NB 3.1 format;
            // these properties are loaded before subcomponents
            convIndex = loadLayout(layoutNode,
                                   visualContainer.getLayoutSupport());
        }

        // load subcomponents
        RADComponent[] childComponents;
        childNodes = subCompsNode != null ?
                     subCompsNode.getChildNodes() : null;
        if (childNodes != null) {
            ArrayList list = new ArrayList();
            for (int i=0, n=childNodes.getLength(); i < n; i++) {
                org.w3c.dom.Node componentNode = childNodes.item(i);
                if (componentNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                    continue; // ignore text nodes

                // hack for dealing with multiple constraints saved by NB 3.1
                layoutConvIndex = convIndex;

                RADComponent newComp = restoreComponent(componentNode, component);

                if (newComp != null)
                    list.add(newComp);
            }

            childComponents = new RADComponent[list.size()];
            list.toArray(childComponents);
        }
        else childComponents = new RADComponent[0];

        if (visualContainer != null && layoutCodeNode != null) {
            // load complete layout code (both for container and components);
            // this container doesn't use NB 3.1 format for saving layout data
            loadLayoutCode(layoutCodeNode);
        }

        // initialize layout support from restored code
        if (visualContainer != null) {
            LayoutSupportManager layoutSupport =
                                   visualContainer.getLayoutSupport();
            boolean layoutInitialized = false;
            boolean unknownLayout = layoutNode != null && convIndex < 0
                                    && layoutCodeNode == null;
            Throwable layoutEx = null;

            
            if (!unknownLayout)
                try {
                    layoutInitialized =
                        layoutSupport.initializeLayoutDelegate(true);
                }
                catch (Exception ex) {
                    layoutEx = ex;
                }
                catch (LinkageError ex) {
                    layoutEx = ex;
                }

            if (!layoutInitialized) {
                if (layoutEx != null) { // no LayoutSupportDelegate found
                    org.w3c.dom.Node errNode;
                    if (layoutNode != null)
                        errNode = layoutNode;
                    else if (layoutCodeNode != null)
                        errNode = layoutCodeNode;
                    else
                        errNode = node;

                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_LayoutInitFailed"), // NOI18N
                        errNode);
                    ErrorManager.getDefault().annotate(layoutEx, msg);
                    nonfatalErrors.add(layoutEx);
                }
                else { // layout initialization failed
                    org.w3c.dom.Node errNode;
                    if (layoutNode != null)
                        errNode = layoutNode;
                    else if (layoutCodeNode != null)
                        errNode = layoutCodeNode;
                    else
                        errNode = node;

                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString(
                            "MSG_ERR_NoLayoutSupportFound"), // NOI18N
                        errNode);

                    PersistenceException ex = new PersistenceException(
                                              "No layout support found"); // NOI18N
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, msg, null, null);
                    nonfatalErrors.add(ex);
                }
                layoutSupport.setUnknownLayoutDelegate(true);
            }

            visualContainer.initSubComponents(childComponents);
            visualContainer.getLayoutSupport().updatePrimaryContainer();
        }
        else // non-visual container
            container.initSubComponents(childComponents);

        // hack for properties that can't be set until all subcomponents
        // are added to the container
        List postProps;
        if (containerDependentProperties != null
            && (postProps = (List) containerDependentProperties
                                       .get(component)) != null)
        {
            for (Iterator it = postProps.iterator(); it.hasNext(); ) {
                RADProperty prop = (RADProperty) it.next();
                Object propValue = it.next();
                try {
                    prop.setValue(propValue);
                }
                catch (Exception ex) { // ignore
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
                        node);
                    ErrorManager.getDefault().annotate(ex, msg);
                    nonfatalErrors.add(ex);
                }
            }
        }
    }

    private boolean loadConstraints(org.w3c.dom.Node node,
                                    CodeExpression compExp,
                                    LayoutSupportManager layoutSupport)
    {
        int convIndex = -1;
        String layout31ConstraintName = node != null ?
                   getAttribute(node, ATTR_CONSTRAINT_VALUE) : null;
        if (layout31ConstraintName != null)
            for (int i=0; i < layout31ConstraintsNames.length; i++)
                if (layout31ConstraintName.equals(layout31ConstraintsNames[i])) {
                    convIndex = i;
                    break;
                }

        // skip constraints saved by NB 3.1 which are not for the current layout
        if (convIndex < 0
                || (layoutConvIndex >= 0 && convIndex != layoutConvIndex))
            return false;

        org.w3c.dom.Node constrNode = null;
        org.w3c.dom.NamedNodeMap constrAttr = null;

        if (/*convIndex >= 0 &&*/reasonable31Constraints[convIndex]) {
            org.w3c.dom.NodeList children = node.getChildNodes();
            if (children != null)
                for (int i=0, n=children.getLength(); i < n; i++) {
                    org.w3c.dom.Node cNode = children.item(i);
                    if (cNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        constrNode = cNode;
                        constrAttr = cNode.getAttributes();
                        break;
                    }
                }
        }

        if (constrNode == null)
            return false;

        try { // obligatory try/catch block for finding methods and constructors

        CodeStructure codeStructure = layoutSupport.getCodeStructure();
        CodeExpression contCodeExp = layoutSupport.getContainerCodeExpression();
        CodeExpression contDelCodeExp =
            layoutSupport.getContainerDelegateCodeExpression();

        if (convIndex == LAYOUT_BORDER) {
            if (!"BorderConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false; // should not happen

            node = constrAttr.getNamedItem("direction"); // NOI18N
            if (node != null) {
                String strValue = node.getNodeValue();
                // create add method statement
                CodeStructure.createStatement(
                    contDelCodeExp,
                    getAddWithConstrMethod(),
                    new CodeExpression[] { compExp,
                                           codeStructure.createExpression(
                                                           String.class,
                                                           strValue,
                                                           strValue) });
            }
        }

        else if (convIndex == LAYOUT_GRIDBAG) {
            if (!"GridBagConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false; // should not happen

            // create GridBagConstraints constructor expression
            if (gridBagConstrConstructor == null)
                gridBagConstrConstructor =
                    java.awt.GridBagConstraints.class.getConstructor(
                                                          new Class[0]);

            CodeExpression constrExp = codeStructure.createExpression(
                    gridBagConstrConstructor, CodeStructure.EMPTY_PARAMS);

            // create statements for GridBagConstraints fields
            String[] gbcAttrs = new String[] {
                "gridX", "gridY", "gridWidth", "gridHeight", // NOI18N
                "fill", "ipadX", "ipadY", // NOI18N
                "anchor", "weightX", "weightY" }; // NOI18N
            String[] gbcFields = new String[] {
                "gridx", "gridy", "gridwidth", "gridheight", // NOI18N
                "fill", "ipadx", "ipady", // NOI18N
                "anchor", "weightx", "weighty" }; // NOI18N

            for (int i=0; i < gbcAttrs.length; i++) {
                node = constrAttr.getNamedItem(gbcAttrs[i]);
                if (node != null) {
                    Class valueType;
                    Object value;
                    String strValue = node.getNodeValue();
                    if (i < 8) { // treat as int
                        valueType = Integer.TYPE;
                        value = Integer.valueOf(strValue);
                    }
                    else { // treat as double
                        valueType = Double.TYPE;
                        value = Double.valueOf(strValue);
                    }

                    CodeStructure.createStatement(
                        constrExp,
                        java.awt.GridBagConstraints.class.getField(gbcFields[i]),
                        codeStructure.createExpression(valueType, value, strValue));
                }
            }

            // Insets
            CodeExpression[] insetsParams = new CodeExpression[4];
            String[] insetsAttrs = new String[] {
                "insetsTop", "insetsLeft", "insetsBottom", "insetsRight" }; // NOI18N

            for (int i=0; i < insetsAttrs.length; i++) {
                node = constrAttr.getNamedItem(insetsAttrs[i]);
                String strValue = node != null ? node.getNodeValue() : "0"; // NOI18N
                insetsParams[i] = codeStructure.createExpression(
                                                    Integer.TYPE,
                                                    Integer.valueOf(strValue),
                                                    strValue);
            }

            if (insetsConstructor == null)
                insetsConstructor = java.awt.Insets.class.getConstructor(
                    new Class[] { Integer.TYPE, Integer.TYPE,
                                  Integer.TYPE, Integer.TYPE });

            CodeStructure.createStatement(
                          constrExp,
                          java.awt.GridBagConstraints.class.getField("insets"), // NOI18N
                          codeStructure.createExpression(insetsConstructor,
                                                         insetsParams));

            // create add method statement
            CodeStructure.createStatement(
                contDelCodeExp,
                getAddWithConstrMethod(),
                new CodeExpression[] { compExp, constrExp });
        }

        else if (convIndex == LAYOUT_JTAB) {
            if (!"JTabbedPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false; // should not happen

            Object tabName = null;
            PropertyEditor tabNamePropEd = null;
            Object toolTip = null;
            PropertyEditor toolTipPropEd = null;
            Object icon = null;
            PropertyEditor iconPropEd = null;

            org.w3c.dom.Node[] propNodes = findSubNodes(constrNode, XML_PROPERTY);
            if (propNodes != null)
                for (int i=0; i < propNodes.length; i++) {
                    Object editorOrValue = getPropertyEditorOrValue(propNodes[i]);
                     if (editorOrValue == NO_VALUE)
                         continue;

                    PropertyEditor prEd = null;
                    Object value = null;
                    if (editorOrValue instanceof PropertyEditor)
                        prEd = (PropertyEditor) editorOrValue;
                    else
                        value = editorOrValue;

                    String name = getAttribute(propNodes[i], ATTR_PROPERTY_NAME);
                    if ("tabTitle".equals(name)) { // NOI18N
                        tabName = value;
                        tabNamePropEd = prEd;
                    }
                    else if ("tabToolTip".equals(name)) { // NOI18N
                        toolTip = value;
                        toolTipPropEd = prEd;
                    }
                    else if ("tabIcon".equals(name)) { // NOI18N
                        icon = value;
                        iconPropEd = prEd;
                    }
                }

            if (tabName == null
                    && (node = constrAttr.getNamedItem("tabName")) != null) // NOI18N
                tabName = node.getNodeValue();
            if (toolTip == null
                    && (node = constrAttr.getNamedItem("toolTip")) != null) // NOI18N
                toolTip = node.getNodeValue();

            if (toolTip != null || toolTipPropEd != null) {
                if (addTabMethod1 == null)
                    addTabMethod1 = javax.swing.JTabbedPane.class.getMethod(
                                    "addTab", // NOI18N
                                    new Class[] { String.class,
                                                  javax.swing.Icon.class,
                                                  java.awt.Component.class,
                                                  String.class });
                CodeStructure.createStatement(
                    contCodeExp,
                    addTabMethod1,
                    new CodeExpression[] { 
                        createExpressionForProperty(
                            codeStructure, String.class, tabName, tabNamePropEd),
                        createExpressionForProperty(
                            codeStructure, javax.swing.Icon.class, icon, iconPropEd),
                        compExp,
                        createExpressionForProperty(
                            codeStructure, String.class, toolTip, toolTipPropEd) });
            }
            else if (icon != null || iconPropEd != null) {
                if (addTabMethod2 == null)
                    addTabMethod2 = javax.swing.JTabbedPane.class.getMethod(
                                    "addTab", // NOI18N
                                    new Class[] { String.class,
                                                  javax.swing.Icon.class,
                                                  java.awt.Component.class });
                CodeStructure.createStatement(
                    contCodeExp,
                    addTabMethod2,
                    new CodeExpression[] {
                        createExpressionForProperty(
                            codeStructure, String.class, tabName, tabNamePropEd),
                        createExpressionForProperty(
                            codeStructure, javax.swing.Icon.class, icon, iconPropEd),
                        compExp });
            }
            else {
                if (addTabMethod3 == null)
                    addTabMethod3 = javax.swing.JTabbedPane.class.getMethod(
                                    "addTab", // NOI18N
                                    new Class[] { String.class,
                                                  java.awt.Component.class });
                CodeStructure.createStatement(
                    contCodeExp,
                    addTabMethod3,
                    new CodeExpression[] {
                        createExpressionForProperty(
                            codeStructure, String.class, tabName, tabNamePropEd),
                        compExp });
            }
        }

        else if (convIndex == LAYOUT_JSPLIT) {
            if (!"JSplitPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false;

            node = constrAttr.getNamedItem("position"); // NOI18N
            if (node != null) {
                String position = node.getNodeValue();
                Method addMethod;

                if ("top".equals(position)) { // NOI18N
                    if (setTopComponentMethod == null)
                        setTopComponentMethod =
                            javax.swing.JSplitPane.class.getMethod(
                                    "setTopComponent", // NOI18N
                                    new Class[] { java.awt.Component.class });
                    addMethod = setTopComponentMethod;
                }
                else if ("bottom".equals(position)) { // NOI18N
                    if (setBottomComponentMethod == null)
                        setBottomComponentMethod =
                            javax.swing.JSplitPane.class.getMethod(
                                    "setBottomComponent", // NOI18N
                                    new Class[] { java.awt.Component.class });
                    addMethod = setBottomComponentMethod;
                }
                else if ("left".equals(position)) { // NOI18N
                    if (setLeftComponentMethod == null)
                        setLeftComponentMethod =
                            javax.swing.JSplitPane.class.getMethod(
                                    "setLeftComponent", // NOI18N
                                    new Class[] { java.awt.Component.class });
                    addMethod = setLeftComponentMethod;
                }
                else if ("right".equals(position)) { // NOI18N
                    if (setRightComponentMethod == null)
                        setRightComponentMethod =
                            javax.swing.JSplitPane.class.getMethod(
                                    "setRightComponent", // NOI18N
                                    new Class[] { java.awt.Component.class });
                    addMethod = setRightComponentMethod;
                }
                else return false;

                CodeStructure.createStatement(contCodeExp,
                                              addMethod,
                                              new CodeExpression[] { compExp });
            }
        }

        else if (convIndex == LAYOUT_CARD) {
            if (!"CardConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false;

            node = constrAttr.getNamedItem("cardName"); // NOI18N
            if (node != null) {
                String strValue = node.getNodeValue();
                // create add method statement
                CodeStructure.createStatement(
                    contDelCodeExp,
                    getAddWithConstrMethod(),
                    new CodeExpression[] { compExp,
                                           codeStructure.createExpression(
                                                           String.class,
                                                           strValue,
                                                           strValue) });
            }
        }

        else if (convIndex == LAYOUT_JLAYER) {
            if (!"JLayeredPaneConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false;

            CodeExpression[] boundsParams = new CodeExpression[4];
            String[] boundsAttrs = new String[] { "x", "y", "width", "height" }; // NOI18N

            for (int i=0; i < boundsAttrs.length; i++) {
                node = constrAttr.getNamedItem(boundsAttrs[i]);
                String strValue = node != null ?
                                      node.getNodeValue() :
                                      (i < 2 ? "0" : "-1"); // NOI18N
                boundsParams[i] = codeStructure.createExpression(
                                                    Integer.TYPE,
                                                    Integer.valueOf(strValue),
                                                    strValue);
            }

            if (setBoundsMethod == null)
                setBoundsMethod = java.awt.Component.class.getMethod(
                                    "setBounds", // NOI18N
                                    new Class[] { Integer.TYPE, Integer.TYPE,
                                                  Integer.TYPE, Integer.TYPE });
            CodeStructure.createStatement(
                            compExp, setBoundsMethod, boundsParams);

            node = constrAttr.getNamedItem("layer"); // NOI18N
            if (node != null) {
                String strValue = node.getNodeValue();
                // create add method statement
                CodeStructure.createStatement(
                    contDelCodeExp,
                    getAddWithConstrMethod(),
                    new CodeExpression[] { compExp,
                                           codeStructure.createExpression(
                                               Integer.TYPE,
                                               Integer.valueOf(strValue),
                                               strValue) });
            }
        }

        else if (convIndex == LAYOUT_ABSOLUTE) {
            if (!"AbsoluteConstraints".equals(constrNode.getNodeName())) // NOI18N
                return false;

            CodeExpression[] boundsParams = new CodeExpression[4];
            String[] boundsAttrs = new String[] { "x", "y", "width", "height" }; // NOI18N

            for (int i=0; i < boundsAttrs.length; i++) {
                node = constrAttr.getNamedItem(boundsAttrs[i]);
                String strValue = node != null ?
                                      node.getNodeValue() :
                                      (i < 2 ? "0" : "-1"); // NOI18N
                boundsParams[i] = codeStructure.createExpression(
                                                    Integer.TYPE,
                                                    Integer.valueOf(strValue),
                                                    strValue);
            }

            Iterator it = CodeStructure.getDefinedStatementsIterator(contDelCodeExp);
            CodeStatement[] statements = CodeStructure.filterStatements(
                                                it, getSetLayoutMethod());
            boolean nullLayout;
            if (statements.length > 0) {
                CodeExpression layoutExp =
                    statements[0].getStatementParameters()[0];
                nullLayout = layoutExp.getOrigin().getType()
                             != org.netbeans.lib.awtextra.AbsoluteLayout.class;
            }
            else nullLayout = true;

            if (nullLayout) {
                if (setBoundsMethod == null)
                    setBoundsMethod = java.awt.Component.class.getMethod(
                                      "setBounds", // NOI18N
                                      new Class[] { Integer.TYPE, Integer.TYPE,
                                                    Integer.TYPE, Integer.TYPE });
                CodeStructure.createStatement(
                    compExp, setBoundsMethod, boundsParams);

                // create add method statement
                CodeStructure.createStatement(contDelCodeExp,
                                              getSimpleAddMethod(),
                                              new CodeExpression[] { compExp });
            }
            else {
                if (absoluteConstraintsConstructor == null)
                    absoluteConstraintsConstructor =
                        org.netbeans.lib.awtextra.AbsoluteConstraints.class
                                                      .getConstructor(
                            new Class[] { Integer.TYPE, Integer.TYPE,
                                          Integer.TYPE, Integer.TYPE });

                // create add method statement
                CodeStructure.createStatement(
                    contDelCodeExp,
                    getAddWithConstrMethod(),
                    new CodeExpression[] { compExp,
                                        codeStructure.createExpression(
                                            absoluteConstraintsConstructor,
                                            boundsParams) });
            }
        }

        return true;

        }
        catch (NoSuchMethodException ex) { // should not happen
            ex.printStackTrace();
        }
        catch (NoSuchFieldException ex) { // should not happen
            ex.printStackTrace();
        }
        return false;
    }

    private void setupDefaultComponentCode(CodeExpression compExp,
                                           LayoutSupportManager layoutSupport)
    {
        if (layoutConvIndex == LAYOUT_JSCROLL) {
            // JScrollPane requires special add code although there are
            // no constraints ...
            if (setViewportViewMethod == null) {
                try {
                    setViewportViewMethod =
                            javax.swing.JScrollPane.class.getMethod(
                                    "setViewportView", // NOI18N
                                    new Class[] { java.awt.Component.class });
                }
                catch (NoSuchMethodException ex) { // should not happen
                    ex.printStackTrace();
                    return;
                }
            }

            CodeStructure.createStatement(
                              layoutSupport.getContainerCodeExpression(),
                              setViewportViewMethod,
                              new CodeExpression[] { compExp });
        }
        else { // create simple add method statement with no constraints
            CodeStructure.createStatement(
                    layoutSupport.getContainerDelegateCodeExpression(),
                    getSimpleAddMethod(),
                    new CodeExpression[] { compExp });
        }
    }

    private static Method getSimpleAddMethod() {
        if (simpleAddMethod == null) {
            try {
                simpleAddMethod = java.awt.Container.class.getMethod(
                                      "add", // NOI18N
                                      new Class[] { java.awt.Component.class });
            }
            catch (NoSuchMethodException ex) { // should not happen
                ex.printStackTrace();
            }
        }
        return simpleAddMethod;
    }

    private static Method getAddWithConstrMethod() {
        if (addWithConstrMethod == null) {
            try {
                addWithConstrMethod = java.awt.Container.class.getMethod(
                                      "add", // NOI18N
                                      new Class[] { java.awt.Component.class,
                                                    Object.class });
            }
            catch (NoSuchMethodException ex) { // should not happen
                ex.printStackTrace();
            }
        }
        return addWithConstrMethod;
    }

    private static Method getSetLayoutMethod() {
        if (setLayoutMethod == null) {
            try {
                setLayoutMethod = java.awt.Container.class.getMethod(
                            "setLayout", // NOI18N
                            new Class[] { java.awt.LayoutManager.class });
            }
            catch (NoSuchMethodException ex) { // should not happen
                ex.printStackTrace();
            }
        }
        return setLayoutMethod;
    }

    private int loadLayout(org.w3c.dom.Node layoutNode,
                           LayoutSupportManager layoutSupport)
    {
        org.w3c.dom.NamedNodeMap layoutAttr = layoutNode.getAttributes();
        org.w3c.dom.Node node = layoutAttr.getNamedItem(ATTR_LAYOUT_CLASS);
        if (node == null)
            return -1;

        String layout31Name = PersistenceObjectRegistry.getClassName(
                                                            node.getNodeValue());
        int convIndex = -1;
        for (int i=0; i < layout31Names.length; i++)
            if (layout31Name.equals(layout31Names[i])) {
                convIndex = i;
                break;
            }

        if (convIndex < 0)
            return -1; // unknown layout

        org.w3c.dom.Node[] propNodes = findSubNodes(layoutNode, XML_PROPERTY);
        List propertyNames = null;
        List propertyValues = null;
        List propertyEditors = null;

        if (propNodes != null && propNodes.length > 0) {
            propertyNames = new ArrayList(propNodes.length);
            propertyValues = new ArrayList(propNodes.length);
            propertyEditors = new ArrayList(propNodes.length);

            for (int i=0; i < propNodes.length; i++) {
                node = propNodes[i];

                Object editorOrValue = getPropertyEditorOrValue(node);
                if (editorOrValue == NO_VALUE)
                    continue;

                propertyNames.add(getAttribute(node, ATTR_PROPERTY_NAME));
                if (editorOrValue instanceof PropertyEditor) {
                    propertyEditors.add(editorOrValue);
                    propertyValues.add(null);
                }
                else {
                    propertyValues.add(editorOrValue);
                    propertyEditors.add(null);
                }
            }
        }

        CodeStructure codeStructure = layoutSupport.getCodeStructure();
        CodeExpression[] layoutParams = null;
        Class[] paramTypes = null;
        Class layoutClass = null;

        String[] layoutPropNames = layout31PropertyNames[convIndex];
        if (convIndex == LAYOUT_BORDER) {
            int hgap = findName(layoutPropNames[0], propertyNames);
            int vgap = findName(layoutPropNames[1], propertyNames);
            if (hgap >= 0 || vgap >= 0) {
                layoutParams = new CodeExpression[2];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    hgap >= 0 ? propertyValues.get(hgap) : new Integer(0),
                    (PropertyEditor)
                        (hgap >= 0 ? propertyEditors.get(hgap) : null));

                layoutParams[1] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    vgap >= 0 ? propertyValues.get(vgap) : new Integer(0),
                    (PropertyEditor)
                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
            }
            else {
                layoutParams = CodeStructure.EMPTY_PARAMS;
            }
            layoutClass = java.awt.BorderLayout.class;
        }

        else if (convIndex == LAYOUT_FLOW) {
            int alignment = findName(layoutPropNames[0], propertyNames);
            int hgap = findName(layoutPropNames[1], propertyNames);
            int vgap = findName(layoutPropNames[2], propertyNames);
            if (hgap >= 0 || vgap >= 0) {
                layoutParams = new CodeExpression[3];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    alignment >= 0 ? propertyValues.get(alignment) : new Integer(1),
                    (PropertyEditor)
                        (alignment >= 0 ? propertyEditors.get(alignment) : null));

                layoutParams[1] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    hgap >= 0 ? propertyValues.get(hgap) : new Integer(5),
                    (PropertyEditor)
                        (hgap >= 0 ? propertyEditors.get(hgap) : null));

                layoutParams[2] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    vgap >= 0 ? propertyValues.get(vgap) : new Integer(5),
                    (PropertyEditor)
                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
            }
            else if (alignment >= 0) {
                layoutParams = new CodeExpression[1];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    alignment >= 0 ? propertyValues.get(alignment) : new Integer(1),
                    (PropertyEditor)
                        (alignment >= 0 ? propertyEditors.get(alignment) : null));
            }
            else {
                layoutParams = CodeStructure.EMPTY_PARAMS;
            }
            layoutClass = java.awt.FlowLayout.class;
        }

        else if (convIndex == LAYOUT_GRIDBAG) {
            layoutParams = CodeStructure.EMPTY_PARAMS;
            layoutClass = java.awt.GridBagLayout.class;
        }

        else if (convIndex == LAYOUT_BOX) {
            int axis = findName(layoutPropNames[0],
                                propertyNames);

            layoutParams = new CodeExpression[2];
            layoutParams[0] = layoutSupport.getContainerDelegateCodeExpression();
            layoutParams[1] = createExpressionForProperty(
                codeStructure,
                Integer.TYPE,
                axis >= 0 ? propertyValues.get(axis) : new Integer(javax.swing.BoxLayout.X_AXIS),
                (PropertyEditor)
                    (axis >= 0 ? propertyEditors.get(axis) : null));

            paramTypes = new Class[] { java.awt.Container.class, Integer.TYPE };
            layoutClass = javax.swing.BoxLayout.class;
        }

        else if (convIndex == LAYOUT_GRID) {
            int rows = findName(layoutPropNames[0], propertyNames);
            int columns = findName(layoutPropNames[1], propertyNames);
            int hgap = findName(layoutPropNames[2], propertyNames);
            int vgap = findName(layoutPropNames[3], propertyNames);
            if (hgap >= 0 || vgap >= 0) {
                layoutParams = new CodeExpression[4];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    rows >= 0 ? propertyValues.get(rows) : new Integer(1),
                    (PropertyEditor)
                        (rows >= 0 ? propertyEditors.get(rows) : null));

                layoutParams[1] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    columns >= 0 ? propertyValues.get(columns) : new Integer(0),
                    (PropertyEditor)
                        (columns >= 0 ? propertyEditors.get(columns) : null));

                layoutParams[2] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    hgap >= 0 ? propertyValues.get(hgap) : new Integer(0),
                    (PropertyEditor)
                        (hgap >= 0 ? propertyEditors.get(hgap) : null));

                layoutParams[3] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    vgap >= 0 ? propertyValues.get(vgap) : new Integer(0),
                    (PropertyEditor)
                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
            }
            else if (rows >= 0 || columns >= 0) {
                layoutParams = new CodeExpression[2];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    rows >= 0 ? propertyValues.get(rows) : new Integer(1),
                    (PropertyEditor)
                        (rows >= 0 ? propertyEditors.get(rows) : null));

                layoutParams[1] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    columns >= 0 ? propertyValues.get(columns) : new Integer(0),
                    (PropertyEditor)
                        (columns >= 0 ? propertyEditors.get(columns) : null));
            }
            else {
                layoutParams = CodeStructure.EMPTY_PARAMS;
            }
            layoutClass = java.awt.GridLayout.class;
        }

        else if (convIndex == LAYOUT_CARD) {
            int hgap = findName(layoutPropNames[0], propertyNames);
            int vgap = findName(layoutPropNames[1], propertyNames);
            if (hgap >= 0 && vgap >= 0) {
                layoutParams = new CodeExpression[2];

                layoutParams[0] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    hgap >= 0 ? propertyValues.get(hgap) : new Integer(0),
                    (PropertyEditor)
                        (hgap >= 0 ? propertyEditors.get(hgap) : null));

                layoutParams[1] = createExpressionForProperty(
                    codeStructure,
                    Integer.TYPE,
                    vgap >= 0 ? propertyValues.get(vgap) : new Integer(0),
                    (PropertyEditor)
                        (vgap >= 0 ? propertyEditors.get(vgap) : null));
            }
            else {
                layoutParams = CodeStructure.EMPTY_PARAMS;
            }
            layoutClass = java.awt.CardLayout.class;
        }

        else if (convIndex == LAYOUT_ABSOLUTE) {
            boolean nullLayout = false;
            int i = findName("useNullLayout", propertyNames); // NOI18N
            if (i >= 0)
                nullLayout = Boolean.TRUE.equals(propertyValues.get(i)); 

            layoutParams = CodeStructure.EMPTY_PARAMS;
            layoutClass = nullLayout ? null :
                          org.netbeans.lib.awtextra.AbsoluteLayout.class;
        }

        else return convIndex; // no layout manager

        CodeExpression layoutExp;
        if (layoutClass != null) {
            if (paramTypes == null) {
                paramTypes = new Class[layoutParams.length];
                for (int i=0; i < layoutParams.length; i++)
                    paramTypes[i] = layoutParams[i].getOrigin().getType();
            }

            Constructor layoutConstructor;
            try {
                layoutConstructor = layoutClass.getConstructor(paramTypes);
            }
            catch (NoSuchMethodException ex) { // should not happen
                ex.printStackTrace();
                return -1;
            }
            layoutExp = layoutSupport.getCodeStructure().createExpression(
                                layoutConstructor, layoutParams);
        }
        else {
            layoutExp = layoutSupport.getCodeStructure().createNullExpression(
                                                 java.awt.LayoutManager.class);
        }

        CodeStructure.createStatement(
            layoutSupport.getContainerDelegateCodeExpression(),
            getSetLayoutMethod(),
            new CodeExpression[] { layoutExp });

        return convIndex;
    }

    private static CodeExpression createExpressionForProperty(
                                      CodeStructure codeStructure,
                                      Class type,
                                      Object value,
                                      PropertyEditor propEd)
    {
        return propEd != null ?
            codeStructure.createExpression(FormCodeSupport.createOrigin(
                                                           type, propEd)) :
            codeStructure.createExpression(type,
                                           value,
                                           value != null ?
                                               value.toString() : "null"); // NOI18N
    }

    private static int findName(String name, List names) {
        return names != null ? names.indexOf(name) : -1;
    }

    private void loadLayoutCode(org.w3c.dom.Node node) {
        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes != null) {
//            codeFlow = true;
            for (int i=0, n=childNodes.getLength(); i < n; i++) {
                org.w3c.dom.Node childNode = childNodes.item(i);

                if (XML_CODE_STATEMENT.equals(childNode.getNodeName()))
                    loadCodeStatement(childNode, null);
            }
        }
    }

    private void loadComponentProperties(org.w3c.dom.Node node,
                                         RADComponent metacomp,
                                         String propCategory)
    {
        org.w3c.dom.Node[] propNodes = findSubNodes(node, XML_PROPERTY);
        String[] propNames = new String[propNodes.length];

        for (int i=0; i < propNodes.length; i++) {
            org.w3c.dom.Node propNode = propNodes[i];
            String propName = getAttribute(propNode, ATTR_PROPERTY_NAME);
            if (propName != null)
                propNames[i] = propName;
            else {
                PersistenceException ex = new PersistenceException(
                                           "Missing property name"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }
        }

        FormProperty[] properties = findProperties(propNames, metacomp, propCategory);

        for (int i=0; i < propNodes.length; i++) {
            if (propNames[i] == null)
                continue;

            org.w3c.dom.Node propNode = propNodes[i];
            FormProperty property = properties[i];

            if (property == null) {
                PersistenceException ex = new PersistenceException(
                                                 "Unknown property"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }

            // read pre-init and post-init code of the property
            String preCode = getAttribute(propNode, ATTR_PROPERTY_PRE_CODE);
            if (preCode != null)
                property.setPreCode(preCode);
            String postCode = getAttribute(propNode, ATTR_PROPERTY_POST_CODE);
            if (postCode != null)
                property.setPostCode(postCode);

            String typeStr = getAttribute(propNode, ATTR_PROPERTY_TYPE);
            String editorStr = getAttribute(propNode, ATTR_PROPERTY_EDITOR);
            String valueStr = getAttribute(propNode, ATTR_PROPERTY_VALUE);

            // get the type of stored property value
            Class propertyType = null;
            Throwable t = null;

            if (typeStr != null) {
                try {
                    propertyType = getClassFromString(typeStr);
                }
                catch (Exception ex) {
                    t = ex;
                }
                catch (LinkageError ex) {
                    t = ex;
                }
                if (t != null) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotLoadClass2", // NOI18N
                            new Object[] { typeStr }),
                        propNode);
                    ErrorManager.getDefault().annotate(t, msg);
                    nonfatalErrors.add(t);
                    continue;
                }
                if (!property.getValueType().isAssignableFrom(propertyType)) {
                    PersistenceException ex = new PersistenceException(
                                           "Incompatible property type"); // NOI18N
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
                        propNode);
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, msg, null, null);
                    nonfatalErrors.add(ex);
                    continue;
                }
            }
            else propertyType = property.getValueType();

            // load the property editor class and create an instance of it
            PropertyEditor prEd = null;
            if (editorStr != null) {
                Class editorClass = null;
                try {
                    editorClass = PersistenceObjectRegistry.loadClass(editorStr, formFile);
                }
                catch (Exception ex) {
                    t = ex;
                }
                catch (LinkageError ex) {
                    t = ex;
                }
                if (t != null) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotLoadClass3", // NOI18N
                            new Object[] { editorStr }),
                        propNode);
                    ErrorManager.getDefault().annotate(t, msg);
                    nonfatalErrors.add(t);
                    continue;
                }

                try {
                    prEd = createPropertyEditor(editorClass,
                                                propertyType,
                                                property);
                }
                catch (Exception ex) {
                    t = ex;
                }
                catch (LinkageError ex) {
                    t = ex;
                }
                if (t != null) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotCreateInstance2", // NOI18N
                            new Object[] { editorStr }),
                        propNode);
                    ErrorManager.getDefault().annotate(t, msg);
                    nonfatalErrors.add(t);
                    continue;
                }
            }

            // load the property value
            Object value = NO_VALUE;
            if (valueStr != null) { // it is a primitive value
                try {
                    value = decodePrimitiveValue(valueStr, propertyType);
                    if (prEd != null) {
                        prEd.setValue(value);
                        value = prEd.getValue();
                    }
                }
                catch (IllegalArgumentException ex) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotDecodePrimitive", // NOI18N
                            new Object[] { valueStr, propertyType.getName() }),
                        propNode);
                    ErrorManager.getDefault().annotate(ex, msg);
                    nonfatalErrors.add(ex);
                    continue;
                }
            }
            else { // the value is serialized or saved by XMLPropertyEditor
                org.w3c.dom.NodeList children = propNode.getChildNodes();
                int n = children != null ? children.getLength() : 0;
                if (n > 0) {
                    try {
                        boolean serialized = false;
                        // first try if the value is serialized
                        for (int j=0; j < n; j++) {
                            if (XML_SERIALIZED_PROPERTY_VALUE.equals(
                                        children.item(j).getNodeName()))
                            {   // here is the value serialized in XML
                                String serValue = getAttribute(children.item(j),
                                                            ATTR_PROPERTY_VALUE);
                                if (serValue != null) {
                                    serialized = true;
                                    value = decodeValue(serValue);
                                }
                                break;
                            }
                        }

                        if (!serialized) {
                            if (prEd instanceof XMLPropertyEditor) {
                                // the value is saved by XMLPropertyEditor
                                for (int j=0; j < n; j++) {
                                    if (children.item(j).getNodeType()
                                        == org.w3c.dom.Node.ELEMENT_NODE)
                                    {   // here is the element of stored value
                                        ((XMLPropertyEditor)prEd).readFromXML(
                                                              children.item(j));
                                        value = prEd.getValue();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex) {
                        t = ex;
                    }
                    catch (LinkageError ex) {
                        t = ex;
                    }
                    if (t != null) {
                        String msg = createLoadingErrorMessage(
                            FormUtils.getBundleString(
                                "MSG_ERR_CannotReadPropertyValue"), // NOI18N
                            propNode);
                        ErrorManager.getDefault().annotate(t, msg);
                        nonfatalErrors.add(t);
                        continue;
                    }
                }

                if (value == NO_VALUE) { // the value is missing
                    if (preCode != null || postCode != null)
                        continue; // not an error
                    PersistenceException ex = new PersistenceException(
                                               "Missing property value"); // NOI18N
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
                        propNode);
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, msg, null, null);
                    nonfatalErrors.add(ex);
                    continue;
                }
            }

            // hack for properties that can't be set until all children 
            // are added to the container
            if (FormUtils.isContainerContentDependentProperty(
                                     metacomp.getBeanClass(),
                                     property.getName()))
            {
                List propList;
                if (containerDependentProperties != null) {
                    propList = (List) containerDependentProperties.get(metacomp);
                }
                else {
                    containerDependentProperties = new HashMap();
                    propList = null;
                }
                if (propList == null) {
                    propList = new LinkedList();
                    containerDependentProperties.put(metacomp, propList);
                }

                propList.add(property);
                propList.add(value);
                continue;
            }

            // set the value to the property
            try {
                property.setValue(value);
                if (prEd != null)
                    property.setCurrentEditor(prEd);
            }
            catch (Exception ex) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(ex, msg);
                nonfatalErrors.add(ex);
                continue;
            }
        }
    }

    private FormProperty[] findProperties(String[] propertyNames,
                                          RADComponent metacomp,
                                          String propCategory)
    {   // [this is a bit ugly method, but don't have better way now...]
        if (XML_PROPERTIES.equals(propCategory)) // bean properties
            return metacomp.getBeanProperties(propertyNames);

        if (XML_A11Y_PROPERTIES.equals(propCategory)) {
            FormProperty[] properties = new FormProperty[propertyNames.length];
            for (int i=0; i < propertyNames.length; i++)
                properties[i] = (FormProperty) metacomp.getPropertyByName(
                                                          propertyNames[i],
                                                          FormProperty.class,
                                                          true);

            return properties;
        }

        return new FormProperty[propertyNames.length]; // error
    }

    private void loadSyntheticProperties(org.w3c.dom.Node node,
                                         RADComponent metacomp)
    {
        org.w3c.dom.Node[] propNodes = findSubNodes(node, XML_SYNTHETIC_PROPERTY);
        for (int i=0; i < propNodes.length; i++) {
            org.w3c.dom.Node propNode = propNodes[i];
            // get the attributes of property node element
            org.w3c.dom.NamedNodeMap attrs = propNode.getAttributes();
            if (attrs == null)
                continue; // no attributes, ignore property

            // get the property name from attributes
            org.w3c.dom.Node nameNode = attrs.getNamedItem(ATTR_PROPERTY_NAME);
            if (nameNode == null) {
                PersistenceException ex = new PersistenceException(
                                 "Missing synthetic property name"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }

            // find the property in the metacomponent
            String propName = nameNode.getNodeValue();
            Node.Property [] props = metacomp.getSyntheticProperties();
            Node.Property property = null;
            Class expectedPropertyType = null;
            for (int j=0; j < props.length; j++) {
                if (props[j].getName().equals(propName)) {
                    property = props[j];
                    break;
                }
            }

            if (property == null) {
                if ("menuBar".equals(propName) // NOI18N
                    && metacomp instanceof RADVisualFormContainer)
                {   // compatibility hack for loading form's menu bar, part 1
                    // (menubar is no longer a synthetic property, but it was
                    // in NB 3.2)
                    expectedPropertyType = String.class;
                }
                else if ("encoding".equals(propName)) // NOI18N
                    continue; // there used to be "encoding" property in NB 3.1
                else { // unknown synthetic property
                    PersistenceException ex = new PersistenceException(
                                           "Unknown synthetic property"); // NOI18N
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
                        propNode);
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, msg, null, null);
                    nonfatalErrors.add(ex);
                    continue;
                }
            }
            else expectedPropertyType = property.getValueType();

            org.w3c.dom.Node typeNode = attrs.getNamedItem(ATTR_PROPERTY_TYPE);
            org.w3c.dom.Node valueNode = attrs.getNamedItem(ATTR_PROPERTY_VALUE);

            // get the type of stored property value
            Class propertyType = null;
            Throwable t = null;

            if (typeNode != null) {
                try {
                    propertyType = getClassFromString(typeNode.getNodeValue());
                }
                catch (Exception ex) {
                    t = ex;
                }
                catch (LinkageError ex) {
                    t = ex;
                }
                if (t != null) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotLoadClass2", // NOI18N
                            new Object[] { typeNode.getNodeValue() }),
                        propNode);
                    ErrorManager.getDefault().annotate(t, msg);
                    nonfatalErrors.add(t);
                    continue;
                }
                if (!expectedPropertyType.isAssignableFrom(propertyType)) {
                    PersistenceException ex = new PersistenceException(
                                           "Incompatible property type"); // NOI18N
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
                        propNode);
                    ErrorManager.getDefault().annotate(
                        ex, ErrorManager.ERROR, null, msg, null, null);
                    nonfatalErrors.add(ex);
                    continue;
                }
            }
            else propertyType = property.getValueType();

            // load the property value
            if (valueNode == null) { // the value is missing
                PersistenceException ex = new PersistenceException(
                                 "Missing synthetic property value"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }

            Object value = null;
            try {
                try {
                    value = decodePrimitiveValue(valueNode.getNodeValue(),
                                                 propertyType);
                }
                catch (IllegalArgumentException ex) {
                    // not a primitive value
                    value = decodeValue(valueNode.getNodeValue());
                }
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            if (t != null) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(t, msg);
                nonfatalErrors.add(t);
                continue;
            }

            // compatibility hack for loading form's menu bar, part 2
            if ("menuBar".equals(propName) // NOI18N
                && value instanceof String
                && metacomp instanceof RADVisualFormContainer)
            {
                RADComponent[] nvComps =
                    metacomp.getFormModel().getNonVisualComponents();
                for (int j=0; j < nvComps.length; j++)
                    if (nvComps[j] instanceof RADMenuComponent
                        && value.equals(nvComps[j].getName()))
                    {
                        RADMenuComponent menuComp =
                            (RADMenuComponent) nvComps[j];
                        RADVisualFormContainer formCont =
                            (RADVisualFormContainer) metacomp;
                        menuComp.getFormModel().removeComponentFromContainer(menuComp);
                        formCont.add(menuComp);
                        menuComp.setParentComponent(formCont);
                        break;
                    }
                continue;
            }

            // set the value to the property
            try {
                property.setValue(value);
            }
            catch (Exception ex) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
                    propNode);
                ErrorManager.getDefault().annotate(ex, msg);
                nonfatalErrors.add(ex);
                continue;
            }
        }
    }

    private void loadEvents(org.w3c.dom.Node node, RADComponent metacomp) {
        org.w3c.dom.Node[] eventNodes = findSubNodes(node, XML_EVENT);
        String[] eventNames = new String[eventNodes.length];

        for (int i=0; i < eventNodes.length; i++) {
            org.w3c.dom.Node eventNode = eventNodes[i];
            String eventName = getAttribute(eventNode, ATTR_EVENT_NAME);
            String eventListener = getAttribute(eventNode, ATTR_EVENT_LISTENER);
            String paramTypes = getAttribute(eventNode, ATTR_EVENT_PARAMS);
            String eventHandlers = getAttribute(eventNode, ATTR_EVENT_HANDLER);

            if (eventName == null || eventHandlers == null)
                continue; // [missing data error - should be reported!!]

            eventNames[i] = getEventIdName(eventListener, eventName, paramTypes);
        }

        FormEvents formEvents = formModel.getFormEvents();

        Event[] events = metacomp.getEvents(eventNames);
        for (int i=0; i < eventNodes.length; i++) {
            if (eventNames[i] == null)
                continue;

            Event event = events[i];
            if (event == null)
                continue; // [uknown event error - should be reported!]

            String eventHandlers = getAttribute(eventNodes[i], ATTR_EVENT_HANDLER);
            StringTokenizer tok = new StringTokenizer(eventHandlers, ","); // NOI18N
            while (tok.hasMoreTokens()) {
                try {
                    formEvents.attachEvent(event, tok.nextToken(), null);
                }
                catch (IllegalArgumentException ex) {
                    // [incompatible handler error - should be reported!]
                }
            }
        }
    }

    private static String getEventIdName(String eventListener,
                                         String eventName,
                                         String paramTypes)
    {
        if (eventListener == null || paramTypes == null)
            return eventName;

        StringBuffer buf = new StringBuffer();
        buf.append("$"); // NOI18N
        buf.append(eventListener);
        buf.append("."); // NOI18N
        buf.append(eventName);
        buf.append("("); // NOI18N

        StringTokenizer tok = new StringTokenizer(paramTypes, ","); // NOI18N
        while (tok.hasMoreTokens()) {
            buf.append(tok.nextToken());
            if (tok.hasMoreTokens())
                buf.append(", "); // NOI18N
        }

        buf.append(")"); // NOI18N
        return buf.toString();
    }

    private void loadAuxValues(org.w3c.dom.Node node, RADComponent comp) {
        org.w3c.dom.Node[] auxNodes = findSubNodes(node, XML_AUX_VALUE);
        for (int i=0; i < auxNodes.length; i++) {
            org.w3c.dom.Node auxNode = auxNodes[i];
            // get the attributes of property node element
            org.w3c.dom.NamedNodeMap attrs = auxNode.getAttributes();
            if (attrs == null)
                continue; // no attributes, ignore

            // get the property name from attributes
            org.w3c.dom.Node nameNode = attrs.getNamedItem(ATTR_AUX_NAME);
            if (nameNode == null) {
                PersistenceException ex = new PersistenceException(
                                           "Missing aux value name"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
                    auxNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }
            String name = nameNode.getNodeValue();

            org.w3c.dom.Node typeNode = attrs.getNamedItem(ATTR_AUX_VALUE_TYPE);
            org.w3c.dom.Node valueNode = attrs.getNamedItem(ATTR_AUX_VALUE);

            // get the type of stored aux value
            if (typeNode == null) {
                PersistenceException ex = new PersistenceException(
                                           "Missing aux value type"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
                    auxNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }

            Class auxValueType = null;
            Throwable t = null;
            try {
                auxValueType = getClassFromString(typeNode.getNodeValue());
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            if (t != null) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getFormattedBundleString(
                        "FMT_ERR_CannotLoadClass2", // NOI18N
                        new Object[] { typeNode.getNodeValue() }),
                    auxNode);
                ErrorManager.getDefault().annotate(t, msg);
                nonfatalErrors.add(t);
                continue;
            }

            // load the aux value
            if (valueNode == null) { // the value is missing
                PersistenceException ex = new PersistenceException(
                                                "Missing aux value"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
                    auxNode);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                continue;
            }

            Object value = null;
            try {
                try {
                    value = decodePrimitiveValue(valueNode.getNodeValue(),
                                                 auxValueType);
                }
                catch (IllegalArgumentException ex) {
                    // not a primitive value
                    value = decodeValue(valueNode.getNodeValue());
                }
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            if (t != null) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
                    auxNode);
                ErrorManager.getDefault().annotate(t, msg);
                nonfatalErrors.add(t);
                continue;
            }

            // we have a valid name / value pair
            comp.setAuxValue(name, value);
        }

        // we must care about some aux values specially ...

        // VALUE_SERIALIZE indicates serialized component
        if (JavaCodeGenerator.VALUE_SERIALIZE.equals(
                comp.getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION)))
        {   // the component has a serialized instance => deserialize it
            try {
                String serFile = (String) comp.getAuxValue(
                                          JavaCodeGenerator.AUX_SERIALIZE_TO);
                if (serFile == null)
                    serFile = formFile.getName() + "_" + comp.getName(); // NOI18N

                ClassPath sourcePath = ClassPath.getClassPath(formFile, ClassPath.SOURCE);
                String serName = sourcePath.getResourceName(formFile.getParent());
                if (!"".equals(serName)) // NOI18N
                    serName += "."; // NOI18N
                serName += serFile;

                Object instance = null;
                try {
                    instance = Beans.instantiate(sourcePath.getClassLoader(true), serName);
                } catch (ClassNotFoundException cnfe) {
                    ClassPath executionPath = ClassPath.getClassPath(formFile, ClassPath.EXECUTE);
                    instance = Beans.instantiate(executionPath.getClassLoader(true), serName);
                }

                comp.setInstance(instance);
            }
            catch (Exception ex) { // ignore
                org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            }
        }

        // AUX_VARIABLE_MODIFIER and AUX_VARIABLE_LOCAL require changing
        // type of component's variable 
        Object val = comp.getAuxValue(JavaCodeGenerator.AUX_VARIABLE_MODIFIER);
        int newType = val instanceof Integer ?
                        ((Integer)val).intValue() : -1;

        val = comp.getAuxValue(JavaCodeGenerator.AUX_VARIABLE_LOCAL);
        if (val instanceof Boolean) {
            if (newType == -1)
                newType = 0;
            newType |= Boolean.TRUE.equals(val) ?
                       CodeVariable.LOCAL | CodeVariable.EXPLICIT_DECLARATION :
                       CodeVariable.FIELD;
        }

        if (newType > -1) { // set variable type
            CodeExpression exp = comp.getCodeExpression();
            int varType = exp.getVariable().getType();

            varType &= ~CodeVariable.ALL_MODIF_MASK;
            varType |= newType & CodeVariable.ALL_MODIF_MASK;

            if ((newType & CodeVariable.SCOPE_MASK) != 0) {
                varType &= ~CodeVariable.SCOPE_MASK;
                varType |= newType & CodeVariable.SCOPE_MASK;
            }

            if ((newType & CodeVariable.DECLARATION_MASK) != 0) {
                varType &= ~CodeVariable.DECLARATION_MASK;
                varType |= newType & CodeVariable.DECLARATION_MASK;
            }

            CodeStructure codeStructure = formModel.getCodeStructure();
            String varName = comp.getName(); // get the original name
            codeStructure.removeExpressionFromVariable(exp);
            codeStructure.createVariableForExpression(exp, varType, varName);
        }
    }

    // -----------

    /** This method saves the form to given data object.
     * @param formObject FormDataObject representing the form files
     * @param formModel FormModel to be saved
     * @param nonfatalErrors List to be filled with errors occurred during
     *        saving which are not fatal (but should be reported)
     * @exception PersistenceException if some fatal problem occurred which
     *            prevents saving the form
     */
    public void saveForm(FormDataObject formObject,
                         FormModel formModel,
                         List nonfatalErrors)
        throws PersistenceException
    {
        FileObject formFile = formObject.getFormEntry().getFile();
        if (!formFile.canWrite()) { // should not happen
            PersistenceException ex = new PersistenceException(
                                 "Tried to save read-only form"); // NOI18N
            String msg = FormUtils.getFormattedBundleString(
                             "FMT_ERR_SaveToReadOnly", // NOI18N
                             new Object[] { formFile.getNameExt() });
            ErrorManager.getDefault().annotate(
                ex, ErrorManager.ERROR, null, msg, null, null);
            throw ex;
        }

        StringBuffer buf1 = new StringBuffer();
        StringBuffer buf2 = new StringBuffer();

        // initial cleanup
        lastExpId = 0; // CodeExpression ID counter
        if (expressions != null)
            expressions.clear();
        if (savedVariables != null)
            savedVariables.clear();

        this.formFile = formFile;
        this.formModel = formModel;
        this.nonfatalErrors = nonfatalErrors;

        // start with the lowest version; if there is nothing in the
        // form that requires higher format version, then the form file
        // is compatible with NB 3.2
        formatVersion = NB32_VERSION;

        RADComponent topComp = formModel.getTopRADComponent();
        RADVisualFormContainer formCont =
            topComp instanceof RADVisualFormContainer ?
                (RADVisualFormContainer) topComp : null;

        // store XML file header
        final String encoding = "UTF-8"; // NOI18N
        buf1.append("\n\n"); // NOI18N

        // store "Other Components"
        RADComponent[] nonVisuals = formModel.getNonVisualComponents();

        // compatibility hack for saving form's menu bar (part I)
        if (formCont != null && formCont.getContainerMenu() != null) {
            RADComponent[] comps = new RADComponent[nonVisuals.length + 1];
            System.arraycopy(nonVisuals, 0, comps, 0, nonVisuals.length);
            comps[nonVisuals.length] = formCont.getContainerMenu();
            nonVisuals = comps;
        }

        if (nonVisuals.length > 0) {
            buf2.append(ONE_INDENT);
            addElementOpen(buf2, XML_NON_VISUAL_COMPONENTS);

            for (int i = 0; i < nonVisuals.length; i++)
                saveAnyComponent(nonVisuals[i],
                                 buf2, ONE_INDENT + ONE_INDENT,
                                 true);

            buf2.append(ONE_INDENT);
            addElementClose(buf2, XML_NON_VISUAL_COMPONENTS);
        }

        // store form main hierarchy
        if (topComp != null) {
            saveAnyComponent(topComp, buf2, ONE_INDENT, false);

            if (!(topComp instanceof RADVisualContainer))
                raiseFormatVersion(NB33_VERSION);
        }
        addElementClose(buf2, XML_FORM);

        // determine FormInfo type (for backward compatibility)
        String compatFormInfo = getFormInfoForKnownClass(
                                    formModel.getFormBaseClass());
        // [if some non-standard FormInfo was used, it is lost]

        // add form specification element at the beginning of the form file
        // (this is done in the end because the required form version is
        // not determined until all data is saved)
        if (compatFormInfo == null) {
            raiseFormatVersion(NB33_VERSION);

            addElementOpenAttr(buf1, XML_FORM,
                new String[] { ATTR_FORM_VERSION },
                new String[] { formatVersion });
        }
        else {
            addElementOpenAttr(buf1, XML_FORM,
                new String[] { ATTR_FORM_VERSION, ATTR_FORM_TYPE },
                new String[] { formatVersion, compatFormInfo });
        }

        // final cleanup
        if (expressions != null)
            expressions.clear();
        if (savedVariables != null)
            savedVariables.clear();

        // write the data
        FileLock lock = null;
        try {
            lock = formFile.lock();
        }
        catch (IOException ex) {
            PersistenceException pe = new PersistenceException(
                                        ex, "Cannot obtain lock on form file"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                FormUtils.getFormattedBundleString("FMT_ERR_CannotLockFormFile", // NOI18N
                                      new Object[] { formFile.getNameExt() }));
            throw pe;
        }

        java.io.OutputStream os = null;
        try {
            os = formFile.getOutputStream(lock);
            os.write(buf1.toString().getBytes(encoding));
            os.write(buf2.toString().getBytes(encoding));
        }
        catch (Exception ex) {
            PersistenceException pe = new PersistenceException(
                                          ex, "Cannot write to form file"); // NOI18N
            ErrorManager.getDefault().annotate(
                ex,
                FormUtils.getFormattedBundleString("FMT_ERR_CannotWrtiteToFile", // NOI18N
                                       new Object[] { formFile.getNameExt() }));
            throw pe;
        }
        finally {
            try {
                if (os != null)
                    os.close();
            }
            catch (IOException ex) {} // ignore
            lock.releaseLock();
            this.formModel = null;
        }
    }

    private void saveAnyComponent(RADComponent comp,
                                  StringBuffer buf,
                                  String indent,
                                  boolean createElement) {
        String elementType = null;
        String elementIndent = indent;
        if (createElement) {
            if (comp instanceof RADMenuComponent)
                elementType = XML_MENU_CONTAINER;
            else if (comp instanceof RADMenuItemComponent)
                elementType = XML_MENU_COMPONENT;
            else if (comp instanceof ComponentContainer)
                elementType = XML_CONTAINER;
            else elementType = XML_COMPONENT;

            buf.append(elementIndent);
            addElementOpenAttr(buf, elementType,
                new String[] { ATTR_COMPONENT_CLASS,
                               ATTR_COMPONENT_NAME },
                new String[] { comp.getBeanClass().getName(),
                               comp.getName() });

            indent += ONE_INDENT;
        }

        if (comp instanceof RADMenuItemComponent) {
            saveMenuComponent((RADMenuItemComponent) comp, buf, indent);
        }
        else if (comp instanceof ComponentContainer) {
            saveContainer((ComponentContainer) comp, buf, indent);
        }
        else if (comp instanceof RADVisualComponent) {
            saveVisualComponent((RADVisualComponent) comp, buf, indent);
        }
        else {
            saveComponent(comp, buf, indent);
        }

        if (createElement) {
            buf.append(elementIndent);
            addElementClose(buf, elementType);
        }
    }

    private void saveContainer(ComponentContainer container,
                               StringBuffer buf, String indent)
    {
        RADVisualContainer visualContainer =
            container instanceof RADVisualContainer ?
                (RADVisualContainer) container : null;

        RADComponent[] children = null;
        int convIndex = -1; // index of layout in conversion table

        if (visualContainer != null) {
            saveVisualComponent(visualContainer, buf, indent);
            convIndex = saveLayout(visualContainer, buf, indent);

            // compatibility hack for saving form's menu bar (part II)
            if (container instanceof RADVisualFormContainer)
                children = visualContainer.getSubComponents();
        } 
        else saveComponent((RADComponent)container, buf, indent);

        if (children == null)
            children = container.getSubBeans();

        if (children.length > 0) {
            buf.append(indent);
            addElementOpen(buf, XML_SUB_COMPONENTS);
            for (int i = 0; i < children.length; i++) {
                if (children[i] instanceof RADMenuItemComponent)
                    raiseFormatVersion(NB33_VERSION);

                saveAnyComponent(children[i], buf, indent+ONE_INDENT, true);
            }
            buf.append(indent);
            addElementClose(buf, XML_SUB_COMPONENTS);
        }

        if (visualContainer != null && convIndex == LAYOUT_FROM_CODE)
            saveLayoutCode(visualContainer.getLayoutSupport(), buf, indent);
    }

    private int saveLayout(RADVisualContainer container,
                           StringBuffer buf, String indent)
    {
        LayoutSupportManager layoutSupport = container.getLayoutSupport();
        if (layoutSupport.isUnknownLayout())
            return LAYOUT_UNKNOWN;

        int convIndex = -1; // index in conversion table

        Class layoutClass = layoutSupport.getLayoutDelegate().getSupportedClass();
        if (layoutClass == null)
            convIndex = LAYOUT_NULL;
        else {
            String className = layoutClass.getName();
            for (int i=0; i < supportedClassNames.length; i++)
                if (className.equals(supportedClassNames[i])) {
                    convIndex = i;
                    break;
                }

            if (convIndex < 0) // not a standard layout
                return LAYOUT_FROM_CODE;
        }

        StringBuffer buf2 = new StringBuffer();

        if (convIndex != LAYOUT_ABSOLUTE && convIndex != LAYOUT_NULL) {
            Node.Property[] properties = layoutSupport.getAllProperties();
            for (int i=0; i < properties.length; i++) {
                FormProperty property = (FormProperty) properties[i];
                if (property.isChanged()
                    // NB 3.1 considered special values as default for
                    // GridLayout, so we must always save rows and columns
                    || (convIndex == LAYOUT_GRID
                        && ("rows".equals(property.getName()) // NOI18N
                            || "columns".equals(property.getName())))) // NOI18N
                {
                    String delegatePropName = property.getName();
                    String layout31PropName = null;
                    String[] delPropNames = layoutDelegatePropertyNames[convIndex];
                    for (int j=0; j < delPropNames.length; j++)
                        if (delegatePropName.equals(delPropNames[j])) {
                            layout31PropName = layout31PropertyNames[convIndex][j];
                            break;
                        }

                    if (layout31PropName != null) {
                        saveProperty(property, layout31PropName,
                                     buf2, indent + ONE_INDENT);
                    }
                }
            }
        }
        else { // AbsoluteLayout and null layout are special...
            String nullLayout = convIndex == LAYOUT_NULL ? "true" : "false"; // NOI18N
            buf2.append(indent);
            buf2.append(ONE_INDENT);
            addLeafElementOpenAttr(
                buf2,
                XML_PROPERTY,
                new String[] { ATTR_PROPERTY_NAME,
                               ATTR_PROPERTY_TYPE,
                               ATTR_PROPERTY_VALUE },
                new String[] { "useNullLayout", "boolean", nullLayout } // NOI18N
            );
        }

        buf.append("\n"); // NOI18N
        buf.append(indent);
        if (buf2.length() > 0) {
            addElementOpenAttr(
                buf,
                XML_LAYOUT,
                new String[] { ATTR_LAYOUT_CLASS },
                new String[] { PersistenceObjectRegistry.getPrimaryName(
                                   layout31Names[convIndex]) }
            );
            buf.append(buf2);
            buf.append(indent);
            addElementClose(buf, XML_LAYOUT);
        }
        else {
            addLeafElementOpenAttr(
                buf,
                XML_LAYOUT,
                new String[] { ATTR_LAYOUT_CLASS },
                new String[] { PersistenceObjectRegistry.getPrimaryName(
                                   layout31Names[convIndex]) }
            );
        }

        return convIndex;
    }

    private void saveLayoutCode(LayoutSupportManager layoutSupport,
                                StringBuffer buf, String indent)
    {
        raiseFormatVersion(NB33_VERSION);

        StringBuffer buf2 = new StringBuffer();
        String subIndent = indent + ONE_INDENT;
//        codeFlow = true;

        // layout manager code
        CodeGroup code = layoutSupport.getLayoutCode();
        if (code != null) {
            Iterator it = code.getStatementsIterator();
            while (it.hasNext()) {
                saveCodeStatement((CodeStatement) it.next(), buf2, subIndent);
            }
        }

        // components code
        for (int i=0, n=layoutSupport.getComponentCount(); i < n; i++) {
            code = layoutSupport.getComponentCode(i);
            if (code != null) {
                Iterator it = code.getStatementsIterator();
                while (it.hasNext()) {
                    saveCodeStatement((CodeStatement) it.next(), buf2, subIndent);
                }
            }
        }

        if (buf2.length() > 0) {
            buf.append(indent);
            addElementOpen(buf, XML_LAYOUT_CODE);

            buf.append(buf2.toString());

            buf.append(indent);
            addElementClose(buf, XML_LAYOUT_CODE);
        }
    }

    private void saveVisualComponent(RADVisualComponent component,
                                     StringBuffer buf, String indent)
    {
        saveComponent(component, buf, indent);

        RADVisualContainer container = component.getParentContainer();
        if (container == null)
            return;

        int componentIndex = container.getIndexOf(component);
        LayoutConstraints constr =
            container.getLayoutSupport().getConstraints(componentIndex);
        if (constr == null)
            return; // no constraints

        StringBuffer buf2 = new StringBuffer(); // [might be not used at all]
        int convIndex = saveConstraints(constr, buf2,
                                        indent + ONE_INDENT + ONE_INDENT);
        if (convIndex >= 0) { // standard constraints (saved in buf2)
            buf.append(indent);
            addElementOpen(buf, XML_CONSTRAINTS);
            buf.append(indent + ONE_INDENT);
            addElementOpenAttr(
                buf,
                XML_CONSTRAINT,
                new String[] { ATTR_CONSTRAINT_LAYOUT, ATTR_CONSTRAINT_VALUE },
                new String[] { PersistenceObjectRegistry.getPrimaryName(
                                   layout31Names[convIndex]),
                               PersistenceObjectRegistry.getPrimaryName(
                                   layout31ConstraintsNames[convIndex]) }
            );
            buf.append(buf2);
            buf.append(indent + ONE_INDENT);
            addElementClose(buf, XML_CONSTRAINT);
            buf.append(indent);
            addElementClose(buf, XML_CONSTRAINTS);
        }
    }

    private int saveConstraints(LayoutConstraints constr,
                                StringBuffer buf,
                                String indent)
    {
        // constraints of BorderLayout
        if (constr instanceof BorderLayoutSupport.BorderConstraints) {
            String position = (String) constr.getConstraintsObject();
            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "BorderConstraints", // NOI18N
                new String[] { "direction" }, // NOI18N
                new String[] { position });

            return LAYOUT_BORDER;
        }

        // constraints of GridBagLayout
        if (constr instanceof GridBagLayoutSupport.GridBagLayoutConstraints) {
            java.awt.GridBagConstraints gbConstr =
                (java.awt.GridBagConstraints) constr.getConstraintsObject();

            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "GridBagConstraints", // NOI18N
                new String[] { "gridX", "gridY", "gridWidth", "gridHeight", // NOI18N
                               "fill", "ipadX", "ipadY", // NOI18N
                               "insetsTop", "insetsLeft", // NOI18N
                               "insetsBottom", "insetsRight", // NOI18N
                               "anchor", "weightX", "weightY" }, // NOI18N
                new String[] { Integer.toString(gbConstr.gridx),
                               Integer.toString(gbConstr.gridy),
                               Integer.toString(gbConstr.gridwidth),
                               Integer.toString(gbConstr.gridheight),
                               Integer.toString(gbConstr.fill),
                               Integer.toString(gbConstr.ipadx),
                               Integer.toString(gbConstr.ipady),
                               Integer.toString(gbConstr.insets.top),
                               Integer.toString(gbConstr.insets.left),
                               Integer.toString(gbConstr.insets.bottom),
                               Integer.toString(gbConstr.insets.right),
                               Integer.toString(gbConstr.anchor),
                               Double.toString(gbConstr.weightx),
                               Double.toString(gbConstr.weighty) });

            return LAYOUT_GRIDBAG;
        }

        // constraints of JTabbedPane
        if (constr instanceof JTabbedPaneSupport.TabConstraints) {
            JTabbedPaneSupport.TabConstraints tabConstr =
                (JTabbedPaneSupport.TabConstraints) constr;

            StringBuffer buf2 = new StringBuffer();
            Node.Property[] tabProperties = constr.getProperties();

            for (int i=0; i < tabProperties.length; i++) {
                FormProperty prop = (FormProperty) tabProperties[i];
                if (prop.isChanged())
                    saveProperty(
                        prop,
                        prop.getName().substring("TabConstraints ".length()), // NOI18N
                        buf2,
                        indent + ONE_INDENT);
            }

            buf.append(indent);
            if (buf2.length() > 0) {
                addElementOpenAttr(
                    buf,
                    "JTabbedPaneConstraints", // NOI18N
                    new String[] { "tabName", "toolTip" }, // NOI18N
                    new String[] { tabConstr.getTitle(),
                                   tabConstr.getToolTip() });
                buf.append(buf2);
                buf.append(indent);
                addElementClose(buf, "JTabbedPaneConstraints"); // NOI18N
            }
            else {
                addLeafElementOpenAttr(
                    buf,
                    "JTabbedPaneConstraints", // NOI18N
                    new String[] { "tabName", "toolTip" }, // NOI18N
                    new String[] { tabConstr.getTitle(),
                                   tabConstr.getToolTip() });
            }

            return LAYOUT_JTAB;
        }

        // constraints of JSplitPane
        if (constr instanceof JSplitPaneSupport.SplitConstraints) {
            Object constrObject = constr.getConstraintsObject();
            String position;

            if (javax.swing.JSplitPane.TOP.equals(constrObject))
                position = "top"; // NOI18N
            else if (javax.swing.JSplitPane.BOTTOM.equals(constrObject))
                position = "bottom"; // NOI18N
            else if (javax.swing.JSplitPane.LEFT.equals(constrObject))
                position = "left"; // NOI18N
            else
                position = "right"; // NOI18N

            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "JSplitPaneConstraints", // NOI18N
                new String[] { "position" }, // NOI18N
                new String[] { position });

            return LAYOUT_JSPLIT;
        }

        // constraints of CardLayout
        if (constr instanceof CardLayoutSupport.CardConstraints) {
            String card = (String) constr.getConstraintsObject();
            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "CardConstraints", // NOI18N
                new String[] { "cardName" }, // NOI18N
                new String[] { card });

            return LAYOUT_CARD;
        }

        // constraints of JLayeredPane (must be tested before AbsoluteLayout)
        if (constr instanceof JLayeredPaneSupport.LayeredConstraints) {
            int layer =
                ((JLayeredPaneSupport.LayeredConstraints)constr).getLayer();
            java.awt.Rectangle r =
                ((JLayeredPaneSupport.LayeredConstraints)constr).getBounds();

            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "JLayeredPaneConstraints", // NOI18N
                new String[] { "x", "y", "width", "height", // NOI18N
                               "layer", "position" }, // NOI18N
                new String[] { Integer.toString(r.x),
                               Integer.toString(r.y),
                               Integer.toString(r.width),
                               Integer.toString(r.height),
                               Integer.toString(layer),
                               "-1" }); // NOI18N

            return LAYOUT_JLAYER;
        }

        // constraints of AbsoluteLayout
        if (constr instanceof AbsoluteLayoutSupport.AbsoluteLayoutConstraints) {
            java.awt.Rectangle r =
                ((AbsoluteLayoutSupport.AbsoluteLayoutConstraints)constr)
                    .getBounds();

            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                "AbsoluteConstraints", // NOI18N
                new String[] { "x", "y", "width", "height" }, // NOI18N
                new String[] { Integer.toString(r.x),
                               Integer.toString(r.y),
                               Integer.toString(r.width),
                               Integer.toString(r.height) });

            return LAYOUT_ABSOLUTE;
        }

        return -1;
    }

    private void saveMenuComponent(RADMenuItemComponent component, StringBuffer buf, String indent) {
        saveComponent(component, buf, indent);

        if (component instanceof RADMenuComponent) {
            RADComponent[] children =((RADMenuComponent)component).getSubBeans();
            if (children.length > 0) {
                buf.append(indent); addElementOpen(buf, XML_SUB_COMPONENTS);
                for (int i = 0; i < children.length; i++) {
                    String elementType;
                    if (children[i] instanceof RADMenuComponent) elementType = XML_MENU_CONTAINER;
                    else if (children[i] instanceof RADMenuItemComponent) elementType = XML_MENU_COMPONENT;
                    else elementType = XML_COMPONENT;

                    buf.append(indent + ONE_INDENT);
                    addElementOpenAttr(
                        buf,
                        elementType,
                        new String[] { ATTR_COMPONENT_CLASS, ATTR_COMPONENT_NAME },
                        new String[] { children[i].getBeanClass().getName(),
                                       children[i].getName() });
                    // [PENDING - RADComponents which are not menu???]
                    saveMenuComponent((RADMenuItemComponent)children[i], buf, indent + ONE_INDENT + ONE_INDENT);
                    buf.append(indent + ONE_INDENT); addElementClose(buf, elementType);
                }
                buf.append(indent); addElementClose(buf, XML_SUB_COMPONENTS);
            }
        }
    }

    private void saveComponent(RADComponent component, StringBuffer buf, String indent) {
        // 1. Properties
        if (!JavaCodeGenerator.VALUE_SERIALIZE.equals(
                component.getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION)))
        {   // save properties only if the component is not to be serialized
            saveProperties(component.getKnownBeanProperties(),
                           XML_PROPERTIES, buf, indent);

            if (component instanceof RADVisualComponent) {
                // try to save accessibility properties
                FormProperty[] accProps = ((RADVisualComponent)component)
                                            .getAccessibilityProperties();
                if (saveProperties(accProps,
                                   XML_A11Y_PROPERTIES, buf, indent))
                    raiseFormatVersion(NB34_VERSION);
            }
            else if (component instanceof RADMenuItemComponent) {
                // try to save accessibility properties
                FormProperty[] accProps = ((RADMenuItemComponent)component)
                                            .getAccessibilityProperties();
                if (saveProperties(accProps,
                                   XML_A11Y_PROPERTIES, buf, indent))
                    raiseFormatVersion(NB34_VERSION);
            }
        }

        // 1. Synthetic properties
        if (component instanceof RADVisualFormContainer)
            saveSyntheticProperties(component, buf, indent);

        // 2. Events
        saveEvents(component.getKnownEvents(), buf, indent);

        // 3. Aux Values
        Map auxValues = component.getAuxValues();
        if (auxValues != null && auxValues.size() > 0) {
//            buf.append("\n"); // NOI18N
            buf.append(indent); addElementOpen(buf, XML_AUX_VALUES);
            saveAuxValues(auxValues, buf, indent + ONE_INDENT);
            buf.append(indent); addElementClose(buf, XML_AUX_VALUES);
        }
    }

    private boolean saveProperties(FormProperty[] props,
                                   String blockName,
                                   StringBuffer buf,
                                   String indent)
    {
        int i=0;
        do {
            if (i >= props.length)
                return false; // nothing saved
            FormProperty prop = props[i];
            if (prop.isChanged() || prop.getPreCode() != null
                                 || prop.getPostCode() != null)
                break;
            i++;
        }
        while (true);

        buf.append(indent);
        addElementOpen(buf, blockName);

        for (i=0; i < props.length; i++) {
            FormProperty prop = props[i];
            if (!prop.isChanged()) {
                if (prop.getPreCode() != null || prop.getPostCode() != null) {
                    buf.append(indent + ONE_INDENT);
                    // in this case save only the pre/post code
                    addLeafElementOpenAttr(
                        buf,
                        XML_PROPERTY,
                        new String[] {
                            ATTR_PROPERTY_NAME,
                            ATTR_PROPERTY_PRE_CODE,
                            ATTR_PROPERTY_POST_CODE,
                        },
                        new String[] {
                            prop.getName(),
                            prop.getPreCode(),
                            prop.getPostCode(),
                        });
                }
                continue; // not changed, so do not save value
            }

            saveProperty(prop, prop.getName(), buf, indent + ONE_INDENT);
        }

        buf.append(indent);
        addElementClose(buf, blockName);

        return true;
    }

    private boolean saveProperty(FormProperty property,
                                 String propertyName,
                                 StringBuffer buf,
                                 String indent)
    {
        Object value;
        try {
            value = property.getValue();
        }
        catch (Exception ex) {
            ErrorManager.getDefault().annotate(
                ex,
                FormUtils.getFormattedBundleString(
                    "FMT_ERR_CannotGetPropertyValue", // NOI18N
                    new Object[] { property.getName() }));
            nonfatalErrors.add(ex);
            return false;
        }

        String encodedValue = null;
        String encodedSerializeValue = null;
        org.w3c.dom.Node valueNode = null;

        PropertyEditor prEd = property.getCurrentEditor();
        if (prEd instanceof XMLPropertyEditor) {
            prEd.setValue(value);
            valueNode = ((XMLPropertyEditor)prEd).storeToXML(topDocument);
            if (valueNode == null) { // property editor refused to save the value
                PersistenceException ex = new PersistenceException(
                                   "Cannot save the property value"); // NOI18N
                String msg = FormUtils.getFormattedBundleString(
                                 "FMT_ERR_CannotSaveProperty", // NOI18N
                                 new Object[] { property.getName() });
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                return false;
            }
        }
        else {
            encodedValue = encodePrimitiveValue(value);
            if (encodedValue == null) {
                try {
                    encodedSerializeValue = encodeValue(value);
                }
                catch (Exception ex) {
                    ErrorManager.getDefault().annotate(
                        ex,
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotSaveProperty", // NOI18N
                            new Object[] { property.getName() }));
                    nonfatalErrors.add(ex);
                    return false;
                }
            }
        }

        buf.append(indent);

        if (encodedValue != null) {
            addLeafElementOpenAttr(
                buf,
                XML_PROPERTY,
                new String[] {
                    ATTR_PROPERTY_NAME,
                    ATTR_PROPERTY_TYPE,
                    ATTR_PROPERTY_VALUE,
                    ATTR_PROPERTY_PRE_CODE,
                    ATTR_PROPERTY_POST_CODE },
                new String[] {
                    propertyName,
                    property.getValueType().getName(),
                    encodedValue,
                    property.getPreCode(),
                    property.getPostCode() });
        }
        else {
            addElementOpenAttr(
                buf,
                XML_PROPERTY,
                new String[] {
                    ATTR_PROPERTY_NAME,
                    ATTR_PROPERTY_TYPE,
                    ATTR_PROPERTY_EDITOR,
                    ATTR_PROPERTY_PRE_CODE,
                    ATTR_PROPERTY_POST_CODE },
                new String[] {
                    propertyName,
                    property.getValueType().getName(),
                    prEd.getClass().getName(),
                    property.getPreCode(),
                    property.getPostCode() });

            if (valueNode != null) {
                saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
            }
            else {
                buf.append(indent + ONE_INDENT);
                addLeafElementOpenAttr(
                    buf,
                    XML_SERIALIZED_PROPERTY_VALUE,
                    new String[] { ATTR_PROPERTY_VALUE },
                    new String[] { encodedSerializeValue });
            }
            buf.append(indent);
            addElementClose(buf, XML_PROPERTY);
        }
        return true;
    }

    private boolean saveValue(Object value,
                              Class valueType,
                              PropertyEditor prEd,
                              StringBuffer buf,
                              String indent)
    {
        String encodedValue = null;
        String encodedSerializeValue = null;
        org.w3c.dom.Node valueNode = null;

        if (prEd instanceof XMLPropertyEditor) {
            prEd.setValue(value);
            valueNode = ((XMLPropertyEditor)prEd).storeToXML(topDocument);
            if (valueNode == null) { // property editor refused to save the value
                PersistenceException ex = new PersistenceException(
                                   "Cannot save the property value"); // NOI18N
                String msg = FormUtils.getFormattedBundleString(
                                 "FMT_ERR_CannotSaveProperty2", // NOI18N
                                 new Object[] { prEd.getClass().getName() });
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                return false;
            }
        }
        else {
            encodedValue = encodePrimitiveValue(value);
            if (encodedValue == null) {
                try {
                    encodedSerializeValue = encodeValue(value);
                }
                catch (Exception ex) {
                    ErrorManager.getDefault().annotate(
                        ex,
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotSaveProperty3", // NOI18N
                            new Object[] { valueType.getClass().getName() }));
                    nonfatalErrors.add(ex);
                    return false;
                }
            }
        }

        buf.append(indent);

        if (encodedValue != null) {
            addLeafElementOpenAttr(
                buf,
                XML_VALUE,
                new String[] { ATTR_PROPERTY_TYPE, ATTR_PROPERTY_VALUE },
                new String[] { valueType.getName(), encodedValue });
        }
        else {
            addElementOpenAttr(
                buf,
                XML_VALUE,
                new String[] { ATTR_PROPERTY_TYPE, ATTR_PROPERTY_EDITOR },
                new String[] { valueType.getName(), prEd.getClass().getName() });

            if (valueNode != null) {
                saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
            }
            else {
                buf.append(indent + ONE_INDENT);
                addLeafElementOpenAttr(
                    buf,
                    XML_SERIALIZED_PROPERTY_VALUE,
                    new String[] { ATTR_PROPERTY_VALUE },
                    new String[] { encodedSerializeValue });
            }
            buf.append(indent);
            addElementClose(buf, XML_VALUE);
        }
        return true;
    }

    private void saveSyntheticProperties(RADComponent component, StringBuffer buf, String indent) {
        boolean anyProp = false;
        String indent2 = null;

        // compatibility hack for saving form's menu bar (part III)
        if (component instanceof RADVisualFormContainer) {
            RADMenuComponent menuComp =
                ((RADVisualFormContainer)component).getContainerMenu();
            if (menuComp != null) {
                buf.append(indent);
                addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
                indent2 = indent + ONE_INDENT;
                anyProp = true;

                buf.append(indent2);
                addLeafElementOpenAttr(buf,
                    XML_SYNTHETIC_PROPERTY,
                    new String[] { ATTR_PROPERTY_NAME,
                                   ATTR_PROPERTY_TYPE,
                                   ATTR_PROPERTY_VALUE },
                    new String[] { "menuBar", // NOI18N
                                   "java.lang.String", // NOI18N
                                   menuComp.getName() });
            }
        }

        Node.Property[] props = component.getSyntheticProperties();
        for (int i=0; i < props.length; i++) {
            Node.Property prop = props[i];

            if (!prop.canWrite())
                continue; // don't save read-only properties

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

            Object value = null;
            try {
                value = prop.getValue();
            }
            catch (Exception ex) {
                ErrorManager.getDefault().annotate(
                    ex,
                    FormUtils.getFormattedBundleString(
                        "FMT_ERR_CannotGetPropertyValue", // NOI18N
                        new Object[] { prop.getName() }));
                nonfatalErrors.add(ex);
                continue;
            }
            String valueType = prop.getValueType().getName();
            String encodedValue = encodePrimitiveValue(value);
            if (encodedValue == null) {
                try {
                    encodedValue = encodeValue(value);
                }
                catch (Exception ex) {
                    ErrorManager.getDefault().annotate(
                        ex,
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotSaveProperty", // NOI18N
                            new Object[] { prop.getName() }));
                    nonfatalErrors.add(ex);
                    continue;
                }
            }

            if (!anyProp) {
                buf.append(indent);
                addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
                indent2 = indent + ONE_INDENT;
                anyProp = true;
            }

            buf.append(indent2);
            addLeafElementOpenAttr(
                buf,
                XML_SYNTHETIC_PROPERTY,
                new String[] {
                    ATTR_PROPERTY_NAME,
                    ATTR_PROPERTY_TYPE,
                    ATTR_PROPERTY_VALUE,
                },
                new String[] {
                    prop.getName(),
                    valueType,
                    encodedValue,
                }
                );
        }

        if (anyProp) {
            buf.append(indent);
            addElementClose(buf, XML_SYNTHETIC_PROPERTIES);
        }
    }

    private void saveEvents(Event[] events, StringBuffer buf, String indent) {
        boolean anyEvent = false;
        String indent2 = null;
        StringBuffer strbuf;

        for (int i=0; i < events.length; i++) {
            Event event = events[i];
            if (!event.hasEventHandlers())
                continue;

            if (!anyEvent) {
                buf.append(indent);
                addElementOpen(buf, XML_EVENTS);
                indent2 = indent + ONE_INDENT;
                anyEvent = true;
            }

            strbuf = new StringBuffer(50);
            Class[] params = event.getListenerMethod().getParameterTypes();
            for (int j=0; j < params.length; j++) {
                strbuf.append(params[j].getName());
                if (j + 1 < params.length)
                    strbuf.append(","); // NOI18N
            }
            String paramString = strbuf.toString();

            strbuf = new StringBuffer(50);
            String[] handlers = event.getEventHandlers();
            for (int j=0; j < handlers.length; j++) {
                strbuf.append(handlers[j]);
                if (j + 1 < handlers.length)
                    strbuf.append(","); // NOI18N
            }
            String handlerString = strbuf.toString();

            buf.append(indent2);
            addLeafElementOpenAttr(
                buf,
                XML_EVENT,
                new String[] {
                    ATTR_EVENT_NAME,
                    ATTR_EVENT_LISTENER,
                    ATTR_EVENT_PARAMS,
                    ATTR_EVENT_HANDLER
                },
                new String[] {
                    event.getListenerMethod().getName(),
                    event.getListenerMethod().getDeclaringClass().getName(),
                    paramString,
                    handlerString
                }
            );
        }

        if (anyEvent) {
            buf.append(indent);
            addElementClose(buf, XML_EVENTS);
        }
    }

    private void saveAuxValues(Map auxValues, StringBuffer buf, String indent) {
        for (Iterator it = auxValues.keySet().iterator(); it.hasNext();) {
            String valueName =(String) it.next();
            Object value = auxValues.get(valueName);
            if (value == null) continue; // such values are not saved
            String valueType = value.getClass().getName();
            String encodedValue = encodePrimitiveValue(value);
            if (encodedValue == null) {
                try {
                    encodedValue = encodeValue(value);
                }
                catch (Exception ex) {
                    ErrorManager.getDefault().annotate(
                        ex,
                        FormUtils.getFormattedBundleString(
                            "FMT_ERR_CannotSaveProperty", // NOI18N
                            new Object[] { valueName }));
                    nonfatalErrors.add(ex);
                    continue;
                }
            }

            buf.append(indent);
            addLeafElementOpenAttr(
                buf,
                XML_AUX_VALUE,
                new String[] {
                    ATTR_AUX_NAME,
                    ATTR_AUX_VALUE_TYPE,
                    ATTR_AUX_VALUE },
                new String[] {
                    valueName,
                    valueType,
                    encodedValue
                }
            );
        }
    }

    private PropertyEditor createPropertyEditor(Class editorClass,
                                                Class propertyType,
                                                FormProperty property)
        throws InstantiationException,
               IllegalAccessException
    {
        PropertyEditor ed =
            editorClass.equals(RADConnectionPropertyEditor.class) ?
                new RADConnectionPropertyEditor(propertyType) :
                (PropertyEditor) editorClass.newInstance();

        if (property != null)
            property.getPropertyContext().initPropertyEditor(ed);
        else if (ed instanceof FormAwareEditor)
            ((FormAwareEditor)ed).setFormModel(formModel);

        return ed;
    }

    // ---------------------
    // The following code ensures persistence of code structure in XML. The
    // code is quite general except special hacks for meta components which
    // must be handled specially (as references) - as we don't save full code
    // yet but only its parts; components are saved separately. [This feature
    // is used only for saving/loading code of non-standard layout supports.]
    //
    // There are two possible ways how to save the code structure - to save
    // the code flow or the static structure.
    //
    // In the first case (code flow), a sequence of code statements is saved
    // (together with epxressions used by the statements). In the second case
    // (static structure), root code expressions are saved as trees including
    // all used expressions and all defined statements. Which style is used
    // is controlled by the codeFlow variable. [We use only code flow now.]

    // XML persistence of code structure - saving

    private void saveCodeExpression(CodeExpression exp,
                                    StringBuffer buf, String indent)
    {
        buf.append(indent);

        Object value = getExpressionsMap().get(exp);
        if (value != null) { // save expression reference only
            addLeafElementOpenAttr(buf,
                                   XML_CODE_EXPRESSION,
                                   new String[] { ATTR_EXPRESSION_ID },
                                   new String[] { value.toString() });
        }
        else { // save complete expression
            // create expression ID
            lastExpId++;
            String expId = Integer.toString(lastExpId);
            CodeVariable var = exp.getVariable();
            if (var != null)
                expId += "_" + var.getName(); // NOI18N
            getExpressionsMap().put(exp, expId);

            addElementOpenAttr(buf,
                               XML_CODE_EXPRESSION,
                               new String[] { ATTR_EXPRESSION_ID },
                               new String[] { expId });

            String subIndent = indent + ONE_INDENT;

            if (var != null)
                saveCodeVariable(var, buf, subIndent);

            saveExpressionOrigin(exp.getOrigin(), buf, subIndent);

            if (!codeFlow) {
                // if static code structure is being saved, statements are
                // saved inside their parent expressions
                Iterator it = CodeStructure.getDefinedStatementsIterator(exp);
                if (it.hasNext()) {
                    buf.append(subIndent);
                    addElementOpen(buf, XML_CODE_STATEMENTS);

                    String subSubIndent = subIndent + ONE_INDENT;
                    do {
                        saveCodeStatement((CodeStatement) it.next(),
                                          buf, subSubIndent);
                    }
                    while (it.hasNext());

                    buf.append(subIndent);
                    addElementClose(buf, XML_CODE_STATEMENTS);
                }
            }

            buf.append(indent);
            addElementClose(buf, XML_CODE_EXPRESSION);
        }
    }

    private void saveCodeVariable(CodeVariable var,
                                  StringBuffer buf, String indent)
    {
        buf.append(indent);
        if (getVariablesMap().get(var) != null) {
            addLeafElementOpenAttr(buf,
                                   XML_CODE_VARIABLE,
                                   new String[] { ATTR_VAR_NAME },
                                   new String[] { var.getName() });
        }
        else {
            addLeafElementOpenAttr(
                buf,
                XML_CODE_VARIABLE,
                new String[] { ATTR_VAR_NAME,
                               ATTR_VAR_TYPE,
                               ATTR_VAR_DECLARED_TYPE },
                new String[] { var.getName(),
                               Integer.toString(var.getType()),
                               var.getDeclaredType().getName() });

            getVariablesMap().put(var, var);
        }
    }

    private void saveExpressionOrigin(CodeExpressionOrigin origin,
                                      StringBuffer buf, String indent)
    {
        buf.append(indent);
        addElementOpen(buf, XML_CODE_ORIGIN);

        String subIndent = indent + ONE_INDENT;

        CodeExpression parentExp = origin.getParentExpression();
        if (parentExp != null)
            saveCodeExpression(parentExp, buf, subIndent);

        Object metaObject = origin.getMetaObject();
        if (metaObject != null)
            saveOriginMetaObject(metaObject, buf, subIndent);
        else
            saveValue(origin.getValue(), origin.getType(), null,
                      buf, subIndent);

        saveParameters(origin.getCreationParameters(), buf, subIndent);

        buf.append(indent);
        addElementClose(buf, XML_CODE_ORIGIN);
    }

    private void saveCodeStatement(CodeStatement statement,
                                   StringBuffer buf, String indent)
    {
        buf.append(indent);
        addElementOpen(buf, XML_CODE_STATEMENT);

        String subIndent = indent + ONE_INDENT;

        if (codeFlow) {
            // if code flow is being saved, also the parent expression of
            // the statement must be saved for it
            CodeExpression parentExp = statement.getParentExpression();
            if (parentExp != null)
                saveCodeExpression(parentExp, buf, subIndent);
        }

        Object metaObject = statement.getMetaObject();
        if (metaObject != null)
            saveStatementMetaObject(metaObject, buf, subIndent);

        saveParameters(statement.getStatementParameters(), buf, subIndent);

        buf.append(indent);
        addElementClose(buf, XML_CODE_STATEMENT);
    }

    private void saveOriginMetaObject(Object metaObject,
                                      StringBuffer buf, String indent)
    {
        if (metaObject instanceof Node.Property) {
            Node.Property property = (Node.Property) metaObject;
            Object value;
            try {
                value = property.getValue();
            }
            catch (Exception ex) { // should not happen
                org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
                return;
            }

            PropertyEditor prEd = property instanceof FormProperty ?
                                  ((FormProperty)property).getCurrentEditor() :
                                  property.getPropertyEditor();
            saveValue(value, property.getValueType(), prEd, buf,indent);
            return;
        }

        StringBuffer buf2 = new StringBuffer();
        String subIndent = indent + ONE_INDENT;
        String originType = null;

        if (metaObject instanceof Constructor) {
            Constructor ctor = (Constructor) metaObject;
            StringBuffer buf3 = new StringBuffer();
            Class[] paramTypes = ctor.getParameterTypes();

            for (int i=0; i < paramTypes.length; i++) {
                buf3.append(paramTypes[i].getName());
                if (i+1 < paramTypes.length)
                    buf3.append(", "); // NOI18N
            }

            buf2.append(subIndent);
            addLeafElementOpenAttr(
                buf2,
                XML_CODE_CONSTRUCTOR,
                new String[] { ATTR_MEMBER_CLASS,
                               ATTR_MEMBER_PARAMS },
                new String[] { ctor.getDeclaringClass().getName(),
                               buf3.toString() });

            originType = XML_CODE_CONSTRUCTOR;
        }

        // special code for handling meta component references
        else if (metaObject instanceof RADComponent) {
            RADComponent metacomp = (RADComponent) metaObject;

            buf2.append(subIndent);
            addLeafElementOpenAttr(
                buf2,
                XML_COMPONENT_REF,
                new String[] { ATTR_COMPONENT_NAME },
                new String[] { metacomp != formModel.getTopRADComponent() ?
                               metacomp.getName() : "." }); // NOI18N

            originType = XML_COMPONENT_REF;
        }

        else if (metaObject instanceof Method) {
            saveMethod((Method) metaObject, buf2, subIndent);
            originType = XML_CODE_METHOD;
        }

        else if (metaObject instanceof Field) {
            saveField((Field) metaObject, buf2, subIndent);
            originType = XML_CODE_FIELD;
        }

        if (originType == null)
            return; // unknown origin

        buf.append(indent);
        addElementOpenAttr(buf,
                           XML_ORIGIN_META_OBJECT,
                           new String[] { ATTR_META_OBJECT_TYPE },
                           new String[] { originType } );
        buf.append(buf2);
        buf.append(indent);
        addElementClose(buf, XML_ORIGIN_META_OBJECT);
    }

    private void saveStatementMetaObject(Object metaObject,
                                         StringBuffer buf, String indent)
    {
        StringBuffer buf2 = new StringBuffer();
        String subIndent = indent + ONE_INDENT;
        String statementType = null;

        if (metaObject instanceof Method) {
            saveMethod((Method) metaObject, buf2, subIndent);
            statementType = XML_CODE_METHOD;
        }
        else if (metaObject instanceof Field) {
            saveField((Field) metaObject, buf2, subIndent);
            statementType = XML_CODE_FIELD;
        }
        else if (metaObject instanceof CodeExpression) { // variable assignment
            CodeExpression exp = (CodeExpression) metaObject;
            if (exp.getVariable() != null) {
                saveCodeExpression(exp, buf2, subIndent);
                statementType = XML_CODE_EXPRESSION;
            }
        }
        // [... variable declaration statement]

        if (statementType == null)
            return; // unknown statement

        buf.append(indent);
        addElementOpenAttr(buf,
                           XML_STATEMENT_META_OBJECT,
                           new String[] { ATTR_META_OBJECT_TYPE },
                           new String[] { statementType } );
        buf.append(buf2);
        buf.append(indent);
        addElementClose(buf, XML_STATEMENT_META_OBJECT);
    }

    private void saveParameters(CodeExpression[] parameters,
                                StringBuffer buf, String indent)
    {
        if (parameters.length > 0) {
            buf.append(indent);
            addElementOpen(buf, XML_CODE_PARAMETERS);

            String subIndent = indent + ONE_INDENT;
            for (int i=0; i < parameters.length; i++)
                saveCodeExpression(parameters[i], buf, subIndent);

            buf.append(indent);
            addElementClose(buf, XML_CODE_PARAMETERS);
        }
    }

    private static void saveMethod(Method method,
                                   StringBuffer buf, String indent)
    {
        StringBuffer buf2 = new StringBuffer();
        Class[] paramTypes = method.getParameterTypes();

        for (int i=0; i < paramTypes.length; i++) {
            buf2.append(paramTypes[i].getName());
            if (i+1 < paramTypes.length)
                buf2.append(", "); // NOI18N
        }

        buf.append(indent);
        addLeafElementOpenAttr(
            buf,
            XML_CODE_METHOD,
            new String[] { ATTR_MEMBER_NAME,
                           ATTR_MEMBER_CLASS,
                           ATTR_MEMBER_PARAMS },
            new String[] { method.getName(),
                           method.getDeclaringClass().getName(),
                           buf2.toString() });
    }

    private static void saveField(Field field, StringBuffer buf, String indent)
    {
        buf.append(indent);
        addLeafElementOpenAttr(
            buf,
            XML_CODE_FIELD,
            new String[] { ATTR_MEMBER_NAME,
                           ATTR_MEMBER_CLASS },
            new String[] { field.getName(),
                           field.getDeclaringClass().getName() });
    }

    // -----------
    // XML persistence of code structure - loading

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

        CodeExpression exp = (CodeExpression) getExpressionsMap().get(expId);
        if (exp != null)
            return exp;

        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes == null)
            return null; // missing subnodes (expression content) error

        org.w3c.dom.Node variableNode = null;
        org.w3c.dom.Node originNode = null;
        org.w3c.dom.Node statementsNode = null;

        for (int i=0, n=childNodes.getLength(); i < n; i++) {
            org.w3c.dom.Node childNode = childNodes.item(i);
            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                continue; // ignore text nodes

            String nodeName = childNode.getNodeName();

            if (XML_CODE_VARIABLE.equals(nodeName))
                variableNode = childNode;
            else if (XML_CODE_ORIGIN.equals(nodeName))
                originNode = childNode;
            else if (!codeFlow && XML_CODE_STATEMENTS.equals(nodeName))
                statementsNode = childNode;
        }

        if (originNode == null)
            return null; // missing origin error

        CodeExpressionOrigin origin = loadExpressionOrigin(originNode);
        if (origin == null)
            return null; // origin loading error

        // special code for handling meta component references
        Object originMetaObject = origin.getMetaObject();
        if (originMetaObject instanceof RADComponent) {
            // use the expression from meta component
            exp = ((RADComponent)originMetaObject).getCodeExpression();
        }
        else { // create a new expression normally
            exp = getCodeStructure().createExpression(origin);

            CodeVariable var = variableNode != null ?
                               loadCodeVariable(variableNode) : null;
            if (var != null)
                getCodeStructure().attachExpressionToVariable(exp, var);
        }

        getExpressionsMap().put(expId, exp);

        if (statementsNode != null) {
            childNodes = statementsNode.getChildNodes();
            if (childNodes != null) {
                for (int i=0, n=childNodes.getLength(); i < n; i++) {
                    org.w3c.dom.Node childNode = childNodes.item(i);

                    if (XML_CODE_STATEMENT.equals(childNode.getNodeName()))
                        loadCodeStatement(childNode, exp);
                }
            }
        }

        return exp;
    }

    private CodeVariable loadCodeVariable(org.w3c.dom.Node node) {
        org.w3c.dom.NamedNodeMap attr = node.getAttributes();
        if (attr == null)
            return null; // no attributes error

        node = attr.getNamedItem(ATTR_VAR_NAME);
        if (node == null)
            return null; // missing variable name error
        String name = node.getNodeValue();

        CodeVariable var = getCodeStructure().getVariable(name);
        if (var != null)
            return var;

        node = attr.getNamedItem(ATTR_VAR_TYPE);
        if (node == null)
            return null; // missing variable type error
        int type = Integer.parseInt(node.getNodeValue());

        node = attr.getNamedItem(ATTR_VAR_DECLARED_TYPE);
        if (node == null)
            return null; // missing variable declared type error
        Class declaredType = null;

        try {
            declaredType = getClassFromString(node.getNodeValue());
        }
        catch (ClassNotFoundException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
        }
        if (declaredType == null)
            return null; // variable declared type loading error

        return getCodeStructure().createVariable(type, declaredType, name);
    }

    private CodeExpressionOrigin loadExpressionOrigin(org.w3c.dom.Node node) {
        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes == null)
            return null; // missing subnodes (origin content) error

        org.w3c.dom.Node parentExpNode = null;
        org.w3c.dom.Node metaObjectNode = null;
        org.w3c.dom.Node valueNode = null;
        org.w3c.dom.Node parametersNode = null;

        for (int i=0, n=childNodes.getLength(); i < n; i++) {
            org.w3c.dom.Node childNode = childNodes.item(i);
            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                continue; // ignore text nodes

            String nodeName = childNode.getNodeName();

            if (XML_CODE_EXPRESSION.equals(nodeName))
                parentExpNode = childNode;
            else if (XML_ORIGIN_META_OBJECT.equals(nodeName))
                metaObjectNode = childNode;
            else if (XML_VALUE.equals(nodeName))
                valueNode = childNode;
            else if (XML_CODE_PARAMETERS.equals(nodeName))
                parametersNode = childNode;
        }

        if (metaObjectNode == null && valueNode == null)
            return null; // missing origin metaobject or value error

        CodeExpression parentExp;
        if (parentExpNode != null) {
            parentExp = loadCodeExpression(parentExpNode);
            if (parentExp == null)
                return null; // parent expression loading error
        }
        else parentExp = null; // origin without parent expression

        CodeExpression[] parameters = parametersNode != null ?
                                        loadParameters(parametersNode) :
                                        CodeStructure.EMPTY_PARAMS;
        if (parameters == null)
            return null; // error loading parameters

        CodeExpressionOrigin origin = null;

        if (metaObjectNode != null) {
            String metaObjectType = getAttribute(metaObjectNode,
                                                  ATTR_META_OBJECT_TYPE);
            childNodes = metaObjectNode.getChildNodes();
            if (metaObjectType != null && childNodes != null) {
                for (int i=0, n=childNodes.getLength(); i < n; i++) {
                    org.w3c.dom.Node childNode = childNodes.item(i);

                    String nodeName = childNode.getNodeName();
                    if (!metaObjectType.equals(nodeName))
                        continue;

                    if (XML_VALUE.equals(nodeName)) {
                        valueNode = childNode;
                        break;
                    }

                    if (XML_CODE_CONSTRUCTOR.equals(nodeName)) {
                        org.w3c.dom.NamedNodeMap attr = childNode.getAttributes();
                        if (attr == null)
                            return null; // no attributes error

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

                        Class ctorClass;
                        try {
                            ctorClass = getClassFromString(node.getNodeValue());
                        }
                        catch (ClassNotFoundException ex) {
                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
                            return null; // constructor class loading error
                        }

                        node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
                        if (node == null)
                            return null; // missing constructor parameter types error

                        Class[] paramTypes;
                        StringTokenizer paramTokens =
                            new StringTokenizer(node.getNodeValue(), ", "); // NOI18N
                        List typeList = new ArrayList();
                        try {
                            while (paramTokens.hasMoreTokens()) {
                                typeList.add(getClassFromString(
                                                 paramTokens.nextToken()));
                            }
                            paramTypes = new Class[typeList.size()];
                            typeList.toArray(paramTypes);
                        }
                        catch (ClassNotFoundException ex) {
                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
                            return null; // parameters classes loading error
                        }

                        Constructor ctor;
                        try {
                            ctor = ctorClass.getConstructor(paramTypes);
                        }
                        catch (NoSuchMethodException ex) {
                            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
                            return null; // constructor not found error
                        }

                        origin = CodeStructure.createOrigin(ctor, parameters);
                        break;
                    }

                    // special code for handling meta component references
                    if (XML_COMPONENT_REF.equals(nodeName)) {
                        String name = getAttribute(childNode,
                                                    ATTR_COMPONENT_NAME);
                        if (name == null)
                            return null; // missing component name error

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

                        origin = comp.getCodeExpression().getOrigin();
                        break;
                    }

                    if (XML_CODE_METHOD.equals(nodeName)) {
                        Method m = loadMethod(childNode);
                        if (m == null)
                            return null; // method loading error

                        origin = CodeStructure.createOrigin(
                                                   parentExp, m, parameters);
                        break;
                    }

                    if (XML_CODE_FIELD.equals(nodeName)) {
                        Field f = loadField(childNode);
                        if (f == null)
                            return null; // field loading error

                        origin = CodeStructure.createOrigin(parentExp, f);
                        break;
                    }
                }
            }
        }

        if (origin == null) {
            if (valueNode == null)
                return null; // origin metaobject loading error

            String typeStr = getAttribute(valueNode, ATTR_PROPERTY_TYPE);
            if (typeStr == null)
                return null; // missing value type error

            Object editorOrValue = getPropertyEditorOrValue(valueNode);
            if (editorOrValue == NO_VALUE)
                return null; // value loading error

            Class valueType;
            try {
                valueType = getClassFromString(typeStr);
            }
            catch (Exception ex) { // does not happen
                return null; // value loading error
            }

            origin = editorOrValue instanceof PropertyEditor ?
                     FormCodeSupport.createOrigin(
                         valueType,
                         (PropertyEditor) editorOrValue) :
                     CodeStructure.createOrigin(
                         valueType,
                         editorOrValue,
                         editorOrValue != null ?
                             editorOrValue.toString() : "null"); // NOI18N
        }

        return origin;
    }

    private CodeStatement loadCodeStatement(org.w3c.dom.Node node,
                                            CodeExpression parentExp)
    {
        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes == null)
            return null; // missing subnodes (statement content) error

        org.w3c.dom.Node parentExpNode = null;
        org.w3c.dom.Node metaObjectNode = null;
        org.w3c.dom.Node parametersNode = null;

        for (int i=0, n=childNodes.getLength(); i < n; i++) {
            org.w3c.dom.Node childNode = childNodes.item(i);
            if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
                continue; // ignore text nodes

            String nodeName = childNode.getNodeName();

            if (XML_CODE_EXPRESSION.equals(nodeName)) {
                if (parentExp == null)
                    parentExpNode = childNode;
            }
            else if (XML_STATEMENT_META_OBJECT.equals(nodeName))
                metaObjectNode = childNode;
            else if (XML_CODE_PARAMETERS.equals(nodeName))
                parametersNode = childNode;
        }

        if (metaObjectNode == null)
            return null; // missing statement metaobject error

        if (parentExpNode != null) {
            parentExp = loadCodeExpression(parentExpNode);
            if (parentExp == null)
                return null; // parent expression loading error
        }

        CodeExpression[] parameters = parametersNode != null ?
                                        loadParameters(parametersNode) :
                                        CodeStructure.EMPTY_PARAMS;
        if (parameters == null)
            return null; // error loading parameters

        CodeStatement statement = null;

        String metaObjectType = getAttribute(metaObjectNode,
                                              ATTR_META_OBJECT_TYPE);
        childNodes = metaObjectNode.getChildNodes();
        if (metaObjectType != null && childNodes != null) {
            for (int i=0, n=childNodes.getLength(); i < n; i++) {
                org.w3c.dom.Node childNode = childNodes.item(i);

                String nodeName = childNode.getNodeName();
                if (!metaObjectType.equals(nodeName))
                    continue;

                if (XML_CODE_METHOD.equals(nodeName)) {
                    Method m = loadMethod(childNode);
                    if (m == null)
                        return null; // method loading error

                    statement = CodeStructure.createStatement(
                                                parentExp, m, parameters);
                    break;
                }

                if (XML_CODE_FIELD.equals(nodeName)) {
                    Field f = loadField(childNode);
                    if (f == null)
                        return null; // field loading error

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

                    statement = CodeStructure.createStatement(
                                                  parentExp, f, parameters[0]);
                    break;
                }

                if (XML_CODE_EXPRESSION.equals(nodeName)) {
                    // variable assignment
                    CodeExpression exp = loadCodeExpression(childNode);
                    if (exp != parentExp)
                        return null; // inconsistent data error

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

                    statement = var.getAssignment(exp);
                    break;
                }
            }
        }

        return statement;
    }

    private CodeExpression[] loadParameters(org.w3c.dom.Node node) {
        List paramList = new ArrayList();
        org.w3c.dom.NodeList childNodes = node.getChildNodes();
        if (childNodes != null) {
            for (int i=0, n=childNodes.getLength(); i < n; i++) {
                org.w3c.dom.Node childNode = childNodes.item(i);

                if (XML_CODE_EXPRESSION.equals(childNode.getNodeName())) {
                    CodeExpression exp = loadCodeExpression(childNode);
                    if (exp == null)
                        return null; // parameter loading error

                    paramList.add(exp);
                }
            }

            CodeExpression[] params = new CodeExpression[paramList.size()];
            paramList.toArray(params);
            return params;
        }
        else return CodeStructure.EMPTY_PARAMS;
    }

    private /*static */Method loadMethod(org.w3c.dom.Node node) {
        org.w3c.dom.NamedNodeMap attr = node.getAttributes();
        if (attr == null)
            return null; // no attributes error

        node = attr.getNamedItem(ATTR_MEMBER_NAME);
        if (node == null)
            return null; // missing method name error
        String name = node.getNodeValue();

        node = attr.getNamedItem(ATTR_MEMBER_CLASS);
        if (node == null)
            return null; // missing method class error

        Class methodClass;
        try {
            methodClass = getClassFromString(node.getNodeValue());
        }
        catch (ClassNotFoundException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            return null; // method class loading error
        }

        node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
        if (node == null)
            return null; // missing method parameter types error

        Class[] paramTypes;
        StringTokenizer paramTokens =
            new StringTokenizer(node.getNodeValue(), ", "); // NOI18N
        List typeList = new ArrayList();
        try {
            while (paramTokens.hasMoreTokens()) {
                typeList.add(getClassFromString(
                                 paramTokens.nextToken()));
            }
            paramTypes = new Class[typeList.size()];
            typeList.toArray(paramTypes);
        }
        catch (ClassNotFoundException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            return null; // parameters classes loading error
        }

        try {
            return methodClass.getMethod(name, paramTypes);
        }
        catch (NoSuchMethodException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            return null; // method not found error
        }
    }

    private /*static */Field loadField(org.w3c.dom.Node node) {
        org.w3c.dom.NamedNodeMap attr = node.getAttributes();
        if (attr == null)
            return null; // no attributes error

        node = attr.getNamedItem(ATTR_MEMBER_NAME);
        if (node == null)
            return null; // missing field name error
        String name = node.getNodeValue();

        node = attr.getNamedItem(ATTR_MEMBER_CLASS);
        if (node == null)
            return null; // missing field class error

        Class fieldClass;
        try {
            fieldClass = getClassFromString(node.getNodeValue());
        }
        catch (ClassNotFoundException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            return null; // field class loading error
        }

        try {
            return fieldClass.getField(name);
        }
        catch (NoSuchFieldException ex) {
            org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
            return null; // field not found error
        }
    }

    // -------

    private CodeStructure getCodeStructure() {
        return formModel.getCodeStructure();
    }

    // -------

    private Map getExpressionsMap() {
        if (expressions == null)
            expressions = new HashMap(100);
        return expressions;
    }

    private Map getVariablesMap() {
        if (savedVariables == null)
            savedVariables = new HashMap(50);
        return savedVariables;
    }

    private Map getComponentsMap() {
        if (loadedComponents == null)
            loadedComponents = new HashMap(50);
        return loadedComponents;
    }

    // -----------------
    // Value encoding and decoding methods

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

        org.w3c.dom.Node typeNode = attrs.getNamedItem(ATTR_PROPERTY_TYPE);
        org.w3c.dom.Node editorNode = attrs.getNamedItem(ATTR_PROPERTY_EDITOR);
        org.w3c.dom.Node valueNode = attrs.getNamedItem(ATTR_PROPERTY_VALUE);

        // get the type of stored property value
        if (typeNode == null) {
            PersistenceException ex = new PersistenceException(
                                        "Missing property type"); // NOI18N
            String msg = createLoadingErrorMessage(
                FormUtils.getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
                node);
            ErrorManager.getDefault().annotate(
                ex, ErrorManager.ERROR, null, msg, null, null);
            nonfatalErrors.add(ex);
            return NO_VALUE;
        }

        Class propertyType = null;
        Throwable t = null;
        try {
            propertyType = getClassFromString(typeNode.getNodeValue());
        }
        catch (Exception ex) {
            t = ex;
        }
        catch (LinkageError ex) {
            t = ex;
        }
        if (t != null) {
            String msg = createLoadingErrorMessage(
                FormUtils.getFormattedBundleString("FMT_ERR_CannotLoadClass2", // NOI18N
                                     new Object[] { typeNode.getNodeValue() }),
                node);
            ErrorManager.getDefault().annotate(t, msg);
            nonfatalErrors.add(t);
            return NO_VALUE;
        }

        // load the property editor class and create an instance of it
        PropertyEditor prEd = null;
        if (editorNode != null) {
            Class editorClass = null;
            try {
                editorClass = PersistenceObjectRegistry.loadClass(
                                         editorNode.getNodeValue(), formFile);
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            if (t != null) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getFormattedBundleString(
                        "FMT_ERR_CannotLoadClass3", // NOI18N
                        new Object[] { editorNode.getNodeValue() }),
                    node);
                ErrorManager.getDefault().annotate(t, msg);
                nonfatalErrors.add(t);
                return NO_VALUE;
            }

            try {
                prEd = createPropertyEditor(editorClass, propertyType, null);
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            if (t != null) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getFormattedBundleString(
                        "FMT_ERR_CannotCreateInstance2", // NOI18N
                        new Object[] { editorNode.getNodeValue() }),
                    node);
                ErrorManager.getDefault().annotate(t, msg);
                nonfatalErrors.add(t);
                return NO_VALUE;
            }
        }

        // load the property value
        Object value = NO_VALUE;
        if (valueNode != null) { // it is a primitive value
            try {
                value = decodePrimitiveValue(valueNode.getNodeValue(),
                                             propertyType);
                if (prEd != null)
                    prEd.setValue(value);
            }
            catch (IllegalArgumentException ex) {
                String msg = createLoadingErrorMessage(
                    FormUtils.getFormattedBundleString(
                        "FMT_ERR_CannotDecodePrimitive", // NOI18N
                        new Object[] { valueNode.getNodeValue(),
                                       propertyType.getName() }),
                    node);
                ErrorManager.getDefault().annotate(ex, msg);
                nonfatalErrors.add(ex);
                return NO_VALUE;
            }
        }
        else { // the value is serialized or saved by XMLPropertyEditor
            org.w3c.dom.NodeList children = node.getChildNodes();
            int n = children != null ? children.getLength() : 0;
            if (n > 0) {
                try {
                    boolean serialized = false;
                    // first try if the value is serialized
                    for (int i=0; i < n; i++) {
                        if (XML_SERIALIZED_PROPERTY_VALUE.equals(
                                    children.item(i).getNodeName()))
                        {   // here is the value serialized in XML
                            String serValue = getAttribute(children.item(i),
                                                        ATTR_PROPERTY_VALUE);
                            if (serValue != null) {
                                serialized = true;
                                value = decodeValue(serValue);
                                prEd = null;
                            }
                            break;
                        }
                    }

                    if (!serialized) {
                        if (prEd instanceof XMLPropertyEditor) {
                            // the value is saved by XMLPropertyEditor
                            for (int i=0; i < n; i++) {
                                if (children.item(i).getNodeType()
                                    == org.w3c.dom.Node.ELEMENT_NODE)
                                {   // here is the element of stored value
                                    ((XMLPropertyEditor)prEd).readFromXML(
                                                          children.item(i));
                                    value = prEd.getValue();
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (Exception ex) {
                    t = ex;
                }
                catch (LinkageError ex) {
                    t = ex;
                }
                if (t != null) {
                    String msg = createLoadingErrorMessage(
                        FormUtils.getBundleString(
                            "MSG_ERR_CannotReadPropertyValue"), // NOI18N
                        node);
                    ErrorManager.getDefault().annotate(t, msg);
                    nonfatalErrors.add(t);
                    return NO_VALUE;
                }
            }

            if (value == NO_VALUE) { // the value is missing
                PersistenceException ex = new PersistenceException(
                                           "Missing property value"); // NOI18N
                String msg = createLoadingErrorMessage(
                    FormUtils.getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
                    node);
                ErrorManager.getDefault().annotate(
                    ex, ErrorManager.ERROR, null, msg, null, null);
                nonfatalErrors.add(ex);
                return NO_VALUE;
            }
        }

        if (prEd != null)
            return prEd;

        return value;
    }

    private /*static */Class getClassFromString(String type)
        throws ClassNotFoundException
    {
        if ("int".equals(type)) // NOI18N
            return Integer.TYPE;
        else if ("short".equals(type)) // NOI18N
            return Short.TYPE;
        else if ("byte".equals(type)) // NOI18N
            return Byte.TYPE;
        else if ("long".equals(type)) // NOI18N
            return Long.TYPE;
        else if ("float".equals(type)) // NOI18N
            return Float.TYPE;
        else if ("double".equals(type)) // NOI18N
            return Double.TYPE;
        else if ("boolean".equals(type)) // NOI18N
            return Boolean.TYPE;
        else if ("char".equals(type)) // NOI18N
            return Character.TYPE;
        else {
            if (type.startsWith("[")) { // NOI18N
                // load array element class first to avoid failure
                for (int i=1, n=type.length(); i < n; i++) {
                    char c = type.charAt(i);
                    if (c == 'L' && type.endsWith(";")) { // NOI18N
                        String clsName = type.substring(i+1, n-1);
                        PersistenceObjectRegistry.loadClass(clsName, formFile);
                        break;
                    }
                    else if (c != '[')
                        break;
                }
            }

            return PersistenceObjectRegistry.loadClass(type, formFile);
        }
    }

    /** Decodes a primitive value of given type from the specified String.
     * @return decoded value
     * @exception IllegalArgumentException thrown if specified object is not
     *            of supported type
     */
    private Object decodePrimitiveValue(String encoded, Class type) {
        if ("null".equals(encoded)) // NOI18N
            return null;

        if (Integer.class.isAssignableFrom(type) || Integer.TYPE.equals(type))
            return Integer.valueOf(encoded);
        if (Short.class.isAssignableFrom(type) || Short.TYPE.equals(type))
            return Short.valueOf(encoded);
        if (Byte.class.isAssignableFrom(type) || Byte.TYPE.equals(type))
            return Byte.valueOf(encoded);
        if (Long.class.isAssignableFrom(type) || Long.TYPE.equals(type))
            return Long.valueOf(encoded);
        if (Float.class.isAssignableFrom(type) || Float.TYPE.equals(type))
            return Float.valueOf(encoded);
        if (Double.class.isAssignableFrom(type) || Double.TYPE.equals(type))
            return Double.valueOf(encoded);
        if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.equals(type))
            return Boolean.valueOf(encoded);
        if (Character.class.isAssignableFrom(type) || Character.TYPE.equals(type))
            return new Character(encoded.charAt(0));
        if (String.class.isAssignableFrom(type))
            return encoded;

        if (Class.class.isAssignableFrom(type)) {
            Throwable t;
            try {
                return PersistenceObjectRegistry.loadClass(encoded, formFile);
            }
            catch (Exception ex) {
                t = ex;
            }
            catch (LinkageError ex) {
                t = ex;
            }
            IllegalArgumentException ex = new IllegalArgumentException(
                                          "Cannot load class: "+encoded); // NOI18N
            ErrorManager.getDefault().annotate(ex, t);
            throw ex;
        }

        throw new IllegalArgumentException();
    }

    /** Encodes specified value into a String. Supported types are: 
    *
  • Class *
  • String *
  • Integer, Short, Byte, Long, Float, Double, Boolean, Character
* @return String containing encoded value or null if specified object is not of supported type */ private String encodePrimitiveValue(Object value) { if (value instanceof Integer || value instanceof Short || value instanceof Byte || value instanceof Long || value instanceof Float || value instanceof Double || value instanceof Boolean || value instanceof Character) return value.toString(); if (value instanceof String) return (String)value; if (value instanceof Class) return ((Class)value).getName(); if (value == null) return "null"; // NOI18N return null; // is not a primitive type } /** Decodes a value from String containing textual representation of * serialized stream. * @return decoded object * @exception IOException thrown if an error occurres during deserializing * the object */ public Object decodeValue(String strValue) throws IOException, ClassNotFoundException { if (strValue == null || strValue.length() == 0) return null; char[] bisChars = strValue.toCharArray(); byte[] bytes = new byte[bisChars.length]; String singleNum = ""; // NOI18N int count = 0; for (int i = 0; i < bisChars.length; i++) { if (',' == bisChars[i]) { bytes[count++] = Byte.parseByte(singleNum); singleNum = ""; // NOI18N } else { singleNum += bisChars[i]; } } // add the last byte bytes[count++] = Byte.parseByte(singleNum); ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 0, count); return new OIS(bis).readObject(); } /** Encodes specified value to a String containing textual representation of serialized stream. * @return String containing textual representation of the serialized object */ public static String encodeValue(Object value) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(value); oos.close(); byte[] bosBytes = bos.toByteArray(); StringBuffer buf = new StringBuffer(bosBytes.length*4); for (int i=0; i < bosBytes.length; i++) { if (i+1 < bosBytes.length) buf.append(bosBytes[i]+","); // NOI18N else buf.append(""+bosBytes[i]); // NOI18N } return buf.toString(); } // ObjectInputStream subclass for reading serialized property values private class OIS extends ObjectInputStream { public OIS(InputStream is) throws IOException { super(is); } protected Class resolveClass(ObjectStreamClass streamCls) throws IOException, ClassNotFoundException { String name = streamCls.getName(); if (name.startsWith("[")) { // NOI18N // load array element class first to avoid failure for (int i=1, n=name.length(); i < n; i++) { char c = name.charAt(i); if (c == 'L' && name.endsWith(";")) { // NOI18N String clsName = name.substring(i+1, n-1); PersistenceObjectRegistry.loadClass(clsName, formFile); break; } else if (c != '[') return super.resolveClass(streamCls); } } return PersistenceObjectRegistry.loadClass(name, formFile); } } // -------------------------------------------------------------------------------------- // Utility formatting methods private static void addElementOpen(StringBuffer buf, String elementName) { buf.append("<"); // NOI18N buf.append(elementName); buf.append(">\n"); // NOI18N } private static void addElementOpenAttr(StringBuffer buf, String elementName, String[] attrNames, String[] attrValues) { buf.append("<"); // NOI18N buf.append(elementName); for (int i = 0; i < attrNames.length; i++) { if (attrValues[i] == null) continue; buf.append(" "); // NOI18N buf.append(attrNames[i]); buf.append("=\""); // NOI18N buf.append(encodeToProperXML(attrValues[i])); buf.append("\""); // NOI18N } buf.append(">\n"); // NOI18N } private static void addLeafElementOpenAttr(StringBuffer buf, String elementName, String[] attrNames, String[] attrValues) { buf.append("<"); // NOI18N buf.append(elementName); for (int i = 0; i < attrNames.length; i++) { if (attrValues[i] == null) continue; buf.append(" "); // NOI18N buf.append(attrNames[i]); buf.append("=\""); // NOI18N buf.append(encodeToProperXML(attrValues[i])); buf.append("\""); // NOI18N } buf.append("/>\n"); // NOI18N } private static void addElementClose(StringBuffer buf, String elementName) { buf.append("\n"); // NOI18N } private void saveNodeIntoText(StringBuffer buf, org.w3c.dom.Node valueNode, String indent) { buf.append(indent); buf.append("<"); // NOI18N buf.append(valueNode.getNodeName()); org.w3c.dom.NamedNodeMap attributes = valueNode.getAttributes(); if (attributes != null) { ArrayList attribList = new ArrayList(attributes.getLength()); for (int i = 0; i < attributes.getLength(); i++) { attribList.add(attributes.item(i)); } // sort the attributes by attribute name // probably not necessary, but there is no guarantee that // the order of attributes will remain the same in DOM Collections.sort(attribList, new Comparator() { public int compare(Object o1, Object o2) { org.w3c.dom.Node n1 =(org.w3c.dom.Node)o1; org.w3c.dom.Node n2 =(org.w3c.dom.Node)o2; return n1.getNodeName().compareTo(n2.getNodeName()); } } ); for (Iterator it = attribList.iterator(); it.hasNext();) { org.w3c.dom.Node attrNode =(org.w3c.dom.Node)it.next(); String attrName = attrNode.getNodeName(); String attrValue = attrNode.getNodeValue(); buf.append(" "); // NOI18N buf.append(encodeToProperXML(attrName)); buf.append("=\""); // NOI18N buf.append(encodeToProperXML(attrValue)); buf.append("\""); // NOI18N } } // [PENDING - CNODES, TEXT NODES, ...] org.w3c.dom.NodeList children = valueNode.getChildNodes(); if ((children == null) ||(children.getLength() == 0)) { buf.append("/>\n"); // NOI18N } else { buf.append(">\n"); // NOI18N for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == org.w3c.dom.Node.TEXT_NODE) continue; // ignore text nodes saveNodeIntoText(buf, children.item(i), indent + ONE_INDENT); } buf.append(indent); buf.append("\n"); // NOI18N } } // -------------------------------------------------------------------------------------- // Utility DOM access methods private static String encodeToProperXML(String text) { if (text.indexOf('&') != -1) text = Utilities.replaceString(text, "&", "&"); // must be the first to prevent changes in the &XX; codes // NOI18N if (text.indexOf('<') != -1) text = Utilities.replaceString(text, "<", "<"); // NOI18N if (text.indexOf('>') != -1) text = Utilities.replaceString(text, ">", ">"); // NOI18N if (text.indexOf('\'') != -1) text = Utilities.replaceString(text, "\'", "'"); // NOI18N if (text.indexOf('\"') != -1) text = Utilities.replaceString(text, "\"", """); // NOI18N if (text.indexOf('\n') != -1) text = Utilities.replaceString(text, "\n", " "); // NOI18N if (text.indexOf('\t') != -1) text = Utilities.replaceString(text, "\t", " "); // NOI18N return text; } /** Finds first subnode of given node with specified name. * @param node the node whose subnode we are looking for * @param name requested name of the subnode * @return the found subnode or null if no such subnode exists */ private org.w3c.dom.Node findSubNode(org.w3c.dom.Node node, String name) { org.w3c.dom.NodeList children = node.getChildNodes(); if (children != null) { for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == org.w3c.dom.Node.TEXT_NODE) continue; // ignore text nodes if (name.equals(children.item(i).getNodeName())) { return children.item(i); } } } return null; } /** Finds all subnodes of given node with specified name. * @param node the node whose subnode we are looking for * @param name requested name of the subnode * @return array of the found subnodes */ private org.w3c.dom.Node[] findSubNodes(org.w3c.dom.Node node, String name) { org.w3c.dom.NodeList children = node.getChildNodes(); if (children == null) return new org.w3c.dom.Node[0]; ArrayList nodeList = new ArrayList(); for (int i=0,n=children.getLength(); i < n; i++) { org.w3c.dom.Node subnode = children.item(i); if (subnode.getNodeType() == org.w3c.dom.Node.TEXT_NODE) continue; // ignore text nodes if (name.equals(subnode.getNodeName())) nodeList.add(subnode); } org.w3c.dom.Node[] nodes = new org.w3c.dom.Node[nodeList.size()]; nodeList.toArray(nodes); return nodes; } /** Utility method to obtain given attribute value from specified Node. * @return attribute name or null if the attribute is not present */ private static String getAttribute(org.w3c.dom.Node node, String attrName) { org.w3c.dom.Node valueNode = node.getAttributes().getNamedItem(attrName); return valueNode != null ? valueNode.getNodeValue() : null; } // -------------- private String createLoadingErrorMessage(String errMsg, org.w3c.dom.Node node) { String nodeName = node.getNodeName(); List path = new ArrayList(); boolean leaf = true; boolean layout = false; boolean layoutConstr = false; boolean inOthers = false; do { String name = node.getNodeName(); if (XML_COMPONENT.equals(name) || XML_CONTAINER.equals(name) || XML_MENU_COMPONENT.equals(name) || XML_MENU_CONTAINER.equals(name) || XML_PROPERTY.equals(name) || XML_SYNTHETIC_PROPERTY.equals(name) || XML_AUX_VALUE.equals(name)) { name = getAttribute(node, "name"); // NOI18N if (name != null || !leaf) path.add(name); if (name != null) leaf = false; } else if (XML_NON_VISUAL_COMPONENTS.equals(name)) { inOthers = true; } else if (XML_LAYOUT.equals(name) || XML_LAYOUT_CODE.equals(name)) { path.add(FormUtils.getBundleString("CTL_PathLayout")); // NOI18N layout = true; } else if (XML_CONSTRAINTS.equals(name)) { path.add(FormUtils.getBundleString("CTL_PathLayoutConstraints")); // NOI18N layoutConstr = true; } node = node.getParentNode(); } while (node != null); if (inOthers) path.add(FormUtils.getBundleString("CTL_NonVisualComponents")); // NOI18N else if (formModel.getFormBaseClass() != null) path.add(FormUtils.getFormattedBundleString( "FMT_UnnamedComponentNodeName", // NOI18N new Object[] { Utilities.getShortClassName( formModel.getFormBaseClass()) })); if (path.isEmpty()) return errMsg; boolean property = XML_PROPERTY.equals(nodeName) || XML_SYNTHETIC_PROPERTY.equals(nodeName) || XML_AUX_VALUE.equals(nodeName); String format; if (!layoutConstr) if (!layout) format = property ? "FMT_ERR_LoadingComponentProperty" : // NOI18N "FMT_ERR_LoadingComponent"; // NOI18N else format = property ? "FMT_ERR_LoadingLayoutProperty" : // NOI18N "FMT_ERR_LoadingLayout"; // NOI18N else format = property ? "FMT_ERR_LoadingLayoutConstraintsProperty" : // NOI18N "FMT_ERR_LoadingLayoutConstraints"; // NOI18N String link = null; StringBuffer pathBuf = new StringBuffer(); for (int i=path.size()-1; i >= 0; i--) { pathBuf.append(path.get(i)); if (i > 0) { if (link == null) link = FormUtils.getBundleString("CTL_PathLink"); // NOI18N pathBuf.append(link); } } StringBuffer buf = new StringBuffer(); buf.append(FormUtils.getFormattedBundleString( format, new Object[] { pathBuf.toString() })); buf.append("\n"); // NOI18N buf.append(errMsg); return buf.toString(); } // -------------- private void raiseFormatVersion(String ver) { if (ver != formatVersion && (formatVersion == NB32_VERSION || (formatVersion == NB33_VERSION && ver == NB34_VERSION))) formatVersion = ver; } private boolean isSupportedFormatVersion(String ver) { return NB32_VERSION.equals(ver) || NB33_VERSION.equals(ver) || NB34_VERSION.equals(ver); } // -------------- // NB 3.2 compatibility - dealing with FormInfo /** In NB 3.2, the declared superclass in java source was not used, so * it could be changed incompatibly to the FormInfo type (typically to * some unrelated non-visual class, moving the generated code to an * innerclass). We try to detect this and use the FormInfo type * preferentially in such case. */ private static Class checkDeclaredSuperclass(Class declaredSuperclass, String formInfoName) { if (!java.awt.Component.class.isAssignableFrom(declaredSuperclass) && formInfoName != null) { Class formInfoType = getCompatibleFormClass(formInfoName); if (formInfoType != null) return formInfoType; } return declaredSuperclass; } /** * @return class corresponding to given FormInfo class name */ private static Class getCompatibleFormClass(String formInfoName) { if (formInfoName == null) return null; // no FormInfo name found in form file return getClassForKnownFormInfo(formInfoName); // ignore unknown FormInfo - it's deep past... } private static Class getCompatibleFormClass(Class formBaseClass) { return getClassForKnownFormInfo(getFormInfoForKnownClass(formBaseClass)); } // FormInfo names used in NB 3.2 private static final String[] defaultFormInfoNames = { "JFrameFormInfo", // NOI18N "JPanelFormInfo", // NOI18N "JDialogFormInfo", // NOI18N "JInternalFrameFormInfo", // NOI18N "JAppletFormInfo", // NOI18N "FrameFormInfo", // NOI18N "AppletFormInfo", // NOI18N "DialogFormInfo", // NOI18N "PanelFormInfo" }; // NOI18N private static Class getClassForKnownFormInfo(String infoName) { if (infoName == null) return null; int i = infoName.lastIndexOf('.'); String shortName = infoName.substring(i+1); if (defaultFormInfoNames[0].equals(shortName)) return javax.swing.JFrame.class; else if (defaultFormInfoNames[1].equals(shortName)) return javax.swing.JPanel.class; else if (defaultFormInfoNames[2].equals(shortName)) return javax.swing.JDialog.class; else if (defaultFormInfoNames[3].equals(shortName)) return javax.swing.JInternalFrame.class; else if (defaultFormInfoNames[4].equals(shortName)) return javax.swing.JApplet.class; else if (defaultFormInfoNames[5].equals(shortName)) return java.awt.Frame.class; else if (defaultFormInfoNames[6].equals(shortName)) return java.applet.Applet.class; else if (defaultFormInfoNames[7].equals(shortName)) return java.awt.Dialog.class; else if (defaultFormInfoNames[8].equals(shortName)) return java.awt.Panel.class; return null; } private static String getFormInfoForKnownClass(Class formType) { String shortName; if (javax.swing.JFrame.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[0]; else if (javax.swing.JPanel.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[1]; else if (javax.swing.JDialog.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[2]; else if (javax.swing.JInternalFrame.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[3]; else if (javax.swing.JApplet.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[4]; else if (java.awt.Frame.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[5]; else if (java.applet.Applet.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[6]; else if (java.awt.Dialog.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[7]; else if (java.awt.Panel.class.isAssignableFrom(formType)) shortName = defaultFormInfoNames[8]; else return null; return "org.netbeans.modules.form.forminfo." + shortName; // NOI18N } // -------- // NB 3.1 compatibility - layout persistence conversion tables private static final int LAYOUT_BORDER = 0; private static final int LAYOUT_FLOW = 1; private static final int LAYOUT_BOX = 2; private static final int LAYOUT_GRIDBAG = 3; private static final int LAYOUT_GRID = 4; private static final int LAYOUT_CARD = 5; private static final int LAYOUT_ABSOLUTE = 6; private static final int LAYOUT_NULL = 7; private static final int LAYOUT_JSCROLL = 8; private static final int LAYOUT_SCROLL = 9; private static final int LAYOUT_JSPLIT = 10; private static final int LAYOUT_JTAB = 11; private static final int LAYOUT_JLAYER = 12; private static final int LAYOUT_TOOLBAR = 13; private static final int LAYOUT_UNKNOWN = -1; private static final int LAYOUT_FROM_CODE = -2; private static final String[] layout31Names = { "org.netbeans.modules.form.compat2.layouts.DesignBorderLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignFlowLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignGridLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignCardLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.ScrollPaneSupportLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JLayeredPaneSupportLayout", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout" // NOI18N }; // fixed table, do not change! private static final String[] layout31ConstraintsNames = { "org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignFlowLayout$FlowConstraintsDescription", // NOI18N, "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout$BoxConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignGridLayout$GridConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout$JScrollPaneConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.ScrollPaneSupportLayout$ScrollPaneConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.support.JLayeredPaneSupportLayout$JLayeredPaneConstraintsDescription", // NOI18N "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout$BoxConstraintsDescription" // NOI18N }; // fixed table, do not change! private static final boolean[] reasonable31Constraints = { true, false, false, true, false, true, true, true, false, false, true, true, true, false }; // fixed table, do not change! private static final String[] supportedClassNames = { "java.awt.BorderLayout", // NOI18N "java.awt.FlowLayout", // NOI18N "javax.swing.BoxLayout", // NOI18N "java.awt.GridBagLayout", // NOI18N "java.awt.GridLayout", // NOI18N "java.awt.CardLayout", // NOI18N "org.netbeans.lib.awtextra.AbsoluteLayout", // NOI18N null, "javax.swing.JScrollPane", // NOI18N "java.awt.ScrollPane", // NOI18N "javax.swing.JSplitPane", // NOI18N "javax.swing.JTabbedPane", // NOI18N "javax.swing.JLayeredPane", // NOI18N "javax.swing.JToolBar" // NOI18N }; // fixed table, do not change! private static final String[][] layout31PropertyNames = { { "horizontalGap", "verticalGap" }, // BorderLayout // NOI18N { "alignment", "horizontalGap", "verticalGap" }, // FlowLayout // NOI18N { "axis" }, // BoxLayout // NOI18N { }, // GridBagLayout { "rows", "columns", "horizontalGap", "verticalGap" }, // GridLayout // NOI18N { "horizontalGap", "verticalGap" }, // CardLayout (ignoring "currentCard") // NOI18N { "useNullLayout" }, // AbsoluteLayout // NOI18N { "useNullLayout" }, // AbsoluteLayout // NOI18N { }, // JScrollPane { }, // ScrollPane { }, // JSplitPane { }, // JTabbedPane { }, // JLayeredPane { "axis" } // BoxLayout // NOI18N }; // fixed table, do not change! private static final String[][] layoutDelegatePropertyNames = { { "hgap", "vgap" }, // BorderLayout // NOI18N { "alignment", "hgap", "vgap" }, // FlowLayout // NOI18N { "axis" }, // BoxLayout // NOI18N { }, // GridBagLayout { "rows", "columns", "hgap", "vgap" }, // GridLayout // NOI18N { "hgap", "vgap" }, // CardLayout (ignoring "currentCard") // NOI18N { null }, // AbsoluteLayout { null }, // null layout { }, // JScrollPane { }, // ScrollPane { }, // JSplitPane { }, // JTabbedPane { }, // JLayeredPane { null } // JToolBar }; // fixed table, do not change! // methods and constructors for creating code structure private static Method setLayoutMethod; private static Method simpleAddMethod; private static Method addWithConstrMethod; private static Method addTabMethod1; private static Method addTabMethod2; private static Method addTabMethod3; private static Method setLeftComponentMethod; private static Method setRightComponentMethod; private static Method setTopComponentMethod; private static Method setBottomComponentMethod; private static Method setBoundsMethod; private static Method setViewportViewMethod; private static Constructor gridBagConstrConstructor; private static Constructor insetsConstructor; private static Constructor absoluteConstraintsConstructor; // Special static field holding last loaded layout index. This is hack for // dealing with multiple constraints types saved by NB 3.1 - we load only // constraints matching with the current layout. At time of loading // constraints, the layout is already loaded but the layout support is not // established yet, so the loadConstraints method cannot find out what the // current layout of container is. private static int layoutConvIndex = LAYOUT_UNKNOWN; }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.