0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.form;
0043:
0044: import java.beans.*;
0045: import java.io.*;
0046: import java.util.*;
0047: import java.lang.reflect.*;
0048:
0049: import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
0050: import org.openide.filesystems.FileLock;
0051: import org.openide.filesystems.FileObject;
0052: import org.openide.nodes.Node;
0053: import org.openide.util.Utilities;
0054: import org.openide.*;
0055: import org.openide.xml.XMLUtil;
0056:
0057: import com.sun.source.tree.ClassTree;
0058: import com.sun.source.tree.Tree;
0059: import com.sun.source.util.TreePath;
0060: import java.util.logging.Level;
0061: import java.util.logging.Logger;
0062: import javax.lang.model.element.Element;
0063: import javax.lang.model.element.ElementKind;
0064: import javax.lang.model.element.TypeElement;
0065: import org.netbeans.api.java.source.CancellableTask;
0066: import org.netbeans.api.java.source.CompilationController;
0067: import org.netbeans.api.java.source.JavaSource;
0068:
0069: import org.netbeans.modules.form.layoutsupport.*;
0070: import org.netbeans.modules.form.layoutsupport.delegates.*;
0071: import org.netbeans.modules.form.codestructure.*;
0072: import org.netbeans.modules.form.layoutdesign.LayoutModel;
0073: import org.netbeans.modules.form.layoutdesign.LayoutComponent;
0074: import org.netbeans.modules.form.layoutdesign.support.SwingLayoutBuilder;
0075:
0076: import org.netbeans.api.java.classpath.ClassPath;
0077: import org.openide.nodes.Node.Property;
0078: import org.openide.util.TopologicalSortException;
0079: import org.w3c.dom.NamedNodeMap;
0080:
0081: /**
0082: * XML persistence manager - responsible for saving/loading forms to/from XML.
0083: * The class contains lots of complicated code with many hacks ensuring full
0084: * compatibility of the format despite that many original classes already don't
0085: * exist (e.g. FormInfo and DesignLayout and subclasses).
0086: *
0087: * @author Ian Formanek, Tomas Pavek
0088: */
0089:
0090: public class GandalfPersistenceManager extends PersistenceManager {
0091: private static final String NB32_VERSION = "1.0"; // NOI18N
0092: private static final String NB33_VERSION = "1.1"; // NOI18N
0093: private static final String NB34_VERSION = "1.2"; // NOI18N
0094: private static final String NB50_VERSION = "1.3"; // NOI18N
0095: private static final String NB60_PRE_VERSION = "1.4"; // NOI18N
0096: private static final String NB60_VERSION = "1.5"; // NOI18N
0097: private static final String NB61_VERSION = "1.6"; // NOI18N
0098:
0099: // XML elements names
0100: static final String XML_FORM = "Form"; // NOI18N
0101: static final String XML_NON_VISUAL_COMPONENTS = "NonVisualComponents"; // NOI18N
0102: static final String XML_CONTAINER = "Container"; // NOI18N
0103: static final String XML_COMPONENT = "Component"; // NOI18N
0104: static final String XML_COMPONENT_REF = "ComponentRef"; // NOI18N
0105: static final String XML_MENU_COMPONENT = "MenuItem"; // NOI18N
0106: static final String XML_MENU_CONTAINER = "Menu"; // NOI18N
0107: static final String XML_LAYOUT = "Layout"; // NOI18N
0108: static final String XML_LAYOUT_CODE = "LayoutCode"; // NOI18N
0109: static final String XML_CONSTRAINTS = "Constraints"; // NOI18N
0110: static final String XML_CONSTRAINT = "Constraint"; // NOI18N
0111: static final String XML_SUB_COMPONENTS = "SubComponents"; // NOI18N
0112: static final String XML_EVENTS = "Events"; // NOI18N
0113: static final String XML_EVENT = "EventHandler"; // NOI18N
0114: static final String XML_PROPERTIES = "Properties"; // NOI18N
0115: static final String XML_PROPERTY = "Property"; // NOI18N
0116: static final String XML_VALUE = "Value"; // NOI18N
0117: static final String XML_SYNTHETIC_PROPERTY = "SyntheticProperty"; // NOI18N
0118: static final String XML_SYNTHETIC_PROPERTIES = "SyntheticProperties"; // NOI18N
0119: static final String XML_BINDING_PROPERTY = "BindingProperty"; // NOI18N
0120: static final String XML_SUBBINDING = "Subbinding"; // NOI18N
0121: static final String XML_BINDING_PARAMETER = "BindingParameter"; // NOI18N
0122: static final String XML_BINDING_PROPERTIES = "BindingProperties"; // NOI18N
0123: static final String XML_AUX_VALUES = "AuxValues"; // NOI18N
0124: static final String XML_AUX_VALUE = "AuxValue"; // NOI18N
0125: static final String XML_A11Y_PROPERTIES = "AccessibilityProperties"; // NOI18N
0126: static final String XML_SERIALIZED_PROPERTY_VALUE = "SerializedValue"; // NOI18N
0127: static final String XML_CODE_EXPRESSION = "CodeExpression"; // NOI18N
0128: static final String XML_CODE_VARIABLE = "CodeVariable"; // NOI18N
0129: static final String XML_CODE_ORIGIN = "ExpressionOrigin"; // NOI18N
0130: static final String XML_CODE_STATEMENT = "CodeStatement"; // NOI18N
0131: static final String XML_CODE_PARAMETERS = "Parameters"; // NOI18N
0132: static final String XML_CODE_STATEMENTS = "Statements"; // NOI18N
0133: static final String XML_ORIGIN_META_OBJECT = "ExpressionProvider"; // NOI18N
0134: static final String XML_STATEMENT_META_OBJECT = "StatementProvider"; // NOI18N
0135: static final String XML_CODE_CONSTRUCTOR = "CodeConstructor"; // NOI18N
0136: static final String XML_CODE_METHOD = "CodeMethod"; // NOI18N
0137: static final String XML_CODE_FIELD = "CodeField"; // NOI18N
0138: static final String XML_PROPERTY_BEAN = "PropertyBean"; // NOI18N
0139:
0140: // XML attributes names
0141: static final String ATTR_FORM_VERSION = "version"; // NOI18N
0142: static final String ATTR_MAX_FORM_VERSION = "maxVersion"; // NOI18N
0143: static final String ATTR_FORM_TYPE = "type"; // NOI18N
0144: static final String ATTR_COMPONENT_NAME = "name"; // NOI18N
0145: static final String ATTR_COMPONENT_CLASS = "class"; // NOI18N
0146: static final String ATTR_PROPERTY_NAME = "name"; // NOI18N
0147: static final String ATTR_PROPERTY_TYPE = "type"; // NOI18N
0148: static final String ATTR_PROPERTY_RES_KEY = "resourceKey"; // NOI18N
0149: static final String ATTR_PROPERTY_NORES = "noResource"; // NOI18N
0150: static final String ATTR_PROPERTY_EDITOR = "editor"; // NOI18N
0151: static final String ATTR_PROPERTY_VALUE = "value"; // NOI18N
0152: static final String ATTR_PROPERTY_PRE_CODE = "preCode"; // NOI18N
0153: static final String ATTR_PROPERTY_POST_CODE = "postCode"; // NOI18N
0154: static final String ATTR_BINDING_SOURCE = "source"; // NOI18N
0155: static final String ATTR_BINDING_TARGET = "target"; // NOI18N
0156: static final String ATTR_BINDING_SOURCE_PATH = "sourcePath"; // NOI18N
0157: static final String ATTR_BINDING_TARGET_PATH = "targetPath"; // NOI18N
0158: static final String ATTR_BINDING_UPDATE_STRATEGY = "updateStrategy"; // NOI18N
0159: static final String ATTR_BINDING_IMMEDIATELY = "immediately"; // NOI18N
0160: static final String ATTR_BINDING_PARAMETER_NAME = "name"; // NOI18N
0161: static final String ATTR_BINDING_PARAMETER_VALUE = "value"; // NOI18N
0162: static final String ATTR_EVENT_NAME = "event"; // NOI18N
0163: static final String ATTR_EVENT_LISTENER = "listener"; // NOI18N
0164: static final String ATTR_EVENT_PARAMS = "parameters"; // NOI18N
0165: static final String ATTR_EVENT_HANDLER = "handler"; // NOI18N
0166: static final String ATTR_AUX_NAME = "name"; // NOI18N
0167: static final String ATTR_AUX_VALUE = "value"; // NOI18N
0168: static final String ATTR_AUX_VALUE_TYPE = "type"; // NOI18N
0169: static final String ATTR_LAYOUT_CLASS = "class"; // NOI18N
0170: static final String ATTR_CONSTRAINT_LAYOUT = "layoutClass"; // NOI18N
0171: static final String ATTR_CONSTRAINT_VALUE = "value"; // NOI18N
0172: static final String ATTR_EXPRESSION_ID = "id"; // NOI18N
0173: static final String ATTR_VAR_NAME = "name"; // NOI18N
0174: static final String ATTR_VAR_TYPE = "type"; // NOI18N
0175: static final String ATTR_VAR_DECLARED_TYPE = "declaredType"; // NOI18N
0176: static final String ATTR_META_OBJECT_TYPE = "type"; // NOI18N
0177: static final String ATTR_MEMBER_CLASS = "class"; // NOI18N
0178: static final String ATTR_MEMBER_PARAMS = "parameterTypes"; // NOI18N
0179: static final String ATTR_MEMBER_NAME = "name"; // NOI18N
0180:
0181: private static final String ONE_INDENT = " "; // NOI18N
0182: private static final Object NO_VALUE = new Object();
0183: private static final String FORM_SETTINGS_PREFIX = "FormSettings_"; // NOI18N
0184:
0185: private org.w3c.dom.Document topDocument = XMLUtil.createDocument(
0186: "topDocument", null, null, null); // NOI18N
0187:
0188: private FileObject formFile;
0189:
0190: private FormModel formModel;
0191:
0192: private List<Throwable> nonfatalErrors;
0193:
0194: // name of the menu bar component loaded as AUX value of the top component
0195: private String mainMenuBarName;
0196:
0197: // maps of properties that cannot be loaded before component is added to
0198: // parent container, or container is filled with sub-components
0199: private Map<RADComponent, java.util.List<Object>> parentDependentProperties;
0200: private Map<RADComponent, java.util.List<Object>> childrenDependentProperties;
0201:
0202: // map of loaded components (not necessarily added to FormModel yet)
0203: private Map<String, RADComponent> loadedComponents;
0204:
0205: private List<Object> bindingProperties; // <property, name of source, name of target, MetaBinding, node>
0206: private ConnectedProperties connectedProperties;
0207:
0208: // XML persistence of code structure
0209: private Map<Object, Object> expressions; // map of expressions/IDs already saved/loaded
0210: private int lastExpId; // CodeExpression ID counter (for saving)
0211: private Set<CodeVariable> savedVariables; // set of code variables already saved
0212: private boolean codeFlow = true; // we can save/load either code flow
0213: // or static code structure
0214:
0215: private Boolean newLayout; // whether a new layout support was loaded
0216:
0217: /** This method is used to check if the persistence manager can read the
0218: * given form (if it understands the form file format).
0219: * @return true if this persistence manager can load the form
0220: * @exception PersistenceException if any unexpected problem occurred
0221: */
0222: public boolean canLoadForm(FormDataObject formObject)
0223: throws PersistenceException {
0224: FileObject formFile = formObject.getFormEntry().getFile();
0225: org.w3c.dom.Element mainElement;
0226: try {
0227: org.w3c.dom.Document doc = XMLUtil.parse(
0228: new org.xml.sax.InputSource(formFile.getURL()
0229: .toExternalForm()), false, false, null,
0230: null);
0231:
0232: mainElement = doc.getDocumentElement();
0233: } catch (IOException ex) {
0234: throw new PersistenceException(ex, "Cannot open form file"); // NOI18N
0235: } catch (org.xml.sax.SAXException e) {
0236: // ignore SAXException?
0237: e.printStackTrace();
0238: return false;
0239: }
0240:
0241: return mainElement != null
0242: && XML_FORM.equals(mainElement.getTagName());
0243: }
0244:
0245: /** This method loads the form from given data object.
0246: * @param formObject FormDataObject representing the form files
0247: * @param formModel FormModel to be filled with loaded data
0248: * @param nonfatalErrors List to be filled with errors occurred during
0249: * loading which are not fatal (but should be reported)
0250: * @exception PersistenceException if some fatal problem occurred which
0251: * prevents loading the form
0252: */
0253: public void loadForm(FormDataObject formObject,
0254: FormModel formModel, List<Throwable> nonfatalErrors)
0255: throws PersistenceException {
0256: loadForm(formObject.getFormEntry().getFile(), formObject
0257: .getPrimaryFile(), formModel, nonfatalErrors);
0258: }
0259:
0260: /** This method loads the form from given data object.
0261: *
0262: * @param formFile form file corresponding to java file
0263: * @param javaFile java file
0264: * @param formModel FormModel to be filled with loaded data
0265: * @param nonfatalErrors List to be filled with errors occurred during
0266: * loading which are not fatal (but should be reported)
0267: * @return form model of the loaded form.
0268: * @exception PersistenceException if some fatal problem occurred which
0269: * prevents loading the form
0270: */
0271: public FormModel loadForm(FileObject formFile, FileObject javaFile,
0272: FormModel formModel, List<Throwable> nonfatalErrors)
0273: throws PersistenceException {
0274: this .formFile = formFile;
0275:
0276: boolean underTest = ((javaFile == null) || (javaFile
0277: .equals(formFile)));
0278:
0279: if (formModel == null) {
0280: formModel = new FormModel();
0281: }
0282: org.w3c.dom.Element mainElement;
0283: try { // parse document, get the main element
0284: mainElement = XMLUtil.parse(
0285: new org.xml.sax.InputSource(formFile.getURL()
0286: .toExternalForm()), false, false, null,
0287: null).getDocumentElement();
0288: } catch (IOException ex) {
0289: PersistenceException pe = new PersistenceException(ex,
0290: "Cannot open form file"); // NOI18N
0291: ErrorManager.getDefault().annotate(ex,
0292: FormUtils.getBundleString("MSG_ERR_LoadingErrors")); // NOI18N
0293: throw pe;
0294: } catch (org.xml.sax.SAXException ex) {
0295: PersistenceException pe = new PersistenceException(ex,
0296: "Invalid XML in form file"); // NOI18N
0297: ErrorManager.getDefault().annotate(ex,
0298: FormUtils.getBundleString("MSG_ERR_InvalidXML")); // NOI18N
0299: throw pe;
0300: }
0301:
0302: // check the main element
0303: if (mainElement == null
0304: || !XML_FORM.equals(mainElement.getTagName())) {
0305: PersistenceException ex = new PersistenceException(
0306: "Missing expected main XML element"); // NOI18N
0307: ErrorManager
0308: .getDefault()
0309: .annotate(
0310: ex,
0311: ErrorManager.ERROR,
0312: null,
0313: FormUtils
0314: .getBundleString("MSG_ERR_MissingMainElement"), // NOI18N
0315: null, null);
0316: throw ex;
0317: }
0318:
0319: // check the form version
0320: String versionString = mainElement
0321: .getAttribute(ATTR_FORM_VERSION);
0322: if (!isSupportedFormatVersion(versionString)) {
0323: PersistenceException ex = new PersistenceException(
0324: "Unsupported form version"); // NOI18N
0325: ErrorManager.getDefault()
0326: .annotate(
0327: ex,
0328: ErrorManager.ERROR,
0329: null,
0330: FormUtils.getFormattedBundleString(
0331: "FMT_ERR_UnsupportedVersion", // NOI18N
0332: new Object[] { versionString }),
0333: null, null);
0334: throw ex;
0335: }
0336: formModel.setCurrentVersionLevel(FormModel.FormVersion.BASIC);
0337: FormModel.FormVersion formatVersion = formVersionForVersionString(versionString);
0338: if (formatVersion != null) {
0339: formModel.raiseVersionLevel(formatVersion, formatVersion);
0340: }
0341: String maxVersionString = mainElement
0342: .getAttribute(ATTR_MAX_FORM_VERSION);
0343: FormModel.FormVersion maxFormatVersion = formVersionForVersionString(maxVersionString);
0344: if (maxFormatVersion == null && maxVersionString != null
0345: && maxVersionString.length() > 0) {
0346: // specified in form file, but unknown max version
0347: maxFormatVersion = FormModel.LATEST_VERSION;
0348: }
0349: formModel.setMaxVersionLevel(maxFormatVersion);
0350:
0351: // --------
0352: // get the form base class and set it to FormModel
0353: String declaredSuperclassName = null;
0354: Class formBaseClass = null;
0355: Throwable formBaseClassEx = null;
0356:
0357: // get the formerly used FormInfo type (to be used as fallback alternative)
0358: String formInfoName = mainElement.getAttribute(ATTR_FORM_TYPE);
0359: if ("".equals(formInfoName)) // NOI18N
0360: formInfoName = null; // not available
0361:
0362: if (!underTest) { // try declared superclass from java source first
0363: // (don't scan java source in tests, we only use the basic form types)
0364: try {
0365: declaredSuperclassName = getSuperClassName(javaFile);
0366: if (declaredSuperclassName != null) {
0367: Class designClass = getFormDesignClass(declaredSuperclassName);
0368: if (designClass == null) {
0369: Class<?> super class = FormUtils.loadClass(
0370: declaredSuperclassName, formFile);
0371: designClass = getFormDesignClass(super class);
0372: if (designClass == null) {
0373: formBaseClass = checkDeclaredSuperclass(
0374: super class, formInfoName);
0375: if (formBaseClass != super class
0376: && !underTest) {
0377: System.err
0378: .println(FormUtils
0379: .getFormattedBundleString(
0380: "FMT_IncompatibleFormTypeWarning", // NOI18N
0381: new Object[] { javaFile
0382: .getName() }));
0383: }
0384: } else {
0385: formBaseClass = designClass;
0386: if (!super class
0387: .isAssignableFrom(designClass)) {
0388: System.err
0389: .println("WARNING: Design class not compatible with declared form base class:"); // NOI18N
0390: System.err.println("-> "
0391: + designClass.getName()
0392: + " is not subclass of "
0393: + super class.getName()); // NOI18N
0394: }
0395: }
0396: } else {
0397: formBaseClass = designClass;
0398: }
0399: }
0400: if (formBaseClass != null) {
0401: formModel.setFormBaseClass(formBaseClass);
0402: // Force creation of the default instance in the correct L&F context
0403: BeanSupport.getDefaultInstance(formBaseClass);
0404: }
0405: } catch (Exception ex) {
0406: formBaseClassEx = ex;
0407: } catch (LinkageError ex) {
0408: formBaseClassEx = ex;
0409: }
0410: }
0411:
0412: if (formModel.getFormBaseClass() == null) {
0413: // using superclass declared in java source failed, so try to use
0414: // some well-known substitute class instead
0415: Class substClass = null;
0416:
0417: if (formBaseClass != null) // try to honor the declared superclass
0418: substClass = getCompatibleFormClass(formBaseClass);
0419:
0420: if (substClass == null && formInfoName != null) // fall back to FormInfo type
0421: substClass = getCompatibleFormClass(formInfoName);
0422:
0423: if (substClass != null) { // succeeded, there is a substitute class
0424: try {
0425: formModel.setFormBaseClass(substClass);
0426:
0427: if (!underTest) { // print a warning about using fallback type (OK for tests)
0428: String msg = FormUtils
0429: .getFormattedBundleString(
0430: "FMT_FormTypeWarning", // NOI18N
0431: new Object[] {
0432: javaFile.getName(),
0433: substClass.getName(),
0434: declaredSuperclassName != null ? declaredSuperclassName
0435: : "<unknown class>" }); // NOI18N
0436: System.err.println(msg);
0437: if (formBaseClassEx != null)
0438: formBaseClassEx.printStackTrace();
0439: }
0440: } catch (Exception ex) { // should not happen for the substitute types
0441: ex.printStackTrace();
0442: } catch (LinkageError ex) { // should not happen for the substitute types
0443: ex.printStackTrace();
0444: }
0445: }
0446:
0447: if (formModel.getFormBaseClass() == null) {
0448: // after all, we still cannot determine the form base class
0449: String annotation;
0450: if (declaredSuperclassName != null) {
0451: // the class from java source at least can be loaded, but
0452: // cannot be used as the form type; no substitute available
0453: annotation = FormUtils.getFormattedBundleString(
0454: "FMT_ERR_InvalidBaseClass", // NOI18N
0455: new Object[] { declaredSuperclassName });
0456: } else { // cannot determine form base class at all;
0457: // no substitute available
0458: annotation = FormUtils
0459: .getBundleString("MSG_ERR_CannotDetermineBaseClass"); // NOI18N
0460: }
0461:
0462: PersistenceException ex;
0463: if (formBaseClassEx != null) {
0464: ex = new PersistenceException(formBaseClassEx,
0465: "Invalid form base class"); // NOI18N
0466: ErrorManager.getDefault().annotate(formBaseClassEx,
0467: annotation);
0468: } else {
0469: ex = new PersistenceException(
0470: "Invalid form base class"); // NOI18N
0471: ErrorManager.getDefault().annotate(ex,
0472: ErrorManager.ERROR, null, annotation, null,
0473: null);
0474: }
0475: throw ex;
0476: }
0477: }
0478: // base class set
0479: // ---------
0480:
0481: // initial cleanup
0482: if (loadedComponents != null)
0483: loadedComponents.clear();
0484: if (expressions != null)
0485: expressions.clear();
0486: mainMenuBarName = null;
0487: parentDependentProperties = null;
0488: childrenDependentProperties = null;
0489: bindingProperties = null;
0490: connectedProperties = null;
0491:
0492: this .formModel = formModel;
0493: this .nonfatalErrors = nonfatalErrors;
0494: this .newLayout = null;
0495:
0496: formModel.setName(javaFile.getName());
0497:
0498: RADComponent topComp = formModel.getTopRADComponent();
0499: if (topComp != null) { // load the main form component
0500: loadComponent(mainElement, topComp, null);
0501: } else {
0502: // Load form settings of bean form
0503: org.w3c.dom.NodeList childNodes = mainElement
0504: .getChildNodes();
0505: for (int i = 0; i < childNodes.getLength(); i++) {
0506: org.w3c.dom.Node childNode = childNodes.item(i);
0507: if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
0508: continue; // ignore text nodes
0509: String nodeName = childNode.getNodeName();
0510: if (XML_AUX_VALUES.equals(nodeName)) {
0511: loadAuxValues(childNode, null);
0512: }
0513: }
0514: }
0515:
0516: // load "Other Components"
0517: loadNonVisuals(mainElement);
0518:
0519: // compatibility hack for loading form's menu bar, part 3
0520: if (mainMenuBarName != null) {
0521: RADComponent menuBar = getComponentsMap().get(
0522: mainMenuBarName);
0523: if (menuBar != null && menuBar.getParentComponent() == null
0524: && topComp instanceof RADVisualFormContainer) {
0525: formModel.removeComponentImpl(menuBar, false);
0526: ((RADVisualFormContainer) topComp).add(menuBar);
0527: }
0528: }
0529:
0530: // set default variable modifiers for ther form
0531: FormSettings settings = formModel.getSettings();
0532: boolean local = settings.getVariablesLocal();
0533: int modifiers = settings.getVariablesModifier();
0534: int type = local ? (CodeVariable.LOCAL
0535: | (modifiers & CodeVariable.FINAL) | CodeVariable.EXPLICIT_DECLARATION)
0536: : modifiers | CodeVariable.FIELD;
0537: formModel.getCodeStructure().setDefaultVariableType(type);
0538:
0539: if (bindingProperties != null) {
0540: setBindingProperties();
0541: bindingProperties = null;
0542: }
0543:
0544: if (connectedProperties != null) {
0545: connectedProperties.setValues();
0546: connectedProperties = null;
0547: }
0548:
0549: if (Boolean.TRUE.equals(newLayout) && (!underTest)) { // for sure update project classpath with layout extensions library
0550: FormEditor.updateProjectForNaturalLayout(formModel);
0551: }
0552: if (!Boolean.FALSE.equals(newLayout)) {
0553: formModel.setFreeDesignDefaultLayout(true);
0554: }
0555:
0556: // make sure form max version is properly set after loading
0557: formatVersion = formModel.getCurrentVersionLevel();
0558: maxFormatVersion = formModel.getMaxVersionLevel();
0559: if (maxFormatVersion == null
0560: || formatVersion.ordinal() > maxFormatVersion.ordinal()) {
0561: // max version needs to be at least as high as the actual version
0562: formModel.setMaxVersionLevel(formatVersion);
0563: }
0564:
0565: // final cleanup
0566: parentDependentProperties = null;
0567: childrenDependentProperties = null;
0568: mainMenuBarName = null;
0569: if (expressions != null)
0570: expressions.clear();
0571: if (loadedComponents != null)
0572: loadedComponents.clear();
0573: this .formModel = null;
0574: return formModel;
0575: }
0576:
0577: /**
0578: * gets superclass if the 'extends' keyword is present
0579: */
0580: private static String getSuperClassName(final FileObject javaFile)
0581: throws IllegalArgumentException, IOException {
0582: final String javaFileName = javaFile.getName();
0583: final String[] result = new String[1];
0584: JavaSource js = JavaSource.forFileObject(javaFile);
0585: js.runUserActionTask(
0586: new CancellableTask<CompilationController>() {
0587: public void cancel() {
0588: }
0589:
0590: public void run(CompilationController controller)
0591: throws Exception {
0592: controller
0593: .toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
0594: ClassTree formClass = null;
0595: for (Tree t : controller.getCompilationUnit()
0596: .getTypeDecls()) {
0597: if (t.getKind() == Tree.Kind.CLASS) {
0598: ClassTree ct = (ClassTree) t;
0599: if (isClass(ct, controller)) {
0600: if (javaFileName
0601: .equals(ct.getSimpleName()
0602: .toString())) {
0603: formClass = ct;
0604: break;
0605: }
0606: if (formClass == null
0607: || ct
0608: .getModifiers()
0609: .getFlags()
0610: .contains(
0611: javax.lang.model.element.Modifier.PUBLIC)) {
0612: formClass = ct; // find at least something (if not matching file name - issue 105626)
0613: }
0614: }
0615: }
0616: }
0617: if (formClass != null) {
0618: if (!javaFileName.equals(formClass
0619: .getSimpleName().toString())) {
0620: // may happen during refactoring - see issue 105626
0621: Logger
0622: .getLogger(
0623: GandalfPersistenceManager.class
0624: .getName())
0625: .log(
0626: Level.INFO,
0627: "Form class not matching the java file name: " // NOI18N
0628: + formClass
0629: .getSimpleName()
0630: .toString()
0631: + " in "
0632: + javaFileName
0633: + ".java"); // NOI18N
0634: }
0635: Tree super T = formClass.getExtendsClause();
0636: if (super T != null) {
0637: TreePath super TPath = controller
0638: .getTrees()
0639: .getPath(
0640: controller
0641: .getCompilationUnit(),
0642: super T);
0643: Element super El = controller.getTrees()
0644: .getElement(super TPath);
0645: if (super El != null
0646: && super El.getKind() == ElementKind.CLASS) {
0647: result[0] = controller
0648: .getElements()
0649: .getBinaryName(
0650: (TypeElement) super El)
0651: .toString(); // .getQualifiedName()
0652: }
0653: } else {
0654: result[0] = "java.lang.Object"; // NOI18N
0655: }
0656: }
0657: }
0658: }, true);
0659: return result[0];
0660: }
0661:
0662: private static boolean isClass(ClassTree ct,
0663: CompilationController controller) {
0664: return !controller.getTreeUtilities().isEnum(ct)
0665: && !controller.getTreeUtilities().isInterface(ct)
0666: && !controller.getTreeUtilities().isAnnotation(ct);
0667: }
0668:
0669: private void setBindingProperties() {
0670: FormEditor.getBindingSupport(formModel);
0671: Iterator iter = bindingProperties.iterator();
0672: while (iter.hasNext()) {
0673: BindingProperty property = (BindingProperty) iter.next();
0674: String sourceName = (String) iter.next();
0675: String targetName = (String) iter.next();
0676: MetaBinding value = (MetaBinding) iter.next();
0677: org.w3c.dom.Node propNode = (org.w3c.dom.Node) iter.next();
0678:
0679: RADComponent source = formModel
0680: .findRADComponent(sourceName);
0681: RADComponent target = formModel
0682: .findRADComponent(targetName);
0683:
0684: if ((source == null) || (target == null)) {
0685: // PENDING error handling
0686: continue;
0687: }
0688:
0689: try {
0690: value.setSource(source);
0691: value.setTarget(target);
0692: property.setValue(value);
0693: } catch (Exception ex) {
0694: String msg = createLoadingErrorMessage(
0695: FormUtils
0696: .getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
0697: propNode);
0698: ErrorManager.getDefault().annotate(ex, msg);
0699: nonfatalErrors.add(ex);
0700: continue;
0701: }
0702: }
0703: }
0704:
0705: private void loadNonVisuals(org.w3c.dom.Node node)
0706: throws PersistenceException {
0707: org.w3c.dom.Node nonVisualsNode = findSubNode(node,
0708: XML_NON_VISUAL_COMPONENTS);
0709: org.w3c.dom.NodeList childNodes = nonVisualsNode == null ? null
0710: : nonVisualsNode.getChildNodes();
0711: List<RADComponent> list = new ArrayList<RADComponent>();
0712:
0713: if (childNodes != null) {
0714: for (int i = 0; i < childNodes.getLength(); i++) {
0715: org.w3c.dom.Node subnode = childNodes.item(i);
0716: if (subnode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
0717: continue; // ignore text nodes
0718:
0719: RADComponent comp = restoreComponent(subnode, null);
0720: if (comp != null)
0721: list.add(comp);
0722: }
0723: }
0724:
0725: RADComponent[] nonVisualComps = new RADComponent[list.size()];
0726: list.toArray(nonVisualComps);
0727: formModel.getModelContainer().initSubComponents(nonVisualComps);
0728: }
0729:
0730: // recognizes, creates, initializes and loads a meta component
0731: private RADComponent restoreComponent(org.w3c.dom.Node node,
0732: RADComponent parentComponent) throws PersistenceException {
0733: org.w3c.dom.NamedNodeMap attrs = node.getAttributes();
0734: if (attrs == null) { // should not be null even if there are no attributes
0735: PersistenceException ex = new PersistenceException(
0736: "Missing attributes of component element"); // NOI18N
0737: nonfatalErrors.add(ex);
0738: return null;
0739: }
0740:
0741: org.w3c.dom.Node classNode = attrs
0742: .getNamedItem(ATTR_COMPONENT_CLASS);
0743: org.w3c.dom.Node nameNode = attrs
0744: .getNamedItem(ATTR_COMPONENT_NAME);
0745: String className = classNode != null ? classNode.getNodeValue()
0746: : null;
0747: String compName = nameNode != null ? nameNode.getNodeValue()
0748: : null;
0749:
0750: if (className == null) {
0751: PersistenceException ex = new PersistenceException(
0752: "Missing component class name"); // NOI18N
0753: String msg = createLoadingErrorMessage(FormUtils
0754: .getBundleString("MSG_ERR_MissingClass"), // NOI18N
0755: node);
0756: ErrorManager.getDefault().annotate(ex, ErrorManager.ERROR,
0757: null, msg, null, null);
0758: nonfatalErrors.add(ex);
0759: return null;
0760: }
0761:
0762: // first load the component class
0763: Class<?> compClass = null;
0764: Throwable compEx = null;
0765: try {
0766: compClass = PersistenceObjectRegistry.loadClass(className,
0767: formFile);
0768: // Force creation of the default instance in the correct L&F context
0769: BeanSupport.getDefaultInstance(compClass);
0770: } catch (Exception ex) {
0771: compClass = InvalidComponent.class;
0772: compEx = ex;
0773: } catch (LinkageError ex) {
0774: compClass = InvalidComponent.class;
0775: compEx = ex;
0776: }
0777: if (compEx != null) { // loading the component class failed
0778: String msg = createLoadingErrorMessage(FormUtils
0779: .getFormattedBundleString(
0780: "FMT_ERR_CannotLoadClass", // NOI18N
0781: new Object[] { className }), node);
0782: ErrorManager.getDefault().annotate(compEx, msg);
0783: nonfatalErrors.add(compEx);
0784: }
0785:
0786: compEx = null;
0787: // create a new metacomponent
0788: RADComponent newComponent;
0789: String nodeName = node.getNodeName();
0790:
0791: if (XML_COMPONENT.equals(nodeName)) {
0792: if (compClass == InvalidComponent.class) {
0793: if (parentComponent instanceof RADVisualContainer) {
0794: newComponent = new RADVisualComponent();
0795: } else {
0796: newComponent = new RADComponent();
0797: }
0798: } else {
0799: if (FormUtils.isVisualizableClass(compClass)) {
0800: newComponent = new RADVisualComponent();
0801: } else {
0802: newComponent = new RADComponent();
0803: }
0804: }
0805: } else if (XML_MENU_COMPONENT.equals(nodeName)) {
0806: if (RADVisualComponent.getMenuType(compClass) != null) {
0807: newComponent = new RADVisualComponent();
0808: } else {
0809: newComponent = new RADMenuItemComponent();
0810: }
0811: } else if (XML_MENU_CONTAINER.equals(nodeName)) {
0812: if (RADVisualComponent.getMenuType(compClass) != null) {
0813: newComponent = new RADVisualContainer();
0814: } else {
0815: newComponent = new RADMenuComponent();
0816: }
0817: } else if (XML_CONTAINER.equals(nodeName)) {
0818: if (compClass == InvalidComponent.class) {
0819: newComponent = new RADVisualContainer();
0820: } else {
0821: if (java.awt.Container.class
0822: .isAssignableFrom(compClass))
0823: newComponent = new RADVisualContainer();
0824: else
0825: newComponent = new RADContainer();
0826: }
0827: } else {
0828: PersistenceException ex = new PersistenceException(
0829: "Unknown component element"); // NOI18N
0830: ErrorManager.getDefault().annotate(
0831: ex,
0832: ErrorManager.ERROR,
0833: null,
0834: FormUtils.getFormattedBundleString(
0835: "FMT_ERR_UnknownElement", // NOI18N
0836: new Object[] { nodeName }), null, null);
0837: nonfatalErrors.add(ex);
0838: return null;
0839: }
0840:
0841: // initialize the metacomponent
0842: try {
0843: if (compClass == InvalidComponent.class) {
0844: newComponent.setValid(false);
0845: newComponent.setMissingClassName(className);
0846: }
0847: newComponent.initialize(formModel);
0848: newComponent.setStoredName(compName);
0849: newComponent.initInstance(compClass);
0850: newComponent.setInModel(true);
0851: } catch (Exception ex) {
0852: compEx = ex;
0853: } catch (LinkageError ex) {
0854: compEx = ex;
0855: }
0856: if (compEx != null) { // creating component instance failed
0857: String msg = createLoadingErrorMessage(FormUtils
0858: .getFormattedBundleString(
0859: "FMT_ERR_CannotCreateInstance", // NOI18N
0860: new Object[] { className }), node);
0861: ErrorManager.getDefault().annotate(compEx, msg);
0862: nonfatalErrors.add(compEx);
0863: return null;
0864: }
0865:
0866: getComponentsMap().put(compName, newComponent);
0867:
0868: // load the metacomponent (properties, events, layout, etc)
0869: loadComponent(node, newComponent, parentComponent);
0870:
0871: return newComponent;
0872: }
0873:
0874: private void loadComponent(org.w3c.dom.Node node,
0875: RADComponent component, RADComponent parentComponent)
0876: throws PersistenceException {
0877: org.w3c.dom.NodeList childNodes = node.getChildNodes();
0878: if (childNodes == null)
0879: return;
0880:
0881: org.w3c.dom.Node layoutNode = null;
0882: org.w3c.dom.Node layoutCodeNode = null;
0883: org.w3c.dom.Node subCompsNode = null;
0884: org.w3c.dom.Node constraintsNode = null;
0885:
0886: for (int i = 0; i < childNodes.getLength(); i++) {
0887: org.w3c.dom.Node childNode = childNodes.item(i);
0888: if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
0889: continue; // ignore text nodes
0890:
0891: String nodeName = childNode.getNodeName();
0892:
0893: if (XML_PROPERTIES.equals(nodeName)
0894: || XML_A11Y_PROPERTIES.equals(nodeName)) {
0895: loadComponentProperties(childNode, component, nodeName);
0896: } else if (XML_EVENTS.equals(nodeName)) {
0897: loadEvents(childNode, component);
0898: } else if (XML_CONSTRAINTS.equals(nodeName)) {
0899: constraintsNode = childNode;
0900: } else if (XML_LAYOUT.equals(nodeName)) {
0901: if (layoutCodeNode == null)
0902: layoutNode = childNode;
0903: } else if (XML_LAYOUT_CODE.equals(nodeName)) {
0904: layoutCodeNode = childNode;
0905: layoutNode = null;
0906: } else if (XML_SUB_COMPONENTS.equals(nodeName)) {
0907: subCompsNode = childNode;
0908: } else if (XML_AUX_VALUES.equals(nodeName)) {
0909: loadAuxValues(childNode, component);
0910: } else if (XML_SYNTHETIC_PROPERTIES.equals(nodeName)) {
0911: loadSyntheticProperties(childNode, component);
0912: } else if (XML_BINDING_PROPERTIES.equals(nodeName)) {
0913: loadBindingProperties(childNode, component);
0914: }
0915: // ignore unknown elements?
0916: }
0917:
0918: // if the loaded component is a visual component in a visual contianer,
0919: // then load NB 3.1 layout constraints for it
0920: if (component instanceof RADVisualComponent
0921: && parentComponent instanceof RADVisualContainer
0922: && layoutConvIndex != LAYOUT_FROM_CODE) {
0923: CodeExpression compExp = component.getCodeExpression();
0924: LayoutSupportManager layoutSupport = ((RADVisualContainer) parentComponent)
0925: .getLayoutSupport();
0926:
0927: org.w3c.dom.Node[] constrNodes = constraintsNode != null ? findSubNodes(
0928: constraintsNode, XML_CONSTRAINT)
0929: : null;
0930:
0931: boolean constraintsLoaded = false;
0932:
0933: if (constrNodes != null && constrNodes.length > 0) {
0934: // NB 3.1 used to save all constraints ever set. We must
0935: // go through all of them, but only those of current layout
0936: // will be loaded.
0937: for (int i = 0; !constraintsLoaded
0938: && i < constrNodes.length; i++)
0939: constraintsLoaded = loadConstraints(constrNodes[i],
0940: compExp, layoutSupport);
0941: }
0942:
0943: if (!constraintsLoaded)
0944: setupDefaultComponentCode(compExp, layoutSupport);
0945: }
0946:
0947: ComponentContainer container = // is this component a container?
0948: component instanceof ComponentContainer ? (ComponentContainer) component
0949: : null;
0950: if (container == null) { // this component is not a container
0951: if (parentComponent == null) // this is a root component - load resource properties
0952: ResourceSupport.loadInjectedResources(component);
0953: return;
0954: }
0955:
0956: // we continue in loading container
0957:
0958: RADVisualContainer visualContainer = // is it a visual container?
0959: component instanceof RADVisualContainer ? (RADVisualContainer) component
0960: : null;
0961:
0962: if (visualContainer != null)
0963: visualContainer.setOldLayoutSupport(true);
0964:
0965: int convIndex = LAYOUT_UNKNOWN;
0966: if (visualContainer != null) {
0967: if (layoutNode != null) {
0968: // load container layout properties saved in NB 3.1 format;
0969: // these properties are loaded before subcomponents
0970: convIndex = loadLayout(layoutNode, visualContainer
0971: .getLayoutSupport());
0972: } else if (layoutCodeNode != null) {
0973: convIndex = LAYOUT_FROM_CODE;
0974: }
0975: }
0976:
0977: // load subcomponents
0978: RADComponent[] childComponents;
0979: childNodes = subCompsNode != null ? subCompsNode
0980: .getChildNodes() : null;
0981: if (childNodes != null) {
0982: List<RADComponent> list = new ArrayList<RADComponent>();
0983: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
0984: org.w3c.dom.Node componentNode = childNodes.item(i);
0985: if (componentNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
0986: continue; // ignore text nodes
0987:
0988: // hack for dealing with multiple constraints saved by NB 3.1
0989: layoutConvIndex = convIndex;
0990:
0991: RADComponent newComp = restoreComponent(componentNode,
0992: component);
0993:
0994: if (newComp != null)
0995: list.add(newComp);
0996: }
0997:
0998: childComponents = new RADComponent[list.size()];
0999: list.toArray(childComponents);
1000: } else
1001: childComponents = new RADComponent[0];
1002:
1003: if (visualContainer != null && layoutCodeNode != null) {
1004: // load complete layout code (both for container and components);
1005: // this container doesn't use NB 3.1 format for saving layout data
1006: loadLayoutCode(layoutCodeNode);
1007: }
1008:
1009: if (visualContainer != null) {
1010: Throwable layoutEx = null;
1011: boolean layoutInitialized = false;
1012: LayoutSupportManager layoutSupport = visualContainer
1013: .getLayoutSupport();
1014:
1015: if (convIndex == LAYOUT_NATURAL) {
1016: LayoutModel layoutModel = formModel.getLayoutModel();
1017: Map<String, String> nameToIdMap = new HashMap<String, String>();
1018: for (int i = 0; i < childComponents.length; i++) {
1019: RADComponent comp = childComponents[i];
1020: nameToIdMap.put(comp.getName(), comp.getId());
1021: }
1022: try {
1023: layoutModel.loadContainerLayout(visualContainer
1024: .getId(), layoutNode.getChildNodes(),
1025: nameToIdMap);
1026: visualContainer.setOldLayoutSupport(false);
1027: layoutSupport = null;
1028: layoutInitialized = true;
1029: newLayout = Boolean.TRUE;
1030: } catch (Exception ex) {
1031: // error occurred - treat this container as with unknown layout
1032: layoutModel
1033: .changeContainerToComponent(visualContainer
1034: .getId());
1035: layoutEx = ex;
1036: }
1037: visualContainer.initSubComponents(childComponents);
1038: } else if (convIndex >= 0 || layoutCodeNode != null) {
1039: // initialize layout support from restored code
1040: try {
1041: layoutInitialized = layoutSupport
1042: .prepareLayoutDelegate(true, true);
1043: } catch (Exception ex) {
1044: layoutEx = ex;
1045: } catch (LinkageError ex) {
1046: layoutEx = ex;
1047: }
1048: // subcomponents are set after reading from code [for some reason...]
1049: visualContainer.initSubComponents(childComponents);
1050: if (layoutInitialized) { // successfully initialized - build the primary container
1051: try { // some weird problems might occur - see issue 67890
1052: layoutSupport.updatePrimaryContainer();
1053: }
1054: // can't do anything reasonable on failure, just log stack trace
1055: catch (Exception ex) {
1056: ErrorManager.getDefault().notify(
1057: ErrorManager.INFORMATIONAL, ex);
1058: } catch (Error ex) {
1059: ErrorManager.getDefault().notify(
1060: ErrorManager.INFORMATIONAL, ex);
1061: }
1062: }
1063: } else if (layoutNode == null) { // Issue 63394, 68753: Bean form that is container
1064: // Issue 70369: Container saved with unknown layout
1065: // Swing menus go here as well
1066: // default init - not reading from code - need the subcomponents set
1067: visualContainer.initSubComponents(childComponents);
1068: try {
1069: // (default init also builds the primary container)
1070: layoutInitialized = layoutSupport
1071: .prepareLayoutDelegate(false, true);
1072: if (!layoutInitialized) { // not known to the old support (e.g. has GroupLayout)
1073: // (but we are sure the container instance is empty)
1074: java.awt.Container cont = layoutSupport
1075: .getPrimaryContainerDelegate();
1076: if (SwingLayoutBuilder
1077: .isRelevantContainer(cont)) {
1078: // acknowledged by SwingLayoutBuilder - this is new layout
1079: visualContainer.setOldLayoutSupport(false);
1080: formModel.getLayoutModel()
1081: .addRootComponent(
1082: new LayoutComponent(
1083: visualContainer
1084: .getId(),
1085: true));
1086: layoutSupport = null;
1087: newLayout = Boolean.TRUE;
1088: } else {
1089: layoutSupport
1090: .setUnknownLayoutDelegate(false);
1091: System.err
1092: .println("[WARNING] Unknown layout in "
1093: + createLoadingErrorMessage(
1094: (String) null, node) // NOI18N
1095: + " ("
1096: + component.getBeanClass()
1097: .getName() + ")"); // NOI18N
1098: }
1099: layoutInitialized = true;
1100: }
1101: } catch (Exception ex) {
1102: layoutEx = ex;
1103: }
1104: }
1105:
1106: if (!layoutInitialized) {
1107: if (layoutEx != null) { // layout initialization failed
1108: org.w3c.dom.Node errNode;
1109: if (layoutNode != null)
1110: errNode = layoutNode;
1111: else if (layoutCodeNode != null)
1112: errNode = layoutCodeNode;
1113: else
1114: errNode = node;
1115:
1116: String msg = createLoadingErrorMessage(
1117: FormUtils
1118: .getBundleString("MSG_ERR_LayoutInitFailed"), // NOI18N
1119: errNode);
1120: ErrorManager.getDefault().annotate(layoutEx, msg);
1121: nonfatalErrors.add(layoutEx);
1122: } else { // no LayoutSupportDelegate found
1123: org.w3c.dom.Node errNode;
1124: if (layoutNode != null)
1125: errNode = layoutNode;
1126: else if (layoutCodeNode != null)
1127: errNode = layoutCodeNode;
1128: else
1129: errNode = node;
1130:
1131: String msg = createLoadingErrorMessage(
1132: FormUtils
1133: .getBundleString("MSG_ERR_NoLayoutSupportFound"), // NOI18N
1134: errNode);
1135:
1136: PersistenceException ex = new PersistenceException(
1137: "No layout support found"); // NOI18N
1138: ErrorManager.getDefault().annotate(ex,
1139: ErrorManager.ERROR, null, msg, null, null);
1140: nonfatalErrors.add(ex);
1141: }
1142: layoutSupport
1143: .setUnknownLayoutDelegate(layoutCodeNode != null);
1144: }
1145:
1146: if (layoutSupport != null && newLayout == null) {
1147: newLayout = Boolean.FALSE;
1148: }
1149: } else { // non-visual container (e.g. AWT menu)
1150: container.initSubComponents(childComponents);
1151: }
1152:
1153: // hack for properties that can't be set until the component is added
1154: // to the parent container
1155: for (RADComponent childcomp : childComponents) {
1156: List postProps;
1157: if (parentDependentProperties != null
1158: && (postProps = parentDependentProperties
1159: .get(childcomp)) != null) {
1160: for (Iterator it = postProps.iterator(); it.hasNext();) {
1161: RADProperty prop = (RADProperty) it.next();
1162: Object propValue = it.next();
1163: try {
1164: prop.setValue(propValue);
1165: } catch (Exception ex) { // ignore
1166: String msg = createLoadingErrorMessage(
1167: FormUtils
1168: .getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
1169: node);
1170: ErrorManager.getDefault().annotate(ex, msg);
1171: nonfatalErrors.add(ex);
1172: }
1173: }
1174: }
1175: // here it is also safe to load resource properties into sub-component
1176: ResourceSupport.loadInjectedResources(childcomp);
1177: }
1178:
1179: // hack for properties that can't be set until all subcomponents
1180: // are added to the container
1181: List postProps;
1182: if (childrenDependentProperties != null
1183: && (postProps = childrenDependentProperties
1184: .get(component)) != null) {
1185: for (Iterator it = postProps.iterator(); it.hasNext();) {
1186: RADProperty prop = (RADProperty) it.next();
1187: Object propValue = it.next();
1188: try {
1189: prop.setValue(propValue);
1190: } catch (Exception ex) { // ignore
1191: String msg = createLoadingErrorMessage(
1192: FormUtils
1193: .getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
1194: node);
1195: ErrorManager.getDefault().annotate(ex, msg);
1196: nonfatalErrors.add(ex);
1197: }
1198: }
1199: }
1200:
1201: if (parentComponent == null) // this is a root component
1202: ResourceSupport.loadInjectedResources(component);
1203: }
1204:
1205: private boolean loadConstraints(org.w3c.dom.Node node,
1206: CodeExpression compExp, LayoutSupportManager layoutSupport) {
1207: int convIndex = -1;
1208: String layout31ConstraintName = node != null ? getAttribute(
1209: node, ATTR_CONSTRAINT_VALUE) : null;
1210: if (layout31ConstraintName != null)
1211: for (int i = 0; i < layout31ConstraintsNames.length; i++)
1212: if (layout31ConstraintName
1213: .equals(layout31ConstraintsNames[i])) {
1214: convIndex = i;
1215: break;
1216: }
1217:
1218: // skip constraints saved by NB 3.1 which are not for the current layout
1219: if (convIndex < 0
1220: || (layoutConvIndex >= 0 && convIndex != layoutConvIndex))
1221: return false;
1222:
1223: org.w3c.dom.Node constrNode = null;
1224: org.w3c.dom.NamedNodeMap constrAttr = null;
1225:
1226: if (/*convIndex >= 0 &&*/reasonable31Constraints[convIndex]) {
1227: org.w3c.dom.NodeList children = node.getChildNodes();
1228: if (children != null)
1229: for (int i = 0, n = children.getLength(); i < n; i++) {
1230: org.w3c.dom.Node cNode = children.item(i);
1231: if (cNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
1232: constrNode = cNode;
1233: constrAttr = cNode.getAttributes();
1234: break;
1235: }
1236: }
1237: }
1238:
1239: if (constrNode == null)
1240: return false;
1241:
1242: try { // obligatory try/catch block for finding methods and constructors
1243:
1244: CodeStructure codeStructure = layoutSupport
1245: .getCodeStructure();
1246: CodeExpression contCodeExp = layoutSupport
1247: .getContainerCodeExpression();
1248: CodeExpression contDelCodeExp = layoutSupport
1249: .getContainerDelegateCodeExpression();
1250:
1251: if (convIndex == LAYOUT_BORDER) {
1252: if (!"BorderConstraints".equals(constrNode
1253: .getNodeName())) // NOI18N
1254: return false; // should not happen
1255:
1256: node = constrAttr.getNamedItem("direction"); // NOI18N
1257: if (node != null) {
1258: String strValue = node.getNodeValue();
1259: // create add method statement
1260: CodeStructure.createStatement(contDelCodeExp,
1261: getAddWithConstrMethod(),
1262: new CodeExpression[] {
1263: compExp,
1264: codeStructure.createExpression(
1265: String.class, strValue,
1266: strValue) });
1267: }
1268: }
1269:
1270: else if (convIndex == LAYOUT_GRIDBAG) {
1271: if (!"GridBagConstraints".equals(constrNode
1272: .getNodeName())) // NOI18N
1273: return false; // should not happen
1274:
1275: // create GridBagConstraints constructor expression
1276: if (gridBagConstrConstructor == null)
1277: gridBagConstrConstructor = java.awt.GridBagConstraints.class
1278: .getConstructor(new Class[0]);
1279:
1280: CodeExpression constrExp = codeStructure
1281: .createExpression(gridBagConstrConstructor,
1282: CodeStructure.EMPTY_PARAMS);
1283:
1284: // create statements for GridBagConstraints fields
1285: String[] gbcAttrs = new String[] { "gridX", "gridY",
1286: "gridWidth", "gridHeight", // NOI18N
1287: "fill", "ipadX", "ipadY", // NOI18N
1288: "anchor", "weightX", "weightY" }; // NOI18N
1289: String[] gbcFields = new String[] { "gridx", "gridy",
1290: "gridwidth", "gridheight", // NOI18N
1291: "fill", "ipadx", "ipady", // NOI18N
1292: "anchor", "weightx", "weighty" }; // NOI18N
1293:
1294: for (int i = 0; i < gbcAttrs.length; i++) {
1295: node = constrAttr.getNamedItem(gbcAttrs[i]);
1296: if (node != null) {
1297: Class valueType;
1298: Object value;
1299: String strValue = node.getNodeValue();
1300: if (i < 8) { // treat as int
1301: valueType = Integer.TYPE;
1302: value = Integer.valueOf(strValue);
1303: } else { // treat as double
1304: valueType = Double.TYPE;
1305: value = Double.valueOf(strValue);
1306: }
1307:
1308: CodeStructure.createStatement(constrExp,
1309: java.awt.GridBagConstraints.class
1310: .getField(gbcFields[i]),
1311: codeStructure.createExpression(
1312: valueType, value, strValue));
1313: }
1314: }
1315:
1316: // Insets
1317: CodeExpression[] insetsParams = new CodeExpression[4];
1318: String[] insetsAttrs = new String[] { "insetsTop",
1319: "insetsLeft", "insetsBottom", "insetsRight" }; // NOI18N
1320:
1321: for (int i = 0; i < insetsAttrs.length; i++) {
1322: node = constrAttr.getNamedItem(insetsAttrs[i]);
1323: String strValue = node != null ? node
1324: .getNodeValue() : "0"; // NOI18N
1325: insetsParams[i] = codeStructure.createExpression(
1326: Integer.TYPE, Integer.valueOf(strValue),
1327: strValue);
1328: }
1329:
1330: if (insetsConstructor == null)
1331: insetsConstructor = java.awt.Insets.class
1332: .getConstructor(new Class[] { Integer.TYPE,
1333: Integer.TYPE, Integer.TYPE,
1334: Integer.TYPE });
1335:
1336: CodeStructure.createStatement(constrExp,
1337: java.awt.GridBagConstraints.class
1338: .getField("insets"), // NOI18N
1339: codeStructure.createExpression(
1340: insetsConstructor, insetsParams));
1341:
1342: // create add method statement
1343: CodeStructure.createStatement(contDelCodeExp,
1344: getAddWithConstrMethod(), new CodeExpression[] {
1345: compExp, constrExp });
1346: }
1347:
1348: else if (convIndex == LAYOUT_JTAB) {
1349: if (!"JTabbedPaneConstraints".equals(constrNode
1350: .getNodeName())) // NOI18N
1351: return false; // should not happen
1352:
1353: Object tabName = null;
1354: PropertyEditor tabNamePropEd = null;
1355: Object toolTip = null;
1356: PropertyEditor toolTipPropEd = null;
1357: Object icon = null;
1358: PropertyEditor iconPropEd = null;
1359:
1360: org.w3c.dom.Node[] propNodes = findSubNodes(constrNode,
1361: XML_PROPERTY);
1362: if (propNodes != null)
1363: for (int i = 0; i < propNodes.length; i++) {
1364: Object editorOrValue = getPropertyEditorOrValue(propNodes[i]);
1365: if (editorOrValue == NO_VALUE)
1366: continue;
1367:
1368: PropertyEditor prEd = null;
1369: Object value = null;
1370: if (editorOrValue instanceof PropertyEditor)
1371: prEd = (PropertyEditor) editorOrValue;
1372: else
1373: value = editorOrValue;
1374:
1375: String name = getAttribute(propNodes[i],
1376: ATTR_PROPERTY_NAME);
1377: if ("tabTitle".equals(name)) { // NOI18N
1378: tabName = value;
1379: tabNamePropEd = prEd;
1380: } else if ("tabToolTip".equals(name)) { // NOI18N
1381: toolTip = value;
1382: toolTipPropEd = prEd;
1383: } else if ("tabIcon".equals(name)) { // NOI18N
1384: icon = value;
1385: iconPropEd = prEd;
1386: }
1387: }
1388:
1389: if (tabName == null
1390: && (node = constrAttr.getNamedItem("tabName")) != null) // NOI18N
1391: tabName = node.getNodeValue();
1392: if (toolTip == null
1393: && (node = constrAttr.getNamedItem("toolTip")) != null) // NOI18N
1394: toolTip = node.getNodeValue();
1395:
1396: if (toolTip != null || toolTipPropEd != null) {
1397: if (addTabMethod1 == null)
1398: addTabMethod1 = javax.swing.JTabbedPane.class
1399: .getMethod(
1400: "addTab", // NOI18N
1401: new Class[] {
1402: String.class,
1403: javax.swing.Icon.class,
1404: java.awt.Component.class,
1405: String.class });
1406: CodeStructure.createStatement(contCodeExp,
1407: addTabMethod1, new CodeExpression[] {
1408: createExpressionForProperty(
1409: codeStructure,
1410: String.class, tabName,
1411: tabNamePropEd),
1412: createExpressionForProperty(
1413: codeStructure,
1414: javax.swing.Icon.class,
1415: icon, iconPropEd),
1416: compExp,
1417: createExpressionForProperty(
1418: codeStructure,
1419: String.class, toolTip,
1420: toolTipPropEd) });
1421: } else if (icon != null || iconPropEd != null) {
1422: if (addTabMethod2 == null)
1423: addTabMethod2 = javax.swing.JTabbedPane.class
1424: .getMethod(
1425: "addTab", // NOI18N
1426: new Class[] {
1427: String.class,
1428: javax.swing.Icon.class,
1429: java.awt.Component.class });
1430: CodeStructure
1431: .createStatement(
1432: contCodeExp,
1433: addTabMethod2,
1434: new CodeExpression[] {
1435: createExpressionForProperty(
1436: codeStructure,
1437: String.class,
1438: tabName,
1439: tabNamePropEd),
1440: createExpressionForProperty(
1441: codeStructure,
1442: javax.swing.Icon.class,
1443: icon, iconPropEd),
1444: compExp });
1445: } else {
1446: if (addTabMethod3 == null)
1447: addTabMethod3 = javax.swing.JTabbedPane.class
1448: .getMethod(
1449: "addTab", // NOI18N
1450: new Class[] {
1451: String.class,
1452: java.awt.Component.class });
1453: CodeStructure.createStatement(contCodeExp,
1454: addTabMethod3, new CodeExpression[] {
1455: createExpressionForProperty(
1456: codeStructure,
1457: String.class, tabName,
1458: tabNamePropEd), compExp });
1459: }
1460: }
1461:
1462: else if (convIndex == LAYOUT_JSPLIT) {
1463: if (!"JSplitPaneConstraints".equals(constrNode
1464: .getNodeName())) // NOI18N
1465: return false;
1466:
1467: node = constrAttr.getNamedItem("position"); // NOI18N
1468: if (node != null) {
1469: String position = node.getNodeValue();
1470: Method addMethod;
1471:
1472: if ("top".equals(position)) { // NOI18N
1473: if (setTopComponentMethod == null)
1474: setTopComponentMethod = javax.swing.JSplitPane.class
1475: .getMethod(
1476: "setTopComponent", // NOI18N
1477: new Class[] { java.awt.Component.class });
1478: addMethod = setTopComponentMethod;
1479: } else if ("bottom".equals(position)) { // NOI18N
1480: if (setBottomComponentMethod == null)
1481: setBottomComponentMethod = javax.swing.JSplitPane.class
1482: .getMethod(
1483: "setBottomComponent", // NOI18N
1484: new Class[] { java.awt.Component.class });
1485: addMethod = setBottomComponentMethod;
1486: } else if ("left".equals(position)) { // NOI18N
1487: if (setLeftComponentMethod == null)
1488: setLeftComponentMethod = javax.swing.JSplitPane.class
1489: .getMethod(
1490: "setLeftComponent", // NOI18N
1491: new Class[] { java.awt.Component.class });
1492: addMethod = setLeftComponentMethod;
1493: } else if ("right".equals(position)) { // NOI18N
1494: if (setRightComponentMethod == null)
1495: setRightComponentMethod = javax.swing.JSplitPane.class
1496: .getMethod(
1497: "setRightComponent", // NOI18N
1498: new Class[] { java.awt.Component.class });
1499: addMethod = setRightComponentMethod;
1500: } else
1501: return false;
1502:
1503: CodeStructure
1504: .createStatement(contCodeExp, addMethod,
1505: new CodeExpression[] { compExp });
1506: }
1507: }
1508:
1509: else if (convIndex == LAYOUT_CARD) {
1510: if (!"CardConstraints".equals(constrNode.getNodeName())) // NOI18N
1511: return false;
1512:
1513: node = constrAttr.getNamedItem("cardName"); // NOI18N
1514: if (node != null) {
1515: String strValue = node.getNodeValue();
1516: // create add method statement
1517: CodeStructure.createStatement(contDelCodeExp,
1518: getAddWithConstrMethod(),
1519: new CodeExpression[] {
1520: compExp,
1521: codeStructure.createExpression(
1522: String.class, strValue,
1523: strValue) });
1524: }
1525: }
1526:
1527: else if (convIndex == LAYOUT_JLAYER) {
1528: if (!"JLayeredPaneConstraints".equals(constrNode
1529: .getNodeName())) // NOI18N
1530: return false;
1531:
1532: CodeExpression[] boundsParams = new CodeExpression[4];
1533: String[] boundsAttrs = new String[] { "x", "y",
1534: "width", "height" }; // NOI18N
1535:
1536: for (int i = 0; i < boundsAttrs.length; i++) {
1537: node = constrAttr.getNamedItem(boundsAttrs[i]);
1538: String strValue = node != null ? node
1539: .getNodeValue() : (i < 2 ? "0" : "-1"); // NOI18N
1540: boundsParams[i] = codeStructure.createExpression(
1541: Integer.TYPE, Integer.valueOf(strValue),
1542: strValue);
1543: }
1544:
1545: if (setBoundsMethod == null)
1546: setBoundsMethod = java.awt.Component.class
1547: .getMethod("setBounds", // NOI18N
1548: new Class[] { Integer.TYPE,
1549: Integer.TYPE, Integer.TYPE,
1550: Integer.TYPE });
1551: CodeStructure.createStatement(compExp, setBoundsMethod,
1552: boundsParams);
1553:
1554: node = constrAttr.getNamedItem("layer"); // NOI18N
1555: if (node != null) {
1556: String strValue = node.getNodeValue();
1557: // create add method statement
1558: CodeStructure.createStatement(contDelCodeExp,
1559: getAddWithConstrMethod(),
1560: new CodeExpression[] {
1561: compExp,
1562: codeStructure.createExpression(
1563: Integer.TYPE, Integer
1564: .valueOf(strValue),
1565: strValue) });
1566: }
1567: }
1568:
1569: else if (convIndex == LAYOUT_ABSOLUTE) {
1570: if (!"AbsoluteConstraints".equals(constrNode
1571: .getNodeName())) // NOI18N
1572: return false;
1573:
1574: CodeExpression[] boundsParams = new CodeExpression[4];
1575: String[] boundsAttrs = new String[] { "x", "y",
1576: "width", "height" }; // NOI18N
1577:
1578: for (int i = 0; i < boundsAttrs.length; i++) {
1579: node = constrAttr.getNamedItem(boundsAttrs[i]);
1580: String strValue = node != null ? node
1581: .getNodeValue() : (i < 2 ? "0" : "-1"); // NOI18N
1582: boundsParams[i] = codeStructure.createExpression(
1583: Integer.TYPE, Integer.valueOf(strValue),
1584: strValue);
1585: }
1586:
1587: Iterator it = CodeStructure
1588: .getDefinedStatementsIterator(contDelCodeExp);
1589: CodeStatement[] statements = CodeStructure
1590: .filterStatements(it, getSetLayoutMethod());
1591: boolean nullLayout;
1592: if (statements.length > 0) {
1593: CodeExpression layoutExp = statements[0]
1594: .getStatementParameters()[0];
1595: nullLayout = layoutExp.getOrigin().getType() != org.netbeans.lib.awtextra.AbsoluteLayout.class;
1596: } else
1597: nullLayout = true;
1598:
1599: if (nullLayout) {
1600: if (setBoundsMethod == null)
1601: setBoundsMethod = java.awt.Component.class
1602: .getMethod("setBounds", // NOI18N
1603: new Class[] { Integer.TYPE,
1604: Integer.TYPE,
1605: Integer.TYPE,
1606: Integer.TYPE });
1607: CodeStructure.createStatement(compExp,
1608: setBoundsMethod, boundsParams);
1609:
1610: // create add method statement
1611: CodeStructure.createStatement(contDelCodeExp,
1612: getSimpleAddMethod(),
1613: new CodeExpression[] { compExp });
1614: } else {
1615: if (absoluteConstraintsConstructor == null)
1616: absoluteConstraintsConstructor = org.netbeans.lib.awtextra.AbsoluteConstraints.class
1617: .getConstructor(new Class[] {
1618: Integer.TYPE, Integer.TYPE,
1619: Integer.TYPE, Integer.TYPE });
1620:
1621: // create add method statement
1622: CodeStructure
1623: .createStatement(
1624: contDelCodeExp,
1625: getAddWithConstrMethod(),
1626: new CodeExpression[] {
1627: compExp,
1628: codeStructure
1629: .createExpression(
1630: absoluteConstraintsConstructor,
1631: boundsParams) });
1632: }
1633: }
1634:
1635: return true;
1636:
1637: } catch (NoSuchMethodException ex) { // should not happen
1638: ex.printStackTrace();
1639: } catch (NoSuchFieldException ex) { // should not happen
1640: ex.printStackTrace();
1641: }
1642: return false;
1643: }
1644:
1645: private void setupDefaultComponentCode(CodeExpression compExp,
1646: LayoutSupportManager layoutSupport) {
1647: if (layoutConvIndex == LAYOUT_JSCROLL) {
1648: // JScrollPane requires special add code although there are
1649: // no constraints ...
1650: if (setViewportViewMethod == null) {
1651: try {
1652: setViewportViewMethod = javax.swing.JScrollPane.class
1653: .getMethod(
1654: "setViewportView", // NOI18N
1655: new Class[] { java.awt.Component.class });
1656: } catch (NoSuchMethodException ex) { // should not happen
1657: ex.printStackTrace();
1658: return;
1659: }
1660: }
1661:
1662: CodeStructure.createStatement(layoutSupport
1663: .getContainerCodeExpression(),
1664: setViewportViewMethod,
1665: new CodeExpression[] { compExp });
1666: } else { // create simple add method statement with no constraints
1667: CodeStructure.createStatement(layoutSupport
1668: .getContainerDelegateCodeExpression(),
1669: getSimpleAddMethod(),
1670: new CodeExpression[] { compExp });
1671: }
1672: }
1673:
1674: private static Method getSimpleAddMethod() {
1675: if (simpleAddMethod == null) {
1676: try {
1677: simpleAddMethod = java.awt.Container.class.getMethod(
1678: "add", // NOI18N
1679: new Class[] { java.awt.Component.class });
1680: } catch (NoSuchMethodException ex) { // should not happen
1681: ex.printStackTrace();
1682: }
1683: }
1684: return simpleAddMethod;
1685: }
1686:
1687: private static Method getAddWithConstrMethod() {
1688: if (addWithConstrMethod == null) {
1689: try {
1690: addWithConstrMethod = java.awt.Container.class
1691: .getMethod("add", // NOI18N
1692: new Class[] { java.awt.Component.class,
1693: Object.class });
1694: } catch (NoSuchMethodException ex) { // should not happen
1695: ex.printStackTrace();
1696: }
1697: }
1698: return addWithConstrMethod;
1699: }
1700:
1701: private static Method getSetLayoutMethod() {
1702: if (setLayoutMethod == null) {
1703: try {
1704: setLayoutMethod = java.awt.Container.class.getMethod(
1705: "setLayout", // NOI18N
1706: new Class[] { java.awt.LayoutManager.class });
1707: } catch (NoSuchMethodException ex) { // should not happen
1708: ex.printStackTrace();
1709: }
1710: }
1711: return setLayoutMethod;
1712: }
1713:
1714: private int loadLayout(org.w3c.dom.Node layoutNode,
1715: LayoutSupportManager layoutSupport) {
1716: org.w3c.dom.NamedNodeMap layoutAttr = layoutNode
1717: .getAttributes();
1718: org.w3c.dom.Node node = layoutAttr
1719: .getNamedItem(ATTR_LAYOUT_CLASS);
1720: if (node == null)
1721: return LAYOUT_NATURAL;
1722:
1723: String layout31Name = PersistenceObjectRegistry
1724: .getClassName(node.getNodeValue());
1725: int convIndex = -1;
1726: for (int i = 0; i < layout31Names.length; i++)
1727: if (layout31Name.equals(layout31Names[i])) {
1728: convIndex = i;
1729: break;
1730: }
1731:
1732: if (convIndex < 0)
1733: return -1; // unknown layout
1734:
1735: org.w3c.dom.Node[] propNodes = findSubNodes(layoutNode,
1736: XML_PROPERTY);
1737: List<String> propertyNames = null;
1738: List<Object> propertyValues = null;
1739: List<Object> propertyEditors = null;
1740:
1741: if (propNodes != null && propNodes.length > 0) {
1742: propertyNames = new ArrayList<String>(propNodes.length);
1743: propertyValues = new ArrayList<Object>(propNodes.length);
1744: propertyEditors = new ArrayList<Object>(propNodes.length);
1745:
1746: for (int i = 0; i < propNodes.length; i++) {
1747: node = propNodes[i];
1748:
1749: Object editorOrValue = getPropertyEditorOrValue(node);
1750: if (editorOrValue == NO_VALUE)
1751: continue;
1752:
1753: propertyNames
1754: .add(getAttribute(node, ATTR_PROPERTY_NAME));
1755: if (editorOrValue instanceof PropertyEditor) {
1756: propertyEditors.add(editorOrValue);
1757: propertyValues.add(null);
1758: } else {
1759: propertyValues.add(editorOrValue);
1760: propertyEditors.add(null);
1761: }
1762: }
1763: }
1764:
1765: CodeStructure codeStructure = layoutSupport.getCodeStructure();
1766: CodeExpression[] layoutParams = null;
1767: Class[] paramTypes = null;
1768: Class layoutClass = null;
1769:
1770: String[] layoutPropNames = layout31PropertyNames[convIndex];
1771: if (convIndex == LAYOUT_BORDER) {
1772: int hgap = findName(layoutPropNames[0], propertyNames);
1773: int vgap = findName(layoutPropNames[1], propertyNames);
1774: if (hgap >= 0 || vgap >= 0) {
1775: layoutParams = new CodeExpression[2];
1776:
1777: layoutParams[0] = createExpressionForProperty(
1778: codeStructure, Integer.TYPE,
1779: hgap >= 0 ? propertyValues.get(hgap)
1780: : new Integer(0),
1781: (PropertyEditor) (hgap >= 0 ? propertyEditors
1782: .get(hgap) : null));
1783:
1784: layoutParams[1] = createExpressionForProperty(
1785: codeStructure, Integer.TYPE,
1786: vgap >= 0 ? propertyValues.get(vgap)
1787: : new Integer(0),
1788: (PropertyEditor) (vgap >= 0 ? propertyEditors
1789: .get(vgap) : null));
1790: } else {
1791: layoutParams = CodeStructure.EMPTY_PARAMS;
1792: }
1793: layoutClass = java.awt.BorderLayout.class;
1794: }
1795:
1796: else if (convIndex == LAYOUT_FLOW) {
1797: int alignment = findName(layoutPropNames[0], propertyNames);
1798: int hgap = findName(layoutPropNames[1], propertyNames);
1799: int vgap = findName(layoutPropNames[2], propertyNames);
1800: if (hgap >= 0 || vgap >= 0) {
1801: layoutParams = new CodeExpression[3];
1802:
1803: layoutParams[0] = createExpressionForProperty(
1804: codeStructure,
1805: Integer.TYPE,
1806: alignment >= 0 ? propertyValues.get(alignment)
1807: : new Integer(1),
1808: (PropertyEditor) (alignment >= 0 ? propertyEditors
1809: .get(alignment)
1810: : null));
1811:
1812: layoutParams[1] = createExpressionForProperty(
1813: codeStructure, Integer.TYPE,
1814: hgap >= 0 ? propertyValues.get(hgap)
1815: : new Integer(5),
1816: (PropertyEditor) (hgap >= 0 ? propertyEditors
1817: .get(hgap) : null));
1818:
1819: layoutParams[2] = createExpressionForProperty(
1820: codeStructure, Integer.TYPE,
1821: vgap >= 0 ? propertyValues.get(vgap)
1822: : new Integer(5),
1823: (PropertyEditor) (vgap >= 0 ? propertyEditors
1824: .get(vgap) : null));
1825: } else if (alignment >= 0) {
1826: layoutParams = new CodeExpression[1];
1827:
1828: layoutParams[0] = createExpressionForProperty(
1829: codeStructure,
1830: Integer.TYPE,
1831: alignment >= 0 ? propertyValues.get(alignment)
1832: : new Integer(1),
1833: (PropertyEditor) (alignment >= 0 ? propertyEditors
1834: .get(alignment)
1835: : null));
1836: } else {
1837: layoutParams = CodeStructure.EMPTY_PARAMS;
1838: }
1839: layoutClass = java.awt.FlowLayout.class;
1840: }
1841:
1842: else if (convIndex == LAYOUT_GRIDBAG) {
1843: layoutParams = CodeStructure.EMPTY_PARAMS;
1844: layoutClass = java.awt.GridBagLayout.class;
1845: }
1846:
1847: else if (convIndex == LAYOUT_BOX) {
1848: int axis = findName(layoutPropNames[0], propertyNames);
1849:
1850: layoutParams = new CodeExpression[2];
1851: layoutParams[0] = layoutSupport
1852: .getContainerDelegateCodeExpression();
1853: layoutParams[1] = createExpressionForProperty(
1854: codeStructure, Integer.TYPE,
1855: axis >= 0 ? propertyValues.get(axis) : new Integer(
1856: javax.swing.BoxLayout.LINE_AXIS),
1857: (PropertyEditor) (axis >= 0 ? propertyEditors
1858: .get(axis) : null));
1859:
1860: paramTypes = new Class[] { java.awt.Container.class,
1861: Integer.TYPE };
1862: layoutClass = javax.swing.BoxLayout.class;
1863: }
1864:
1865: else if (convIndex == LAYOUT_GRID) {
1866: int rows = findName(layoutPropNames[0], propertyNames);
1867: int columns = findName(layoutPropNames[1], propertyNames);
1868: int hgap = findName(layoutPropNames[2], propertyNames);
1869: int vgap = findName(layoutPropNames[3], propertyNames);
1870: if (hgap >= 0 || vgap >= 0) {
1871: layoutParams = new CodeExpression[4];
1872:
1873: layoutParams[0] = createExpressionForProperty(
1874: codeStructure, Integer.TYPE,
1875: rows >= 0 ? propertyValues.get(rows)
1876: : new Integer(1),
1877: (PropertyEditor) (rows >= 0 ? propertyEditors
1878: .get(rows) : null));
1879:
1880: layoutParams[1] = createExpressionForProperty(
1881: codeStructure,
1882: Integer.TYPE,
1883: columns >= 0 ? propertyValues.get(columns)
1884: : new Integer(0),
1885: (PropertyEditor) (columns >= 0 ? propertyEditors
1886: .get(columns)
1887: : null));
1888:
1889: layoutParams[2] = createExpressionForProperty(
1890: codeStructure, Integer.TYPE,
1891: hgap >= 0 ? propertyValues.get(hgap)
1892: : new Integer(0),
1893: (PropertyEditor) (hgap >= 0 ? propertyEditors
1894: .get(hgap) : null));
1895:
1896: layoutParams[3] = createExpressionForProperty(
1897: codeStructure, Integer.TYPE,
1898: vgap >= 0 ? propertyValues.get(vgap)
1899: : new Integer(0),
1900: (PropertyEditor) (vgap >= 0 ? propertyEditors
1901: .get(vgap) : null));
1902: } else if (rows >= 0 || columns >= 0) {
1903: layoutParams = new CodeExpression[2];
1904:
1905: layoutParams[0] = createExpressionForProperty(
1906: codeStructure, Integer.TYPE,
1907: rows >= 0 ? propertyValues.get(rows)
1908: : new Integer(1),
1909: (PropertyEditor) (rows >= 0 ? propertyEditors
1910: .get(rows) : null));
1911:
1912: layoutParams[1] = createExpressionForProperty(
1913: codeStructure,
1914: Integer.TYPE,
1915: columns >= 0 ? propertyValues.get(columns)
1916: : new Integer(0),
1917: (PropertyEditor) (columns >= 0 ? propertyEditors
1918: .get(columns)
1919: : null));
1920: } else {
1921: layoutParams = CodeStructure.EMPTY_PARAMS;
1922: }
1923: layoutClass = java.awt.GridLayout.class;
1924: }
1925:
1926: else if (convIndex == LAYOUT_CARD) {
1927: int hgap = findName(layoutPropNames[0], propertyNames);
1928: int vgap = findName(layoutPropNames[1], propertyNames);
1929: if (hgap >= 0 && vgap >= 0) {
1930: layoutParams = new CodeExpression[2];
1931:
1932: layoutParams[0] = createExpressionForProperty(
1933: codeStructure, Integer.TYPE,
1934: hgap >= 0 ? propertyValues.get(hgap)
1935: : new Integer(0),
1936: (PropertyEditor) (hgap >= 0 ? propertyEditors
1937: .get(hgap) : null));
1938:
1939: layoutParams[1] = createExpressionForProperty(
1940: codeStructure, Integer.TYPE,
1941: vgap >= 0 ? propertyValues.get(vgap)
1942: : new Integer(0),
1943: (PropertyEditor) (vgap >= 0 ? propertyEditors
1944: .get(vgap) : null));
1945: } else {
1946: layoutParams = CodeStructure.EMPTY_PARAMS;
1947: }
1948: layoutClass = java.awt.CardLayout.class;
1949: }
1950:
1951: else if (convIndex == LAYOUT_ABSOLUTE) {
1952: boolean nullLayout = false;
1953: int i = findName("useNullLayout", propertyNames); // NOI18N
1954: if (i >= 0)
1955: nullLayout = Boolean.TRUE.equals(propertyValues.get(i));
1956:
1957: layoutParams = CodeStructure.EMPTY_PARAMS;
1958: layoutClass = nullLayout ? null
1959: : org.netbeans.lib.awtextra.AbsoluteLayout.class;
1960: }
1961:
1962: else
1963: return convIndex; // no layout manager
1964:
1965: CodeExpression layoutExp;
1966: if (layoutClass != null) {
1967: if (paramTypes == null) {
1968: paramTypes = new Class[layoutParams.length];
1969: for (int i = 0; i < layoutParams.length; i++)
1970: paramTypes[i] = layoutParams[i].getOrigin()
1971: .getType();
1972: }
1973:
1974: Constructor layoutConstructor;
1975: try {
1976: layoutConstructor = layoutClass
1977: .getConstructor(paramTypes);
1978: } catch (NoSuchMethodException ex) { // should not happen
1979: ex.printStackTrace();
1980: return -1;
1981: }
1982: layoutExp = layoutSupport.getCodeStructure()
1983: .createExpression(layoutConstructor, layoutParams);
1984: } else {
1985: layoutExp = layoutSupport.getCodeStructure()
1986: .createNullExpression(java.awt.LayoutManager.class);
1987: }
1988:
1989: CodeStructure.createStatement(layoutSupport
1990: .getContainerDelegateCodeExpression(),
1991: getSetLayoutMethod(),
1992: new CodeExpression[] { layoutExp });
1993:
1994: return convIndex;
1995: }
1996:
1997: private static CodeExpression createExpressionForProperty(
1998: CodeStructure codeStructure, Class type, Object value,
1999: PropertyEditor propEd) {
2000: return propEd != null ? codeStructure
2001: .createExpression(FormCodeSupport.createOrigin(type,
2002: propEd)) : codeStructure.createExpression(type,
2003: value, value != null ? value.toString() : "null"); // NOI18N
2004: }
2005:
2006: private static int findName(String name, List<String> names) {
2007: return names != null ? names.indexOf(name) : -1;
2008: }
2009:
2010: private void loadLayoutCode(org.w3c.dom.Node node) {
2011: org.w3c.dom.NodeList childNodes = node.getChildNodes();
2012: if (childNodes != null) {
2013: // codeFlow = true;
2014: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
2015: org.w3c.dom.Node childNode = childNodes.item(i);
2016:
2017: if (XML_CODE_STATEMENT.equals(childNode.getNodeName()))
2018: loadCodeStatement(childNode, null);
2019: }
2020: }
2021: }
2022:
2023: private void loadComponentProperties(org.w3c.dom.Node node,
2024: RADComponent metacomp, String propCategory) {
2025: FormProperty[] properties;
2026: org.w3c.dom.Node[] propNodes = findSubNodes(node, XML_PROPERTY);
2027: String[] propNames = getPropertyAttributes(propNodes,
2028: ATTR_PROPERTY_NAME);
2029:
2030: if (metacomp.isValid()) {
2031: properties = findProperties(propNames, metacomp,
2032: propCategory);
2033: } else {
2034: String[] propTypes = getPropertyAttributes(propNodes,
2035: ATTR_PROPERTY_TYPE);
2036: properties = getFakeProperties(propNames, propTypes,
2037: propNodes, metacomp, propCategory);
2038: }
2039:
2040: for (int i = 0; i < propNodes.length; i++) {
2041: if (propNames[i] == null)
2042: continue;
2043:
2044: org.w3c.dom.Node propNode = propNodes[i];
2045: FormProperty property = properties[i];
2046:
2047: loadProperty(propNode, metacomp, property);
2048: }
2049: }
2050:
2051: private void loadProperty(org.w3c.dom.Node propNode,
2052: RADComponent metacomp, FormProperty property) {
2053: Throwable t = null;
2054: org.w3c.dom.Node valueNode = null;
2055:
2056: if (property == null) {
2057: PersistenceException ex = new PersistenceException(
2058: "Unknown property"); // NOI18N
2059: String msg = createLoadingErrorMessage(FormUtils
2060: .getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
2061: propNode);
2062: ErrorManager.getDefault().annotate(ex, ErrorManager.ERROR,
2063: null, msg, null, null);
2064: nonfatalErrors.add(ex);
2065: return;
2066: }
2067:
2068: // read pre-init and post-init code of the property
2069: String preCode = getAttribute(propNode, ATTR_PROPERTY_PRE_CODE);
2070: if (preCode != null)
2071: property.setPreCode(preCode);
2072: String postCode = getAttribute(propNode,
2073: ATTR_PROPERTY_POST_CODE);
2074: if (postCode != null)
2075: property.setPostCode(postCode);
2076:
2077: String typeStr = getAttribute(propNode, ATTR_PROPERTY_TYPE);
2078: String editorStr = getAttribute(propNode, ATTR_PROPERTY_EDITOR);
2079: String valueStr = getAttribute(propNode, ATTR_PROPERTY_VALUE);
2080: String resourceKey = getAttribute(propNode,
2081: ATTR_PROPERTY_RES_KEY);
2082:
2083: // get the type of stored property value
2084: Class propertyType = getPropertyType(typeStr, property,
2085: propNode);
2086: if (propertyType == null) {
2087: return;
2088: }
2089:
2090: // load the property editor class and create an instance of it
2091: PropertyEditor prEd = null;
2092: if (editorStr != null) {
2093: boolean prEdNecessary = (valueStr == null);
2094: prEd = getPropertyEditor(editorStr, property, propertyType,
2095: propNode, prEdNecessary);
2096: if (prEd == null && prEdNecessary) {
2097: return;
2098: } // if we failed to create the property editor we may still decode
2099: // the saved value from valueStr (i.e. a primitive value)
2100: }
2101:
2102: // load the property value
2103: Object value = NO_VALUE;
2104: if (valueStr != null) { // it is a primitive value
2105: try {
2106: value = decodePrimitiveValue(valueStr, propertyType);
2107: if (prEd != null) {
2108: prEd.setValue(value);
2109: value = prEd.getValue();
2110: }
2111: } catch (IllegalArgumentException ex) {
2112: String msg = createLoadingErrorMessage(FormUtils
2113: .getFormattedBundleString(
2114: "FMT_ERR_CannotDecodePrimitive", // NOI18N
2115: new Object[] { valueStr,
2116: propertyType.getName() }),
2117: propNode);
2118: ErrorManager.getDefault().annotate(ex, msg);
2119: nonfatalErrors.add(ex);
2120: return;
2121: }
2122: } else if (resourceKey != null) {
2123: value = ResourceSupport.findResource(resourceKey, property);
2124: if (value == null)
2125: return;
2126: } else { // the value is serialized or saved by XMLPropertyEditor
2127: org.w3c.dom.NodeList children = propNode.getChildNodes();
2128: int n = children != null ? children.getLength() : 0;
2129: if (n > 0) {
2130: try {
2131: boolean serialized = false;
2132: // first try if the value is serialized
2133: for (int j = 0; j < n; j++) {
2134: if (XML_SERIALIZED_PROPERTY_VALUE
2135: .equals(children.item(j).getNodeName())) { // here is the value serialized in XML
2136: String serValue = getAttribute(children
2137: .item(j), ATTR_PROPERTY_VALUE);
2138: if (serValue != null) {
2139: serialized = true;
2140: value = decodeValue(serValue);
2141: }
2142: break;
2143: }
2144: }
2145:
2146: if (!serialized) {
2147: // the value is saved by XMLPropertyEditor
2148: for (int j = 0; j < n; j++) {
2149: org.w3c.dom.Node node = children.item(j);
2150: if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { // here is the element of stored value
2151: if (prEd instanceof BeanPropertyEditor
2152: && XML_PROPERTY_BEAN
2153: .equals(node
2154: .getNodeName())) {
2155: loadBeanFromXML(node,
2156: (BeanPropertyEditor) prEd);
2157: loadBeanProperty(
2158: (BeanPropertyEditor) prEd,
2159: node);
2160: } else if (prEd instanceof XMLPropertyEditor) {
2161: ((XMLPropertyEditor) prEd)
2162: .readFromXML(node);
2163: }
2164: value = prEd.getValue();
2165:
2166: // hack for converting noI18n strings formerly handled by i18n/form
2167: if (value instanceof String
2168: && "PlainString".equals(node
2169: .getNodeName())) { // NOI18N
2170: prEd = null; // don't switch editor, keep default
2171: ResourceSupport
2172: .setExcludedProperty(
2173: property, true);
2174: }
2175: break;
2176: }
2177: }
2178: }
2179: } catch (Exception ex) {
2180: t = ex;
2181: } catch (LinkageError ex) {
2182: t = ex;
2183: }
2184: if (t != null) {
2185: String msg = createLoadingErrorMessage(
2186: FormUtils
2187: .getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
2188: propNode);
2189: ErrorManager.getDefault().annotate(t, msg);
2190: nonfatalErrors.add(t);
2191: return;
2192: }
2193: }
2194:
2195: if (value == NO_VALUE) { // the value is missing
2196: if (preCode != null || postCode != null)
2197: return; // not an error
2198: PersistenceException ex = new PersistenceException(
2199: "Missing property value"); // NOI18N
2200: String msg = createLoadingErrorMessage(
2201: FormUtils
2202: .getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
2203: propNode);
2204: ErrorManager.getDefault().annotate(ex,
2205: ErrorManager.ERROR, null, msg, null, null);
2206: nonfatalErrors.add(ex);
2207: return;
2208: }
2209: }
2210:
2211: String noResource = getAttribute(propNode, ATTR_PROPERTY_NORES);
2212: if (Boolean.parseBoolean(noResource)) {
2213: ResourceSupport.setExcludedProperty(property, true);
2214: }
2215:
2216: // hack for properties that can't be set until all children
2217: // are added to the container
2218: if (metacomp != null) {
2219: List<Object> propList = null;
2220: if (FormUtils.isMarkedParentDependentProperty(property)) {
2221: if (parentDependentProperties != null) {
2222: propList = parentDependentProperties.get(metacomp);
2223: } else {
2224: parentDependentProperties = new HashMap<RADComponent, java.util.List<Object>>();
2225: propList = null;
2226: }
2227: if (propList == null) {
2228: propList = new LinkedList<Object>();
2229: parentDependentProperties.put(metacomp, propList);
2230: }
2231: propList.add(property);
2232: propList.add(value);
2233: }
2234: if (FormUtils.isMarkedChildrenDependentProperty(property)) {
2235: if (childrenDependentProperties != null) {
2236: propList = childrenDependentProperties
2237: .get(metacomp);
2238: } else {
2239: childrenDependentProperties = new HashMap<RADComponent, java.util.List<Object>>();
2240: propList = null;
2241: }
2242: if (propList == null) {
2243: propList = new LinkedList<Object>();
2244: childrenDependentProperties.put(metacomp, propList);
2245: }
2246: propList.add(property);
2247: propList.add(value);
2248: }
2249: if (propList != null)
2250: return;
2251: }
2252:
2253: // set the value to the property
2254: try {
2255: if (prEd != null) {
2256: property.setCurrentEditor(prEd);
2257: }
2258: if (value instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
2259: boolean accepted = setConnectedProperty(
2260: property,
2261: (RADConnectionPropertyEditor.RADConnectionDesignValue) value,
2262: (metacomp == null) ? null : metacomp.getName(),
2263: propNode);
2264: if (!accepted) {
2265: // makes sense only for PROPERTY, and METHOD type.
2266: // in case it wasn't set for further handling
2267: // we must set it now.
2268: property.setValue(value);
2269: }
2270: } else {
2271: if (prEd instanceof BeanPropertyEditor) {
2272: // value is no RADConnection, but it still could have
2273: // properties which are RADConnection-s
2274: Property[] properties = ((BeanPropertyEditor) prEd)
2275: .getProperties();
2276: for (int i = 0; i < properties.length; i++) {
2277: Object propValue = properties[i].getValue();
2278: if (propValue instanceof RADConnectionPropertyEditor.RADConnectionDesignValue) {
2279: setConnectedProperty(
2280: properties[i],
2281: (RADConnectionPropertyEditor.RADConnectionDesignValue) propValue,
2282: value.toString(), // XXX getBeanName() ?
2283: propNode);
2284: // value was already set, so don't care
2285: // if it also was or wasn't set for further handling.
2286: }
2287: }
2288: }
2289: property.setValue(value);
2290: }
2291: } catch (Exception ex) {
2292: createLoadingErrorMessage(ex, propNode);
2293: return;
2294: }
2295: }
2296:
2297: private boolean setConnectedProperty(Property property,
2298: RADConnectionPropertyEditor.RADConnectionDesignValue value,
2299: String beanName, org.w3c.dom.Node propNode) {
2300: if (connectedProperties == null) {
2301: connectedProperties = new ConnectedProperties();
2302: }
2303: int type = value.getType();
2304: if (type == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_PROPERTY
2305: || type == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_METHOD) {
2306: // makes sense only for PROPERTY, and METHOD type ...
2307: connectedProperties
2308: .put(property, value, beanName, propNode);
2309: return true;
2310: }
2311: return false;
2312: }
2313:
2314: private void createLoadingErrorMessage(Exception ex,
2315: org.w3c.dom.Node propNode) {
2316: String msg = createLoadingErrorMessage(FormUtils
2317: .getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
2318: propNode);
2319: ErrorManager.getDefault().annotate(ex, msg);
2320: nonfatalErrors.add(ex);
2321: }
2322:
2323: private PropertyEditor getPropertyEditor(String editorStr,
2324: FormProperty property, Class propertyType,
2325: org.w3c.dom.Node propNode, boolean reportFailure) {
2326: // load the property editor class and create an instance of it
2327: PropertyEditor prEd = null;
2328: Throwable t = null;
2329: if (editorStr != null) {
2330: Class editorClass = null;
2331: try {
2332: editorClass = PersistenceObjectRegistry.loadClass(
2333: editorStr, formFile);
2334: } catch (Exception ex) {
2335: t = ex;
2336: } catch (LinkageError ex) {
2337: t = ex;
2338: }
2339: if (t != null) {
2340: // fallback: try PropertyEditorManager
2341: prEd = PropertyEditorManager.findEditor(propertyType);
2342: if (prEd != null
2343: && prEd.getClass().getName().equals(editorStr))
2344: return prEd;
2345:
2346: if (reportFailure) {
2347: String msg = createLoadingErrorMessage(FormUtils
2348: .getFormattedBundleString(
2349: "FMT_ERR_CannotLoadClass3", // NOI18N
2350: new Object[] { editorStr }),
2351: propNode);
2352: ErrorManager.getDefault().annotate(t,
2353: ErrorManager.USER, null, msg, null, null);
2354: nonfatalErrors.add(t);
2355: }
2356: return null;
2357: }
2358:
2359: try {
2360: prEd = createPropertyEditor(editorClass, propertyType,
2361: property);
2362: } catch (Exception ex) {
2363: t = ex;
2364: } catch (LinkageError ex) {
2365: t = ex;
2366: }
2367: if (t != null) {
2368: String msg = createLoadingErrorMessage(FormUtils
2369: .getFormattedBundleString(
2370: "FMT_ERR_CannotCreateInstance2", // NOI18N
2371: new Object[] { editorStr }), propNode);
2372: ErrorManager.getDefault().annotate(t, msg);
2373: nonfatalErrors.add(t);
2374: return null;
2375: }
2376: }
2377: return prEd;
2378: }
2379:
2380: private Class getPropertyType(String typeStr,
2381: FormProperty property, org.w3c.dom.Node propNode) {
2382: // get the type of stored property value
2383: Class propertyType = null;
2384: Throwable t = null;
2385:
2386: if (typeStr != null) {
2387: try {
2388: propertyType = getClassFromString(typeStr);
2389: } catch (Exception ex) {
2390: t = ex;
2391: } catch (LinkageError ex) {
2392: t = ex;
2393: }
2394: if (t != null) {
2395: String msg = createLoadingErrorMessage(FormUtils
2396: .getFormattedBundleString(
2397: "FMT_ERR_CannotLoadClass2", // NOI18N
2398: new Object[] { typeStr }), propNode);
2399: ErrorManager.getDefault().annotate(t, msg);
2400: nonfatalErrors.add(t);
2401: return null;
2402: }
2403: if (!property.getValueType().isAssignableFrom(propertyType)) {
2404: PersistenceException ex = new PersistenceException(
2405: "Incompatible property type"); // NOI18N
2406: String msg = createLoadingErrorMessage(
2407: FormUtils
2408: .getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
2409: propNode);
2410: ErrorManager.getDefault().annotate(ex,
2411: ErrorManager.ERROR, null, msg, null, null);
2412: nonfatalErrors.add(ex);
2413: return null;
2414: }
2415: } else
2416: propertyType = property.getValueType();
2417: return propertyType;
2418: }
2419:
2420: private void loadBeanFromXML(org.w3c.dom.Node node,
2421: BeanPropertyEditor beanPropertyEditor) throws Exception {
2422: String typeStr = node.getAttributes().getNamedItem(
2423: ATTR_PROPERTY_TYPE).getNodeValue();
2424: Class type = null;
2425: try {
2426: type = getClassFromString(typeStr);
2427: } catch (ClassNotFoundException ex) {
2428: String msg = createLoadingErrorMessage(FormUtils
2429: .getFormattedBundleString(
2430: "FMT_ERR_CannotLoadClass2", // NOI18N
2431: new Object[] { typeStr }), node);
2432: ErrorManager.getDefault().annotate(ex, msg);
2433: nonfatalErrors.add(ex);
2434: return;
2435: }
2436:
2437: beanPropertyEditor.intializeFromType(type);
2438:
2439: }
2440:
2441: private void loadBeanProperty(
2442: BeanPropertyEditor beanPropertyEditor,
2443: org.w3c.dom.Node valueNode) {
2444: if (beanPropertyEditor.valueIsBeanProperty()) {
2445: org.w3c.dom.NodeList children = valueNode.getChildNodes();
2446: Node.Property[] allBeanProperties = beanPropertyEditor
2447: .getProperties();
2448: org.w3c.dom.Node node;
2449: FormProperty prop;
2450:
2451: for (int i = 0; i < children.getLength(); i++) {
2452: node = children.item(i);
2453: if (node != null
2454: && node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
2455: prop = (FormProperty) getPropertyOfName(
2456: allBeanProperties, getAttribute(node,
2457: ATTR_PROPERTY_NAME));
2458: if (prop != null) {
2459: loadProperty(node, null, prop);
2460: }
2461: }
2462: }
2463: }
2464: }
2465:
2466: private String[] getPropertyAttributes(
2467: org.w3c.dom.Node[] propNodes, String attribute) {
2468: String[] ret = new String[propNodes.length];
2469: for (int i = 0; i < propNodes.length; i++) {
2470: org.w3c.dom.Node propNode = propNodes[i];
2471: String propAttribute = getAttribute(propNode, attribute);
2472: if (propAttribute != null)
2473: ret[i] = propAttribute;
2474: else {
2475: PersistenceException ex = new PersistenceException(
2476: "Missing property attribute " + attribute); // NOI18N
2477: String msg = FormUtils.getFormattedBundleString(
2478: "MSG_ERR_MissingPropertyName", // NOI18N
2479: new Object[] { attribute });
2480: ErrorManager.getDefault().annotate(ex,
2481: ErrorManager.ERROR, null, msg, null, null);
2482: nonfatalErrors.add(ex);
2483: continue;
2484: }
2485: }
2486: return ret;
2487: }
2488:
2489: private FormProperty[] findProperties(String[] propertyNames,
2490: RADComponent metacomp, String propCategory) { // [this is a bit ugly method, but don't have better way now...]
2491: if (XML_PROPERTIES.equals(propCategory)) // bean properties
2492: return metacomp.getBeanProperties(propertyNames);
2493:
2494: if (XML_A11Y_PROPERTIES.equals(propCategory)) {
2495: return findPropertiesByName(propertyNames, metacomp);
2496: }
2497:
2498: return new FormProperty[propertyNames.length]; // error
2499: }
2500:
2501: private FormProperty[] findPropertiesByName(String[] propertyNames,
2502: RADComponent metacomp) {
2503: FormProperty[] properties = new FormProperty[propertyNames.length];
2504: for (int i = 0; i < propertyNames.length; i++) {
2505: properties[i] = metacomp.getPropertyByName(
2506: propertyNames[i], FormProperty.class, true);
2507: }
2508:
2509: return properties;
2510: }
2511:
2512: private FormProperty[] getFakeProperties(String[] propertyNames,
2513: String[] propertyTypes, org.w3c.dom.Node[] propNodes,
2514: RADComponent metacomp, String propCategory) {
2515: if (XML_PROPERTIES.equals(propCategory)) {
2516: Class[] propertyClasses = new Class[propertyTypes.length];
2517: for (int i = 0; i < propertyNames.length; i++) {
2518: propertyClasses[i] = getClassByName(propertyTypes[i],
2519: propNodes[i]);
2520: }
2521: return metacomp.getFakeBeanProperties(propertyNames,
2522: propertyClasses);
2523:
2524: }
2525: if (XML_A11Y_PROPERTIES.equals(propCategory)) {
2526: findPropertiesByName(propertyNames, metacomp);
2527: }
2528:
2529: return new FormProperty[propertyNames.length]; // error
2530: }
2531:
2532: private Class getClassByName(String className, org.w3c.dom.Node node) {
2533: Class clazz = null;
2534: Throwable t = null;
2535: try {
2536: clazz = PersistenceObjectRegistry.loadClass(className,
2537: formFile);
2538: } catch (Exception ex) {
2539: t = ex;
2540: } catch (LinkageError ex) {
2541: t = ex;
2542: }
2543: if (t != null) { // loading the component class failed
2544: String msg = createLoadingErrorMessage(FormUtils
2545: .getFormattedBundleString(
2546: "FMT_ERR_CannotLoadClass", // NOI18N
2547: new Object[] { className }), node);
2548: ErrorManager.getDefault().annotate(t, msg);
2549: nonfatalErrors.add(t);
2550: }
2551: return clazz;
2552: }
2553:
2554: private Node.Property getPropertyOfName(Node.Property[] props,
2555: String name) {
2556: for (int i = 0; i < props.length; i++)
2557: if (props[i].getName().equals(name))
2558: return props[i];
2559:
2560: return null;
2561: }
2562:
2563: private void loadBindingProperties(org.w3c.dom.Node node,
2564: RADComponent metacomp) {
2565: org.w3c.dom.Node[] propNodes = findSubNodes(node,
2566: XML_BINDING_PROPERTY);
2567: for (int i = 0; i < propNodes.length; i++) {
2568: org.w3c.dom.Node propNode = propNodes[i];
2569: // get the attributes of property node element
2570: org.w3c.dom.NamedNodeMap attrs = propNode.getAttributes();
2571:
2572: // get the property name from attributes
2573: org.w3c.dom.Node nameNode = attrs
2574: .getNamedItem(ATTR_PROPERTY_NAME);
2575: if (nameNode == null) {
2576: PersistenceException ex = new PersistenceException(
2577: "Missing binding property name"); // NOI18N
2578: String msg = createLoadingErrorMessage(
2579: FormUtils
2580: .getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
2581: propNode);
2582: ErrorManager.getDefault().annotate(ex,
2583: ErrorManager.ERROR, null, msg, null, null);
2584: nonfatalErrors.add(ex);
2585: continue;
2586: }
2587:
2588: // find the property in the metacomponent
2589: String propName = nameNode.getNodeValue();
2590: BindingProperty property = metacomp
2591: .getBindingProperty(propName);
2592:
2593: // Backward compatibility with NB 6.0 Beta 1
2594: boolean ignoreAdjusting = false;
2595: if ((property == null)
2596: && "value_IGNORE_ADJUSTING".equals(propName)
2597: && javax.swing.JSlider.class
2598: .isAssignableFrom(metacomp.getBeanClass())) { // NOI18N
2599: property = metacomp.getBindingProperty("value"); // NOI18N
2600: ignoreAdjusting = true;
2601: }
2602:
2603: if (property == null) {
2604: // unknown binding property
2605: PersistenceException ex = new PersistenceException(
2606: "Unknown binding property"); // NOI18N
2607: String msg = createLoadingErrorMessage(FormUtils
2608: .getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
2609: propNode);
2610: ErrorManager.getDefault().annotate(ex,
2611: ErrorManager.ERROR, null, msg, null, null);
2612: nonfatalErrors.add(ex);
2613: continue;
2614: }
2615:
2616: org.w3c.dom.Node sourceNode = attrs
2617: .getNamedItem(ATTR_BINDING_SOURCE);
2618: org.w3c.dom.Node sourcePathNode = attrs
2619: .getNamedItem(ATTR_BINDING_SOURCE_PATH);
2620: org.w3c.dom.Node targetNode = attrs
2621: .getNamedItem(ATTR_BINDING_TARGET);
2622: org.w3c.dom.Node targetPathNode = attrs
2623: .getNamedItem(ATTR_BINDING_TARGET_PATH);
2624: org.w3c.dom.Node updateStrategyNode = attrs
2625: .getNamedItem(ATTR_BINDING_UPDATE_STRATEGY);
2626: org.w3c.dom.Node immediatelyNode = attrs
2627: .getNamedItem(ATTR_BINDING_IMMEDIATELY);
2628:
2629: // load the property value
2630: if ((sourceNode == null) || (targetNode == null)) { // the value is missing
2631: PersistenceException ex = new PersistenceException(
2632: "Missing binding property value"); // NOI18N
2633: String msg = createLoadingErrorMessage(
2634: FormUtils
2635: .getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
2636: propNode);
2637: ErrorManager.getDefault().annotate(ex,
2638: ErrorManager.ERROR, null, msg, null, null);
2639: nonfatalErrors.add(ex);
2640: continue;
2641: }
2642:
2643: String source = sourceNode.getNodeValue();
2644: String sourcePath = (sourcePathNode == null) ? null
2645: : sourcePathNode.getNodeValue();
2646: String target = targetNode.getNodeValue();
2647: String targetPath = (targetPathNode == null) ? null
2648: : targetPathNode.getNodeValue();
2649: if (ignoreAdjusting) {
2650: targetPath = targetPath.substring(0, targetPath
2651: .length()
2652: - "_IGNORE_ADJUSTING".length()); // NOI18N
2653: }
2654: MetaBinding value = new MetaBinding(null, sourcePath, null,
2655: targetPath);
2656: if (ignoreAdjusting) {
2657: value.setParameter(
2658: MetaBinding.IGNORE_ADJUSTING_PARAMETER, "Y"); // NOI18N
2659: }
2660:
2661: if (updateStrategyNode != null) {
2662: String updateStrategyTxt = updateStrategyNode
2663: .getNodeValue();
2664: value.setUpdateStrategy(Integer
2665: .parseInt(updateStrategyTxt));
2666: }
2667:
2668: if (immediatelyNode != null) {
2669: String immediatelyTxt = immediatelyNode.getNodeValue();
2670: value.setBindImmediately(Boolean
2671: .parseBoolean(immediatelyTxt));
2672: }
2673:
2674: if (bindingProperties == null)
2675: bindingProperties = new LinkedList<Object>();
2676: bindingProperties.add(property);
2677: bindingProperties.add(source);
2678: bindingProperties.add(target);
2679: bindingProperties.add(value);
2680: bindingProperties.add(propNode);
2681:
2682: // load properties
2683: org.w3c.dom.Node[] subNodes = findSubNodes(propNode,
2684: XML_PROPERTY);
2685: for (int j = 0; j < subNodes.length; j++) {
2686: org.w3c.dom.NamedNodeMap subAttrs = subNodes[j]
2687: .getAttributes();
2688: org.w3c.dom.Node propNameNode = subAttrs
2689: .getNamedItem(ATTR_PROPERTY_NAME);
2690: if (propNameNode != null) {
2691: String subPropName = propNameNode.getNodeValue();
2692: if ("nullValue".equals(subPropName)) { // NOI18N
2693: loadProperty(subNodes[j], null, property
2694: .getNullValueProperty());
2695: value.setNullValueSpecified(true);
2696: } else if ("incompletePathValue"
2697: .equals(subPropName)) { // NOI18N
2698: loadProperty(subNodes[j], null, property
2699: .getIncompleteValueProperty());
2700: value.setIncompletePathValueSpecified(true);
2701: } else if ("converter".equals(subPropName)) { // NOI18N
2702: loadProperty(subNodes[j], null, property
2703: .getConverterProperty());
2704: } else if ("validator".equals(subPropName)) { // NOI18N
2705: loadProperty(subNodes[j], null, property
2706: .getValidatorProperty());
2707: } else if ("name".equals(subPropName)) { // NOI18N
2708: loadProperty(subNodes[j], null, property
2709: .getNameProperty());
2710: }
2711: }
2712: }
2713:
2714: // load parameters
2715: loadBindingParameters(propNode, value);
2716:
2717: // load subbindings
2718: subNodes = findSubNodes(propNode, XML_SUBBINDING);
2719: for (int j = 0; j < subNodes.length; j++) {
2720: org.w3c.dom.Node subNode = subNodes[j];
2721: org.w3c.dom.NamedNodeMap subAttrs = subNode
2722: .getAttributes();
2723: org.w3c.dom.Node sourcePathSubNode = subAttrs
2724: .getNamedItem(ATTR_BINDING_SOURCE_PATH);
2725: org.w3c.dom.Node targetPathSubNode = subAttrs
2726: .getNamedItem(ATTR_BINDING_TARGET_PATH);
2727:
2728: String subSourcePath = (sourcePathSubNode == null) ? null
2729: : sourcePathSubNode.getNodeValue();
2730: String subTargetPath = (targetPathSubNode == null) ? null
2731: : targetPathSubNode.getNodeValue();
2732: MetaBinding subBinding = value.addSubBinding(
2733: subSourcePath, subTargetPath);
2734:
2735: // load parameters of subbinding
2736: loadBindingParameters(subNode, subBinding);
2737: }
2738: }
2739: }
2740:
2741: private void loadBindingParameters(org.w3c.dom.Node node,
2742: MetaBinding binding) {
2743: org.w3c.dom.Node[] subNodes = findSubNodes(node,
2744: XML_BINDING_PARAMETER);
2745: for (int j = 0; j < subNodes.length; j++) {
2746: org.w3c.dom.Node subNode = subNodes[j];
2747: org.w3c.dom.NamedNodeMap subAttrs = subNode.getAttributes();
2748: org.w3c.dom.Node paramNameNode = subAttrs
2749: .getNamedItem(ATTR_BINDING_PARAMETER_NAME);
2750: org.w3c.dom.Node paramValueNode = subAttrs
2751: .getNamedItem(ATTR_BINDING_PARAMETER_VALUE);
2752: if ((paramNameNode != null) || (paramValueNode != null)) {
2753: binding.setParameter(paramNameNode.getNodeValue(),
2754: paramValueNode.getNodeValue());
2755: }
2756: }
2757: }
2758:
2759: private void loadSyntheticProperties(org.w3c.dom.Node node,
2760: RADComponent metacomp) {
2761: org.w3c.dom.Node[] propNodes = findSubNodes(node,
2762: XML_SYNTHETIC_PROPERTY);
2763: for (int i = 0; i < propNodes.length; i++) {
2764: org.w3c.dom.Node propNode = propNodes[i];
2765: // get the attributes of property node element
2766: org.w3c.dom.NamedNodeMap attrs = propNode.getAttributes();
2767: if (attrs == null)
2768: continue; // no attributes, ignore property
2769:
2770: // get the property name from attributes
2771: org.w3c.dom.Node nameNode = attrs
2772: .getNamedItem(ATTR_PROPERTY_NAME);
2773: if (nameNode == null) {
2774: PersistenceException ex = new PersistenceException(
2775: "Missing synthetic property name"); // NOI18N
2776: String msg = createLoadingErrorMessage(
2777: FormUtils
2778: .getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
2779: propNode);
2780: ErrorManager.getDefault().annotate(ex,
2781: ErrorManager.ERROR, null, msg, null, null);
2782: nonfatalErrors.add(ex);
2783: continue;
2784: }
2785:
2786: // find the property in the metacomponent
2787: String propName = nameNode.getNodeValue();
2788: Node.Property[] props = metacomp.getSyntheticProperties();
2789: Node.Property property = null;
2790: Class<?> expectedPropertyType = null;
2791: for (int j = 0; j < props.length; j++) {
2792: if (props[j].getName().equals(propName)) {
2793: property = props[j];
2794: break;
2795: }
2796: }
2797:
2798: if (property == null) {
2799: if ("menuBar".equals(propName) // NOI18N
2800: && metacomp instanceof RADVisualFormContainer) { // compatibility hack for loading form's menu bar, part 1
2801: // (menubar is no longer a synthetic property, but it was
2802: // in NB 3.2)
2803: expectedPropertyType = String.class;
2804: } else if ("encoding".equals(propName)) // NOI18N
2805: continue; // there used to be "encoding" property in NB 3.1
2806: else { // unknown synthetic property
2807: PersistenceException ex = new PersistenceException(
2808: "Unknown synthetic property"); // NOI18N
2809: String msg = createLoadingErrorMessage(
2810: FormUtils
2811: .getBundleString("MSG_ERR_UnknownProperty"), // NOI18N
2812: propNode);
2813: ErrorManager.getDefault().annotate(ex,
2814: ErrorManager.ERROR, null, msg, null, null);
2815: nonfatalErrors.add(ex);
2816: continue;
2817: }
2818: } else
2819: expectedPropertyType = property.getValueType();
2820:
2821: org.w3c.dom.Node typeNode = attrs
2822: .getNamedItem(ATTR_PROPERTY_TYPE);
2823: org.w3c.dom.Node valueNode = attrs
2824: .getNamedItem(ATTR_PROPERTY_VALUE);
2825:
2826: // get the type of stored property value
2827: Class propertyType = null;
2828: Throwable t = null;
2829:
2830: if (typeNode != null) {
2831: try {
2832: propertyType = getClassFromString(typeNode
2833: .getNodeValue());
2834: } catch (Exception ex) {
2835: t = ex;
2836: } catch (LinkageError ex) {
2837: t = ex;
2838: }
2839: if (t != null) {
2840: String msg = createLoadingErrorMessage(FormUtils
2841: .getFormattedBundleString(
2842: "FMT_ERR_CannotLoadClass2", // NOI18N
2843: new Object[] { typeNode
2844: .getNodeValue() }),
2845: propNode);
2846: ErrorManager.getDefault().annotate(t, msg);
2847: nonfatalErrors.add(t);
2848: continue;
2849: }
2850: if (!expectedPropertyType
2851: .isAssignableFrom(propertyType)) {
2852: PersistenceException ex = new PersistenceException(
2853: "Incompatible property type"); // NOI18N
2854: String msg = createLoadingErrorMessage(
2855: FormUtils
2856: .getBundleString("MSG_ERR_IncompatiblePropertyType"), // NOI18N
2857: propNode);
2858: ErrorManager.getDefault().annotate(ex,
2859: ErrorManager.ERROR, null, msg, null, null);
2860: nonfatalErrors.add(ex);
2861: continue;
2862: }
2863: } else
2864: propertyType = property.getValueType();
2865:
2866: // load the property value
2867: if (valueNode == null) { // the value is missing
2868: PersistenceException ex = new PersistenceException(
2869: "Missing synthetic property value"); // NOI18N
2870: String msg = createLoadingErrorMessage(
2871: FormUtils
2872: .getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
2873: propNode);
2874: ErrorManager.getDefault().annotate(ex,
2875: ErrorManager.ERROR, null, msg, null, null);
2876: nonfatalErrors.add(ex);
2877: continue;
2878: }
2879:
2880: Object value = null;
2881: try {
2882: try {
2883: value = decodePrimitiveValue(valueNode
2884: .getNodeValue(), propertyType);
2885: } catch (IllegalArgumentException ex) {
2886: // not a primitive value
2887: value = decodeValue(valueNode.getNodeValue());
2888: }
2889: } catch (Exception ex) {
2890: t = ex;
2891: } catch (LinkageError ex) {
2892: t = ex;
2893: }
2894: if (t != null) {
2895: String msg = createLoadingErrorMessage(
2896: FormUtils
2897: .getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
2898: propNode);
2899: ErrorManager.getDefault().annotate(t, msg);
2900: nonfatalErrors.add(t);
2901: continue;
2902: }
2903:
2904: // compatibility hack for loading form's menu bar, part 2
2905: if ("menuBar".equals(propName) // NOI18N
2906: && value instanceof String
2907: && metacomp instanceof RADVisualFormContainer) { // menuBar synthetic property points to a component in Other Components
2908: mainMenuBarName = (String) value;
2909: continue;
2910: }
2911:
2912: // set the value to the property
2913: try {
2914: property.setValue(value);
2915: } catch (Exception ex) {
2916: String msg = createLoadingErrorMessage(
2917: FormUtils
2918: .getBundleString("MSG_ERR_CannotSetLoadedValue"), // NOI18N
2919: propNode);
2920: ErrorManager.getDefault().annotate(ex, msg);
2921: nonfatalErrors.add(ex);
2922: continue;
2923: }
2924: }
2925: }
2926:
2927: private void loadEvents(org.w3c.dom.Node node, RADComponent metacomp) {
2928: org.w3c.dom.Node[] eventNodes = findSubNodes(node, XML_EVENT);
2929: String[] eventNames = new String[eventNodes.length];
2930:
2931: for (int i = 0; i < eventNodes.length; i++) {
2932: org.w3c.dom.Node eventNode = eventNodes[i];
2933: String eventName = getAttribute(eventNode, ATTR_EVENT_NAME);
2934: String eventListener = getAttribute(eventNode,
2935: ATTR_EVENT_LISTENER);
2936: String paramTypes = getAttribute(eventNode,
2937: ATTR_EVENT_PARAMS);
2938: String eventHandlers = getAttribute(eventNode,
2939: ATTR_EVENT_HANDLER);
2940:
2941: if (eventName == null || eventHandlers == null)
2942: continue; // [missing data error - should be reported!!]
2943:
2944: eventNames[i] = getEventIdName(eventListener, eventName,
2945: paramTypes);
2946: }
2947:
2948: FormEvents formEvents = formModel.getFormEvents();
2949:
2950: Event[] events = metacomp.getEvents(eventNames);
2951: for (int i = 0; i < eventNodes.length; i++) {
2952: if (eventNames[i] == null)
2953: continue;
2954:
2955: Event event = events[i];
2956: if (event == null)
2957: continue; // [uknown event error - should be reported!]
2958:
2959: String eventHandlers = getAttribute(eventNodes[i],
2960: ATTR_EVENT_HANDLER);
2961: StringTokenizer tok = new StringTokenizer(eventHandlers,
2962: ","); // NOI18N
2963: while (tok.hasMoreTokens()) {
2964: try {
2965: formEvents
2966: .attachEvent(event, tok.nextToken(), null);
2967: } catch (IllegalArgumentException ex) {
2968: // [incompatible handler error - should be reported!]
2969: }
2970: }
2971: }
2972: }
2973:
2974: private static String getEventIdName(String eventListener,
2975: String eventName, String paramTypes) {
2976: if (eventListener == null || paramTypes == null)
2977: return eventName;
2978:
2979: StringBuffer buf = new StringBuffer();
2980: buf.append("$"); // NOI18N
2981: buf.append(eventListener);
2982: buf.append("."); // NOI18N
2983: buf.append(eventName);
2984: buf.append("("); // NOI18N
2985:
2986: StringTokenizer tok = new StringTokenizer(paramTypes, ","); // NOI18N
2987: while (tok.hasMoreTokens()) {
2988: buf.append(tok.nextToken());
2989: if (tok.hasMoreTokens())
2990: buf.append(", "); // NOI18N
2991: }
2992:
2993: buf.append(")"); // NOI18N
2994: return buf.toString();
2995: }
2996:
2997: private void loadAuxValues(org.w3c.dom.Node node, RADComponent comp) {
2998: org.w3c.dom.Node[] auxNodes = findSubNodes(node, XML_AUX_VALUE);
2999: for (int i = 0; i < auxNodes.length; i++) {
3000: org.w3c.dom.Node auxNode = auxNodes[i];
3001: // get the attributes of property node element
3002: org.w3c.dom.NamedNodeMap attrs = auxNode.getAttributes();
3003: if (attrs == null)
3004: continue; // no attributes, ignore
3005:
3006: // get the property name from attributes
3007: org.w3c.dom.Node nameNode = attrs
3008: .getNamedItem(ATTR_AUX_NAME);
3009: if (nameNode == null) {
3010: PersistenceException ex = new PersistenceException(
3011: "Missing aux value name"); // NOI18N
3012: String msg = createLoadingErrorMessage(
3013: FormUtils
3014: .getBundleString("MSG_ERR_MissingPropertyName"), // NOI18N
3015: auxNode);
3016: ErrorManager.getDefault().annotate(ex,
3017: ErrorManager.ERROR, null, msg, null, null);
3018: nonfatalErrors.add(ex);
3019: continue;
3020: }
3021: String name = nameNode.getNodeValue();
3022:
3023: org.w3c.dom.Node typeNode = attrs
3024: .getNamedItem(ATTR_AUX_VALUE_TYPE);
3025: org.w3c.dom.Node valueNode = attrs
3026: .getNamedItem(ATTR_AUX_VALUE);
3027:
3028: // get the type of stored aux value
3029: if (typeNode == null) {
3030: PersistenceException ex = new PersistenceException(
3031: "Missing aux value type"); // NOI18N
3032: String msg = createLoadingErrorMessage(
3033: FormUtils
3034: .getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
3035: auxNode);
3036: ErrorManager.getDefault().annotate(ex,
3037: ErrorManager.ERROR, null, msg, null, null);
3038: nonfatalErrors.add(ex);
3039: continue;
3040: }
3041:
3042: Class auxValueType = null;
3043: Throwable t = null;
3044: try {
3045: auxValueType = getClassFromString(typeNode
3046: .getNodeValue());
3047: } catch (Exception ex) {
3048: t = ex;
3049: } catch (LinkageError ex) {
3050: t = ex;
3051: }
3052: if (t != null) {
3053: String msg = createLoadingErrorMessage(
3054: FormUtils
3055: .getFormattedBundleString(
3056: "FMT_ERR_CannotLoadClass2", // NOI18N
3057: new Object[] { typeNode
3058: .getNodeValue() }),
3059: auxNode);
3060: ErrorManager.getDefault().annotate(t, msg);
3061: nonfatalErrors.add(t);
3062: continue;
3063: }
3064:
3065: // load the aux value
3066: if (valueNode == null) { // the value is missing
3067: PersistenceException ex = new PersistenceException(
3068: "Missing aux value"); // NOI18N
3069: String msg = createLoadingErrorMessage(
3070: FormUtils
3071: .getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
3072: auxNode);
3073: ErrorManager.getDefault().annotate(ex,
3074: ErrorManager.ERROR, null, msg, null, null);
3075: nonfatalErrors.add(ex);
3076: continue;
3077: }
3078:
3079: Object value = null;
3080: try {
3081: try {
3082: value = decodePrimitiveValue(valueNode
3083: .getNodeValue(), auxValueType);
3084: } catch (IllegalArgumentException ex) {
3085: // not a primitive value
3086: value = decodeValue(valueNode.getNodeValue());
3087: }
3088: } catch (Exception ex) {
3089: t = ex;
3090: } catch (LinkageError ex) {
3091: t = ex;
3092: }
3093: if (t != null) {
3094: String msg = createLoadingErrorMessage(
3095: FormUtils
3096: .getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
3097: auxNode);
3098: ErrorManager.getDefault().annotate(t, msg);
3099: nonfatalErrors.add(t);
3100: continue;
3101: }
3102:
3103: // Form settings are stored in AuxValues of top-level container
3104: if ((comp == formModel.getTopRADComponent() && (name
3105: .startsWith(FORM_SETTINGS_PREFIX)))) {
3106: String settingName = name
3107: .substring(FORM_SETTINGS_PREFIX.length());
3108: FormSettings formSettings = formModel.getSettings();
3109: formSettings.set(settingName, value);
3110:
3111: if (FormSettings.PROP_AUTO_I18N.equals(settingName)
3112: && Boolean.TRUE.equals(value)) { // auto i18n set
3113: // if loading form from updated 5.5 or early 6.0,
3114: // the version might be just 1.3, but should be 1.4
3115: formModel.raiseVersionLevel(
3116: FormModel.FormVersion.NB60_PRE,
3117: FormModel.FormVersion.NB60_PRE);
3118: // also keep auto resourcing in sync - if present but turned off
3119: Object autoResSetting = formSettings
3120: .get(ResourceSupport.PROP_AUTO_RESOURCING);
3121: if (autoResSetting instanceof Integer
3122: && ((Integer) autoResSetting).intValue() == ResourceSupport.AUTO_OFF) {
3123: formSettings.set(
3124: ResourceSupport.PROP_AUTO_RESOURCING,
3125: ResourceSupport.AUTO_I18N);
3126: }
3127: }
3128: } else {
3129: // we have a valid name / value pair
3130: comp.setAuxValue(name, value);
3131: }
3132: }
3133:
3134: // we must care about some aux values specially ...
3135:
3136: if (comp == formModel.getTopRADComponent()) {
3137: return;
3138: }
3139:
3140: // VALUE_SERIALIZE indicates serialized component
3141: if (JavaCodeGenerator.VALUE_SERIALIZE.equals(comp
3142: .getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION))) { // the component has a serialized instance => deserialize it
3143: try {
3144: String serFile = (String) comp
3145: .getAuxValue(JavaCodeGenerator.AUX_SERIALIZE_TO);
3146: if (serFile == null)
3147: serFile = formFile.getName() + "_" + comp.getName(); // NOI18N
3148:
3149: ClassPath sourcePath = ClassPath.getClassPath(formFile,
3150: ClassPath.SOURCE);
3151: String serName = sourcePath.getResourceName(formFile
3152: .getParent());
3153: if (!"".equals(serName)) // NOI18N
3154: serName += "."; // NOI18N
3155: serName += serFile;
3156:
3157: Object instance = null;
3158: try {
3159: instance = Beans.instantiate(sourcePath
3160: .getClassLoader(true), serName);
3161: } catch (ClassNotFoundException cnfe) {
3162: ClassPath executionPath = ClassPath.getClassPath(
3163: formFile, ClassPath.EXECUTE);
3164: instance = Beans.instantiate(executionPath
3165: .getClassLoader(true), serName);
3166: }
3167:
3168: comp.setInstance(instance);
3169: } catch (Exception ex) { // ignore
3170: org.openide.ErrorManager.getDefault().notify(
3171: org.openide.ErrorManager.INFORMATIONAL, ex);
3172: }
3173: }
3174:
3175: JavaCodeGenerator.setupComponentFromAuxValues(comp);
3176: }
3177:
3178: // -----------
3179:
3180: /** This method saves the form to given data object.
3181: * @param formObject FormDataObject representing the form files
3182: * @param formModel FormModel to be saved
3183: * @param nonfatalErrors List to be filled with errors occurred during
3184: * saving which are not fatal (but should be reported)
3185: * @exception PersistenceException if some fatal problem occurred which
3186: * prevents saving the form
3187: */
3188: public void saveForm(FormDataObject formObject,
3189: FormModel formModel, List<Throwable> nonfatalErrors)
3190: throws PersistenceException {
3191: FileObject formFile = formObject.getFormEntry().getFile();
3192: if (!formFile.canWrite()) { // should not happen
3193: PersistenceException ex = new PersistenceException(
3194: "Tried to save read-only form"); // NOI18N
3195: String msg = FormUtils.getFormattedBundleString(
3196: "FMT_ERR_SaveToReadOnly", // NOI18N
3197: new Object[] { formFile.getNameExt() });
3198: ErrorManager.getDefault().annotate(ex, ErrorManager.ERROR,
3199: null, msg, null, null);
3200: throw ex;
3201: }
3202:
3203: StringBuffer buf = new StringBuffer();
3204:
3205: // initial cleanup
3206: lastExpId = 0; // CodeExpression ID counter
3207: if (expressions != null)
3208: expressions.clear();
3209: if (savedVariables != null)
3210: savedVariables.clear();
3211:
3212: this .formFile = formFile;
3213: this .formModel = formModel;
3214: this .nonfatalErrors = nonfatalErrors;
3215:
3216: RADComponent topComp = formModel.getTopRADComponent();
3217: RADVisualFormContainer formCont = topComp instanceof RADVisualFormContainer ? (RADVisualFormContainer) topComp
3218: : null;
3219:
3220: // store XML file header
3221: final String encoding = "UTF-8"; // NOI18N
3222: buf.append("<?xml version=\"1.0\" encoding=\""); // NOI18N
3223: buf.append(encoding);
3224: buf.append("\" ?>\n\n"); // NOI18N
3225:
3226: // add form specification element
3227: String formatVersion = versionStringForFormVersion(formModel
3228: .getCurrentVersionLevel());
3229: String maxVersion = versionStringForFormVersion(formModel
3230: .getMaxVersionLevel());
3231: String compatFormInfo = getFormInfoForKnownClass(formModel
3232: .getFormBaseClass());
3233: if (compatFormInfo == null) {
3234: addElementOpenAttr(buf, XML_FORM, new String[] {
3235: ATTR_FORM_VERSION, ATTR_MAX_FORM_VERSION },
3236: new String[] { formatVersion, maxVersion });
3237: } else { // FormInfo type stored for backward compatibility
3238: addElementOpenAttr(buf, XML_FORM, new String[] {
3239: ATTR_FORM_VERSION, ATTR_MAX_FORM_VERSION,
3240: ATTR_FORM_TYPE }, new String[] { formatVersion,
3241: maxVersion, compatFormInfo });
3242: }
3243:
3244: // store "Other Components"
3245: Collection<RADComponent> otherComps = formModel
3246: .getOtherComponents();
3247:
3248: // compatibility hack for saving form's menu bar (part I)
3249: RADComponent formMenuComp = formCont != null ? formCont
3250: .getContainerMenu() : null;
3251:
3252: if (otherComps.size() > 0 || formMenuComp != null) {
3253: buf.append(ONE_INDENT);
3254: addElementOpen(buf, XML_NON_VISUAL_COMPONENTS);
3255: for (RADComponent metacomp : otherComps) {
3256: saveAnyComponent(metacomp, buf,
3257: ONE_INDENT + ONE_INDENT, true);
3258: }
3259: if (formMenuComp != null) {
3260: saveAnyComponent(formMenuComp, buf, ONE_INDENT
3261: + ONE_INDENT, true);
3262: }
3263: buf.append(ONE_INDENT);
3264: addElementClose(buf, XML_NON_VISUAL_COMPONENTS);
3265: }
3266:
3267: // store form main hierarchy
3268: if (topComp != null) {
3269: saveAnyComponent(topComp, buf, ONE_INDENT, false);
3270: // if (!(topComp instanceof RADVisualContainer))
3271: // raiseFormatVersion(NB33_VERSION);
3272: } else {
3273: // Form settings of bean form
3274: Map<String, Object> auxValues = new TreeMap<String, Object>();
3275: addFormSettings(auxValues);
3276: buf.append(ONE_INDENT);
3277: addElementOpen(buf, XML_AUX_VALUES);
3278: saveAuxValues(auxValues, buf, ONE_INDENT + ONE_INDENT);
3279: buf.append(ONE_INDENT);
3280: addElementClose(buf, XML_AUX_VALUES);
3281: }
3282:
3283: addElementClose(buf, XML_FORM);
3284:
3285: // final cleanup
3286: if (expressions != null)
3287: expressions.clear();
3288: if (savedVariables != null)
3289: savedVariables.clear();
3290:
3291: // write the data
3292: FileLock lock = null;
3293: try {
3294: lock = formFile.lock();
3295: } catch (IOException ex) {
3296: PersistenceException pe = new PersistenceException(ex,
3297: "Cannot obtain lock on form file"); // NOI18N
3298: ErrorManager.getDefault().annotate(
3299: ex,
3300: FormUtils.getFormattedBundleString(
3301: "FMT_ERR_CannotLockFormFile", // NOI18N
3302: new Object[] { formFile.getNameExt() }));
3303: throw pe;
3304: }
3305:
3306: java.io.OutputStream os = null;
3307: try {
3308: os = formFile.getOutputStream(lock);
3309: os.write(buf.toString().getBytes(encoding));
3310: } catch (Exception ex) {
3311: PersistenceException pe = new PersistenceException(ex,
3312: "Cannot write to form file"); // NOI18N
3313: ErrorManager.getDefault().annotate(
3314: ex,
3315: FormUtils.getFormattedBundleString(
3316: "FMT_ERR_CannotWrtiteToFile", // NOI18N
3317: new Object[] { formFile.getNameExt() }));
3318: throw pe;
3319: } finally {
3320: try {
3321: if (os != null)
3322: os.close();
3323: } catch (IOException ex) {
3324: } // ignore
3325: lock.releaseLock();
3326: this .formModel = null;
3327: }
3328: }
3329:
3330: private void addFormSettings(Map<String, Object> auxValues) {
3331: FormSettings formSettings = formModel.getSettings();
3332: Map<String, Object> settings = formSettings.allSettings();
3333: Iterator<Map.Entry<String, Object>> iter = settings.entrySet()
3334: .iterator();
3335: while (iter.hasNext()) {
3336: Map.Entry<String, Object> entry = iter.next();
3337: String key = entry.getKey();
3338: if (!formSettings.isSessionSetting(key)) {
3339: auxValues.put(FORM_SETTINGS_PREFIX + key, entry
3340: .getValue());
3341: }
3342: }
3343: }
3344:
3345: private void saveAnyComponent(RADComponent comp, StringBuffer buf,
3346: String indent, boolean createElement) {
3347: String elementType = null;
3348: String elementIndent = indent;
3349: boolean visualMenuComp = comp instanceof RADVisualComponent
3350: && ((RADVisualComponent) comp).isMenuComponent();
3351: if (createElement) {
3352: if (comp instanceof RADMenuComponent) {
3353: elementType = XML_MENU_CONTAINER;
3354: } else if (comp instanceof RADMenuItemComponent) {
3355: elementType = XML_MENU_COMPONENT;
3356: } else if (comp instanceof ComponentContainer) {
3357: elementType = visualMenuComp ? XML_MENU_CONTAINER
3358: : XML_CONTAINER;
3359: } else {
3360: elementType = visualMenuComp ? XML_MENU_COMPONENT
3361: : XML_COMPONENT;
3362: }
3363:
3364: buf.append(elementIndent);
3365: addElementOpenAttr(buf, elementType, new String[] {
3366: ATTR_COMPONENT_CLASS, ATTR_COMPONENT_NAME },
3367: new String[] { comp.getBeanClass().getName(),
3368: comp.getName() });
3369:
3370: indent += ONE_INDENT;
3371: }
3372:
3373: if (visualMenuComp || comp instanceof RADMenuItemComponent) {
3374: saveMenuComponent(comp, buf, indent);
3375: } else if (comp instanceof ComponentContainer) {
3376: saveContainer((ComponentContainer) comp, buf, indent);
3377: } else if (comp instanceof RADVisualComponent) {
3378: saveVisualComponent((RADVisualComponent) comp, buf, indent);
3379: } else {
3380: saveComponent(comp, buf, indent);
3381: }
3382:
3383: if (createElement) {
3384: buf.append(elementIndent);
3385: addElementClose(buf, elementType);
3386: }
3387: }
3388:
3389: private void saveContainer(ComponentContainer container,
3390: StringBuffer buf, String indent) {
3391: RADVisualContainer visualContainer = container instanceof RADVisualContainer ? (RADVisualContainer) container
3392: : null;
3393:
3394: RADComponent[] children = null;
3395: int convIndex = -1; // index of layout in conversion table
3396:
3397: if (visualContainer != null) {
3398: saveVisualComponent(visualContainer, buf, indent);
3399: convIndex = saveLayout(visualContainer, buf, indent);
3400:
3401: // compatibility hack for saving form's menu bar (part II)
3402: if (container instanceof RADVisualFormContainer)
3403: children = visualContainer.getSubComponents();
3404: } else
3405: saveComponent((RADComponent) container, buf, indent);
3406:
3407: if (children == null)
3408: children = container.getSubBeans();
3409:
3410: if (children.length > 0) {
3411: buf.append(indent);
3412: addElementOpen(buf, XML_SUB_COMPONENTS);
3413: for (int i = 0; i < children.length; i++) {
3414: // if (children[i] instanceof RADMenuItemComponent)
3415: // raiseFormatVersion(NB33_VERSION);
3416: saveAnyComponent(children[i], buf, indent + ONE_INDENT,
3417: true);
3418: }
3419: buf.append(indent);
3420: addElementClose(buf, XML_SUB_COMPONENTS);
3421: }
3422:
3423: if (visualContainer != null && convIndex == LAYOUT_FROM_CODE)
3424: saveLayoutCode(visualContainer.getLayoutSupport(), buf,
3425: indent);
3426: }
3427:
3428: private int saveLayout(RADVisualContainer container,
3429: StringBuffer buf, String indent) {
3430: LayoutSupportManager layoutSupport = container
3431: .getLayoutSupport();
3432:
3433: if (layoutSupport == null) {
3434: // raiseFormatVersion(NB42_VERSION);
3435: RADVisualComponent[] subComponents = container
3436: .getSubComponents();
3437: Map<String, String> idToNameMap = new HashMap<String, String>();
3438: for (int i = 0; i < subComponents.length; i++) {
3439: RADVisualComponent comp = subComponents[i];
3440: idToNameMap.put(comp.getId(), comp.getName());
3441: }
3442: buf.append("\n"); // NOI18N
3443: buf.append(indent);
3444: addElementOpen(buf, XML_LAYOUT);
3445: LayoutModel layoutModel = formModel.getLayoutModel();
3446: int indentation = indent.length() / ONE_INDENT.length() + 1;
3447: LayoutComponent layoutComp = layoutModel
3448: .getLayoutComponent(container.getId());
3449: buf.append(layoutModel.saveContainerLayout(layoutComp,
3450: idToNameMap, indentation, false));
3451: buf.append(indent);
3452: addElementClose(buf, XML_LAYOUT);
3453: return LAYOUT_NATURAL;
3454: } // end of hack
3455:
3456: if (layoutSupport.isUnknownLayout())
3457: return LAYOUT_UNKNOWN;
3458:
3459: int convIndex = -1; // index in conversion table
3460:
3461: Class layoutClass = layoutSupport.getLayoutDelegate()
3462: .getSupportedClass();
3463: if (layoutClass == null)
3464: convIndex = LAYOUT_NULL;
3465: else {
3466: String className = layoutClass.getName();
3467: for (int i = 0; i < supportedClassNames.length; i++)
3468: if (className.equals(supportedClassNames[i])) {
3469: convIndex = i;
3470: break;
3471: }
3472:
3473: if (convIndex < 0) // not a standard layout
3474: return LAYOUT_FROM_CODE;
3475: }
3476:
3477: StringBuffer buf2 = new StringBuffer();
3478:
3479: if (convIndex != LAYOUT_ABSOLUTE && convIndex != LAYOUT_NULL) {
3480: Node.Property[] properties = layoutSupport
3481: .getAllProperties();
3482: for (int i = 0; i < properties.length; i++) {
3483: FormProperty property = (FormProperty) properties[i];
3484: if (property.isChanged()
3485: // NB 3.1 considered special values as default for
3486: // GridLayout, so we must always save rows and columns
3487: || (convIndex == LAYOUT_GRID && ("rows"
3488: .equals(property.getName()) // NOI18N
3489: || "columns".equals(property.getName())))) // NOI18N
3490: {
3491: String delegatePropName = property.getName();
3492: String layout31PropName = null;
3493: String[] delPropNames = layoutDelegatePropertyNames[convIndex];
3494: for (int j = 0; j < delPropNames.length; j++)
3495: if (delegatePropName.equals(delPropNames[j])) {
3496: layout31PropName = layout31PropertyNames[convIndex][j];
3497: break;
3498: }
3499:
3500: if (layout31PropName != null) {
3501: saveProperty(property, layout31PropName, buf2,
3502: indent + ONE_INDENT);
3503: }
3504: }
3505: }
3506: } else { // AbsoluteLayout and null layout are special...
3507: String nullLayout = convIndex == LAYOUT_NULL ? "true"
3508: : "false"; // NOI18N
3509: buf2.append(indent);
3510: buf2.append(ONE_INDENT);
3511: addLeafElementOpenAttr(buf2, XML_PROPERTY, new String[] {
3512: ATTR_PROPERTY_NAME, ATTR_PROPERTY_TYPE,
3513: ATTR_PROPERTY_VALUE }, new String[] {
3514: "useNullLayout", "boolean", nullLayout } // NOI18N
3515: );
3516: }
3517:
3518: buf.append("\n"); // NOI18N
3519: buf.append(indent);
3520: if (buf2.length() > 0) {
3521: addElementOpenAttr(buf, XML_LAYOUT,
3522: new String[] { ATTR_LAYOUT_CLASS },
3523: new String[] { PersistenceObjectRegistry
3524: .getPrimaryName(layout31Names[convIndex]) });
3525: buf.append(buf2);
3526: buf.append(indent);
3527: addElementClose(buf, XML_LAYOUT);
3528: } else {
3529: addLeafElementOpenAttr(buf, XML_LAYOUT,
3530: new String[] { ATTR_LAYOUT_CLASS },
3531: new String[] { PersistenceObjectRegistry
3532: .getPrimaryName(layout31Names[convIndex]) });
3533: }
3534:
3535: return convIndex;
3536: }
3537:
3538: private void saveLayoutCode(LayoutSupportManager layoutSupport,
3539: StringBuffer buf, String indent) {
3540: // raiseFormatVersion(NB33_VERSION);
3541: StringBuffer buf2 = new StringBuffer();
3542: String subIndent = indent + ONE_INDENT;
3543: // codeFlow = true;
3544:
3545: // layout manager code
3546: CodeGroup code = layoutSupport.getLayoutCode();
3547: if (code != null) {
3548: Iterator it = code.getStatementsIterator();
3549: while (it.hasNext()) {
3550: saveCodeStatement((CodeStatement) it.next(), buf2,
3551: subIndent);
3552: }
3553: }
3554:
3555: // components code
3556: for (int i = 0, n = layoutSupport.getComponentCount(); i < n; i++) {
3557: code = layoutSupport.getComponentCode(i);
3558: if (code != null) {
3559: Iterator it = code.getStatementsIterator();
3560: while (it.hasNext()) {
3561: saveCodeStatement((CodeStatement) it.next(), buf2,
3562: subIndent);
3563: }
3564: }
3565: }
3566:
3567: if (buf2.length() > 0) {
3568: buf.append(indent);
3569: addElementOpen(buf, XML_LAYOUT_CODE);
3570:
3571: buf.append(buf2.toString());
3572:
3573: buf.append(indent);
3574: addElementClose(buf, XML_LAYOUT_CODE);
3575: }
3576: }
3577:
3578: private void saveVisualComponent(RADVisualComponent component,
3579: StringBuffer buf, String indent) {
3580: saveComponent(component, buf, indent);
3581:
3582: RADVisualContainer container = component.getParentContainer();
3583: if (container == null || container.getLayoutSupport() == null)
3584: return;
3585:
3586: int componentIndex = container.getIndexOf(component);
3587: LayoutConstraints constr = container.getLayoutSupport()
3588: .getConstraints(componentIndex);
3589: if (constr == null)
3590: return; // no constraints
3591:
3592: StringBuffer buf2 = new StringBuffer(); // [might be not used at all]
3593: int convIndex = saveConstraints(constr, buf2, indent
3594: + ONE_INDENT + ONE_INDENT);
3595: if (convIndex >= 0) { // standard constraints (saved in buf2)
3596: buf.append(indent);
3597: addElementOpen(buf, XML_CONSTRAINTS);
3598: buf.append(indent + ONE_INDENT);
3599: addElementOpenAttr(
3600: buf,
3601: XML_CONSTRAINT,
3602: new String[] { ATTR_CONSTRAINT_LAYOUT,
3603: ATTR_CONSTRAINT_VALUE },
3604: new String[] {
3605: PersistenceObjectRegistry
3606: .getPrimaryName(layout31Names[convIndex]),
3607: PersistenceObjectRegistry
3608: .getPrimaryName(layout31ConstraintsNames[convIndex]) });
3609: buf.append(buf2);
3610: buf.append(indent + ONE_INDENT);
3611: addElementClose(buf, XML_CONSTRAINT);
3612: buf.append(indent);
3613: addElementClose(buf, XML_CONSTRAINTS);
3614: }
3615: }
3616:
3617: private int saveConstraints(LayoutConstraints constr,
3618: StringBuffer buf, String indent) {
3619: // constraints of BorderLayout
3620: if (constr instanceof BorderLayoutSupport.BorderConstraints) {
3621: String position = (String) constr.getConstraintsObject();
3622: buf.append(indent);
3623: addLeafElementOpenAttr(buf, "BorderConstraints", // NOI18N
3624: new String[] { "direction" }, // NOI18N
3625: new String[] { position });
3626:
3627: return LAYOUT_BORDER;
3628: }
3629:
3630: // constraints of GridBagLayout
3631: if (constr instanceof GridBagLayoutSupport.GridBagLayoutConstraints) {
3632: java.awt.GridBagConstraints gbConstr = (java.awt.GridBagConstraints) constr
3633: .getConstraintsObject();
3634:
3635: buf.append(indent);
3636: addLeafElementOpenAttr(buf, "GridBagConstraints", // NOI18N
3637: new String[] { "gridX", "gridY", "gridWidth",
3638: "gridHeight", // NOI18N
3639: "fill", "ipadX", "ipadY", // NOI18N
3640: "insetsTop", "insetsLeft", // NOI18N
3641: "insetsBottom", "insetsRight", // NOI18N
3642: "anchor", "weightX", "weightY" }, // NOI18N
3643: new String[] { Integer.toString(gbConstr.gridx),
3644: Integer.toString(gbConstr.gridy),
3645: Integer.toString(gbConstr.gridwidth),
3646: Integer.toString(gbConstr.gridheight),
3647: Integer.toString(gbConstr.fill),
3648: Integer.toString(gbConstr.ipadx),
3649: Integer.toString(gbConstr.ipady),
3650: Integer.toString(gbConstr.insets.top),
3651: Integer.toString(gbConstr.insets.left),
3652: Integer.toString(gbConstr.insets.bottom),
3653: Integer.toString(gbConstr.insets.right),
3654: Integer.toString(gbConstr.anchor),
3655: Double.toString(gbConstr.weightx),
3656: Double.toString(gbConstr.weighty) });
3657:
3658: return LAYOUT_GRIDBAG;
3659: }
3660:
3661: // constraints of JTabbedPane
3662: if (constr instanceof JTabbedPaneSupport.TabConstraints) {
3663: JTabbedPaneSupport.TabConstraints tabConstr = (JTabbedPaneSupport.TabConstraints) constr;
3664:
3665: StringBuffer buf2 = new StringBuffer();
3666: Node.Property[] tabProperties = constr.getProperties();
3667:
3668: for (int i = 0; i < tabProperties.length; i++) {
3669: FormProperty prop = (FormProperty) tabProperties[i];
3670: if (prop.isChanged())
3671: saveProperty(prop, prop.getName().substring(
3672: "TabConstraints ".length()), // NOI18N
3673: buf2, indent + ONE_INDENT);
3674: }
3675:
3676: buf.append(indent);
3677: if (buf2.length() > 0) {
3678: addElementOpenAttr(buf, "JTabbedPaneConstraints", // NOI18N
3679: new String[] { "tabName", "toolTip" }, // NOI18N
3680: new String[] { tabConstr.getTitle(),
3681: tabConstr.getToolTip() });
3682: buf.append(buf2);
3683: buf.append(indent);
3684: addElementClose(buf, "JTabbedPaneConstraints"); // NOI18N
3685: } else {
3686: addLeafElementOpenAttr(buf, "JTabbedPaneConstraints", // NOI18N
3687: new String[] { "tabName", "toolTip" }, // NOI18N
3688: new String[] { tabConstr.getTitle(),
3689: tabConstr.getToolTip() });
3690: }
3691:
3692: return LAYOUT_JTAB;
3693: }
3694:
3695: // constraints of JSplitPane
3696: if (constr instanceof JSplitPaneSupport.SplitConstraints) {
3697: Object constrObject = constr.getConstraintsObject();
3698: String position;
3699:
3700: if (javax.swing.JSplitPane.TOP.equals(constrObject))
3701: position = "top"; // NOI18N
3702: else if (javax.swing.JSplitPane.BOTTOM.equals(constrObject))
3703: position = "bottom"; // NOI18N
3704: else if (javax.swing.JSplitPane.LEFT.equals(constrObject))
3705: position = "left"; // NOI18N
3706: else
3707: position = "right"; // NOI18N
3708:
3709: buf.append(indent);
3710: addLeafElementOpenAttr(buf, "JSplitPaneConstraints", // NOI18N
3711: new String[] { "position" }, // NOI18N
3712: new String[] { position });
3713:
3714: return LAYOUT_JSPLIT;
3715: }
3716:
3717: // constraints of CardLayout
3718: if (constr instanceof CardLayoutSupport.CardConstraints) {
3719: String card = (String) constr.getConstraintsObject();
3720: buf.append(indent);
3721: addLeafElementOpenAttr(buf, "CardConstraints", // NOI18N
3722: new String[] { "cardName" }, // NOI18N
3723: new String[] { card });
3724:
3725: return LAYOUT_CARD;
3726: }
3727:
3728: // constraints of JLayeredPane (must be tested before AbsoluteLayout)
3729: if (constr instanceof JLayeredPaneSupport.LayeredConstraints) {
3730: int layer = ((JLayeredPaneSupport.LayeredConstraints) constr)
3731: .getLayer();
3732: java.awt.Rectangle r = ((JLayeredPaneSupport.LayeredConstraints) constr)
3733: .getBounds();
3734:
3735: buf.append(indent);
3736: addLeafElementOpenAttr(buf, "JLayeredPaneConstraints", // NOI18N
3737: new String[] { "x", "y", "width", "height", // NOI18N
3738: "layer", "position" }, // NOI18N
3739: new String[] { Integer.toString(r.x),
3740: Integer.toString(r.y),
3741: Integer.toString(r.width),
3742: Integer.toString(r.height),
3743: Integer.toString(layer), "-1" }); // NOI18N
3744:
3745: return LAYOUT_JLAYER;
3746: }
3747:
3748: // constraints of AbsoluteLayout
3749: if (constr instanceof AbsoluteLayoutSupport.AbsoluteLayoutConstraints) {
3750: java.awt.Rectangle r = ((AbsoluteLayoutSupport.AbsoluteLayoutConstraints) constr)
3751: .getBounds();
3752:
3753: buf.append(indent);
3754: addLeafElementOpenAttr(buf, "AbsoluteConstraints", // NOI18N
3755: new String[] { "x", "y", "width", "height" }, // NOI18N
3756: new String[] { Integer.toString(r.x),
3757: Integer.toString(r.y),
3758: Integer.toString(r.width),
3759: Integer.toString(r.height) });
3760:
3761: return LAYOUT_ABSOLUTE;
3762: }
3763:
3764: return -1;
3765: }
3766:
3767: private void saveMenuComponent(RADComponent component,
3768: StringBuffer buf, String indent) {
3769: saveComponent(component, buf, indent);
3770:
3771: if (component instanceof ComponentContainer) {
3772: RADComponent[] children = ((ComponentContainer) component)
3773: .getSubBeans();
3774: if (children.length > 0) {
3775: buf.append(indent);
3776: addElementOpen(buf, XML_SUB_COMPONENTS);
3777: for (int i = 0; i < children.length; i++) {
3778: String elementType = children[i] instanceof ComponentContainer ? XML_MENU_CONTAINER
3779: : XML_MENU_COMPONENT;
3780: buf.append(indent + ONE_INDENT);
3781: addElementOpenAttr(buf, elementType,
3782: new String[] { ATTR_COMPONENT_CLASS,
3783: ATTR_COMPONENT_NAME },
3784: new String[] {
3785: children[i].getBeanClass()
3786: .getName(),
3787: children[i].getName() });
3788: saveMenuComponent(children[i], buf, indent
3789: + ONE_INDENT + ONE_INDENT);
3790: buf.append(indent + ONE_INDENT);
3791: addElementClose(buf, elementType);
3792: }
3793: buf.append(indent);
3794: addElementClose(buf, XML_SUB_COMPONENTS);
3795: }
3796: }
3797: }
3798:
3799: private void saveComponent(RADComponent component,
3800: StringBuffer buf, String indent) {
3801: // 1. Properties
3802: if (!JavaCodeGenerator.VALUE_SERIALIZE.equals(component
3803: .getAuxValue(JavaCodeGenerator.AUX_CODE_GENERATION))) { // save properties only if the component is not to be serialized
3804: saveProperties(component.getKnownBeanProperties(),
3805: XML_PROPERTIES, buf, indent);
3806:
3807: if (component instanceof RADVisualComponent) {
3808: // try to save accessibility properties
3809: FormProperty[] accProps = ((RADVisualComponent) component)
3810: .getAccessibilityProperties();
3811: saveProperties(accProps, XML_A11Y_PROPERTIES, buf,
3812: indent);
3813: // if (saveProperties(accProps,
3814: // XML_A11Y_PROPERTIES, buf, indent))
3815: // raiseFormatVersion(NB34_VERSION);
3816: }
3817: }
3818:
3819: // 2. Binding properties
3820: saveBindingProperties(component, buf, indent);
3821:
3822: // 3. Synthetic properties
3823: if (component instanceof RADVisualFormContainer)
3824: saveSyntheticProperties(component, buf, indent);
3825:
3826: // 4. Events
3827: saveEvents(component.getKnownEvents(), buf, indent);
3828:
3829: // 5. Aux Values
3830: Map<String, Object> auxValues = component.getAuxValues();
3831: // Form settings are stored as a part of AuxValues of top-level container
3832: if (component == formModel.getTopRADComponent()) {
3833: auxValues = (auxValues == null) ? new TreeMap<String, Object>()
3834: : new TreeMap<String, Object>(auxValues);
3835: addFormSettings(auxValues);
3836: }
3837: if (auxValues != null && auxValues.size() > 0) {
3838: // buf.append("\n"); // NOI18N
3839: buf.append(indent);
3840: addElementOpen(buf, XML_AUX_VALUES);
3841: saveAuxValues(auxValues, buf, indent + ONE_INDENT);
3842: buf.append(indent);
3843: addElementClose(buf, XML_AUX_VALUES);
3844: }
3845: }
3846:
3847: private boolean saveProperties(FormProperty[] props,
3848: String blockName, StringBuffer buf, String indent) {
3849: int i = 0;
3850: do {
3851: if (i >= props.length)
3852: return false; // nothing saved
3853: FormProperty prop = props[i];
3854: if ((prop.isChanged() && !ResourceSupport
3855: .isInjectedProperty(prop))
3856: || prop.getPreCode() != null
3857: || prop.getPostCode() != null)
3858: break;
3859: i++;
3860: } while (true);
3861:
3862: buf.append(indent);
3863: addElementOpen(buf, blockName);
3864:
3865: for (i = 0; i < props.length; i++) {
3866: FormProperty prop = props[i];
3867: if (!prop.isChanged()
3868: || ResourceSupport.isInjectedProperty(prop)) {
3869: if (prop.getPreCode() != null
3870: || prop.getPostCode() != null) {
3871: buf.append(indent + ONE_INDENT);
3872: // in this case save only the pre/post code
3873: addLeafElementOpenAttr(buf, XML_PROPERTY,
3874: new String[] { ATTR_PROPERTY_NAME,
3875: ATTR_PROPERTY_PRE_CODE,
3876: ATTR_PROPERTY_POST_CODE, },
3877: new String[] { prop.getName(),
3878: prop.getPreCode(),
3879: prop.getPostCode(), });
3880: }
3881: continue; // not changed, so do not save value
3882: }
3883:
3884: saveProperty(prop, prop.getName(), buf, indent + ONE_INDENT);
3885: }
3886:
3887: buf.append(indent);
3888: addElementClose(buf, blockName);
3889:
3890: return true;
3891: }
3892:
3893: private boolean saveProperty(FormProperty property,
3894: String propertyName, StringBuffer buf, String indent) {
3895: Object value;
3896: Object realValue;
3897: try {
3898: value = property.getValue();
3899: realValue = property.getRealValue();
3900: } catch (Exception ex) {
3901: ErrorManager.getDefault().annotate(
3902: ex,
3903: FormUtils.getFormattedBundleString(
3904: "FMT_ERR_CannotGetPropertyValue", // NOI18N
3905: new Object[] { property.getName() }));
3906: nonfatalErrors.add(ex);
3907: return false;
3908: }
3909:
3910: String resourceKey = null;
3911: String noResource = null;
3912: org.w3c.dom.Node valueNode = null;
3913: String encodedValue = null;
3914: String encodedSerializeValue = null;
3915:
3916: PropertyEditor prEd = property.getCurrentEditor();
3917:
3918: // if (prEd instanceof FontEditor) { // Issue 82465: new prEd in NB 6.0
3919: // raiseFormatVersion(NB60_VERSION);
3920: // }
3921:
3922: if (value instanceof ResourceValue) {
3923: resourceKey = ((ResourceValue) value).getKey();
3924: }
3925: // if (resourceKey != null) { // just save the key, not the value
3926: // raiseFormatVersion(NB60_VERSION);
3927: // }
3928: if (resourceKey == null) {
3929: if (prEd instanceof ResourceWrapperEditor) {
3930: prEd = ((ResourceWrapperEditor) prEd)
3931: .getDelegatedPropertyEditor();
3932: if (ResourceSupport.isResourceableProperty(property)
3933: && ResourceSupport.isExcludedProperty(property)) {
3934: noResource = "true"; // NOI18N
3935: // raiseFormatVersion(NB60_VERSION);
3936: }
3937: }
3938:
3939: if (prEd instanceof BeanPropertyEditor) {
3940: prEd.setValue(value);
3941: if (((BeanPropertyEditor) prEd).valueIsBeanProperty()) {
3942: valueNode = saveBeanToXML(realValue.getClass(),
3943: topDocument);
3944: }
3945: }
3946: if (valueNode == null && prEd instanceof XMLPropertyEditor) {
3947: prEd.setValue(value);
3948: valueNode = ((XMLPropertyEditor) prEd)
3949: .storeToXML(topDocument);
3950: // if (valueNode == null) { // property editor refused to save the value
3951: // PersistenceException ex = new PersistenceException(
3952: // "Cannot save the property value"); // NOI18N
3953: // String msg = FormUtils.getFormattedBundleString(
3954: // "FMT_ERR_CannotSaveProperty", // NOI18N
3955: // new Object[] { property.getName() });
3956: // ErrorManager.getDefault().annotate(
3957: // ex, ErrorManager.ERROR, null, msg, null, null);
3958: // nonfatalErrors.add(ex);
3959: // return false;
3960: // }
3961: }
3962: if (valueNode == null) { // save as primitive or serialized value
3963: encodedValue = encodePrimitiveValue(value);
3964: if (encodedValue == null) {
3965: try {
3966: encodedSerializeValue = encodeValue(value);
3967: } catch (Exception ex) {
3968: ErrorManager.getDefault().annotate(
3969: ex,
3970: FormUtils.getFormattedBundleString(
3971: "FMT_ERR_CannotSaveProperty", // NOI18N
3972: new Object[] { property
3973: .getName() }));
3974: nonfatalErrors.add(ex);
3975: return false;
3976: }
3977: }
3978: }
3979: }
3980:
3981: buf.append(indent);
3982:
3983: if (valueNode != null || encodedSerializeValue != null) {
3984: // value is encoded by XMLPrpertyEditor or serialized
3985: addElementOpenAttr(buf, XML_PROPERTY, new String[] {
3986: ATTR_PROPERTY_NAME, ATTR_PROPERTY_TYPE,
3987: ATTR_PROPERTY_NORES, ATTR_PROPERTY_EDITOR,
3988: ATTR_PROPERTY_PRE_CODE, ATTR_PROPERTY_POST_CODE },
3989: new String[] { propertyName,
3990: property.getValueType().getName(),
3991: noResource, prEd.getClass().getName(),
3992: property.getPreCode(),
3993: property.getPostCode() });
3994:
3995: if (valueNode != null) {
3996: if (prEd instanceof BeanPropertyEditor
3997: && ((BeanPropertyEditor) prEd)
3998: .valueIsBeanProperty()) { // the property is a bean,
3999: // so there could be some children nodes ...
4000: saveBeanProperty((BeanPropertyEditor) prEd,
4001: valueNode, buf, indent + ONE_INDENT);
4002: } else {
4003: saveNodeIntoText(buf, valueNode, indent
4004: + ONE_INDENT);
4005: }
4006: } else {
4007: buf.append(indent + ONE_INDENT);
4008: addLeafElementOpenAttr(buf,
4009: XML_SERIALIZED_PROPERTY_VALUE,
4010: new String[] { ATTR_PROPERTY_VALUE },
4011: new String[] { encodedSerializeValue });
4012: }
4013: buf.append(indent);
4014: addElementClose(buf, XML_PROPERTY);
4015: } else { // primitive value or resource - just one element with attributes
4016: addLeafElementOpenAttr(buf, XML_PROPERTY, new String[] {
4017: ATTR_PROPERTY_NAME, ATTR_PROPERTY_TYPE,
4018: ATTR_PROPERTY_VALUE, ATTR_PROPERTY_RES_KEY,
4019: ATTR_PROPERTY_NORES, ATTR_PROPERTY_PRE_CODE,
4020: ATTR_PROPERTY_POST_CODE }, new String[] {
4021: propertyName, property.getValueType().getName(),
4022: encodedValue, resourceKey, noResource,
4023: property.getPreCode(), property.getPostCode() });
4024: }
4025: return true;
4026: }
4027:
4028: private org.w3c.dom.Node saveBeanToXML(Class type,
4029: org.w3c.dom.Document doc) {
4030: org.w3c.dom.Element el = doc.createElement(XML_PROPERTY_BEAN);
4031: el.setAttribute(ATTR_PROPERTY_TYPE, type.getName());
4032: return el;
4033: }
4034:
4035: private void saveBeanProperty(
4036: BeanPropertyEditor beanPropertyEditor,
4037: org.w3c.dom.Node valueNode, StringBuffer buf, String indent) {
4038: boolean children = false;
4039: FormProperty[] props = (FormProperty[]) beanPropertyEditor
4040: .getProperties();
4041:
4042: NamedNodeMap attributes = valueNode.getAttributes();
4043: String[] attrNames = new String[attributes.getLength()];
4044: String[] attrValues = new String[attributes.getLength()];
4045:
4046: for (int i = 0; i < attrValues.length; i++) {
4047: attrNames[i] = attributes.item(i).getNodeName();
4048: attrValues[i] = attributes.item(i).getNodeValue();
4049: }
4050:
4051: for (int i = 0; i < props.length; i++) {
4052: if (props[i].isChanged()) {
4053: if (!children) {
4054: // we found the first child property,
4055: // let's start the element tag
4056: buf.append(indent);
4057: addElementOpenAttr(buf, valueNode.getNodeName(),
4058: attrNames, attrValues);
4059: children = true;
4060: }
4061: saveProperty(props[i], props[i].getName(), buf, indent
4062: + ONE_INDENT);
4063: }
4064: }
4065:
4066: if (children) {
4067: // there were children properties,
4068: // we should close the element tag
4069: buf.append(indent);
4070: addElementClose(buf, valueNode.getNodeName());
4071: } else {
4072: // there were no children properties,
4073: // let's save the node as it is
4074: saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
4075: }
4076: }
4077:
4078: private boolean saveValue(Object value, Class valueType,
4079: PropertyEditor prEd, StringBuffer buf, String indent) {
4080: String encodedValue = null;
4081: String encodedSerializeValue = null;
4082: org.w3c.dom.Node valueNode = null;
4083:
4084: if (prEd instanceof XMLPropertyEditor) {
4085: prEd.setValue(value);
4086: valueNode = ((XMLPropertyEditor) prEd)
4087: .storeToXML(topDocument);
4088: if (valueNode == null) { // property editor refused to save the value
4089: PersistenceException ex = new PersistenceException(
4090: "Cannot save the property value"); // NOI18N
4091: String msg = FormUtils.getFormattedBundleString(
4092: "FMT_ERR_CannotSaveProperty2", // NOI18N
4093: new Object[] { prEd.getClass().getName() });
4094: ErrorManager.getDefault().annotate(ex,
4095: ErrorManager.ERROR, null, msg, null, null);
4096: nonfatalErrors.add(ex);
4097: return false;
4098: }
4099: } else {
4100: encodedValue = encodePrimitiveValue(value);
4101: if (encodedValue == null) {
4102: try {
4103: encodedSerializeValue = encodeValue(value);
4104: } catch (Exception ex) {
4105: ErrorManager.getDefault().annotate(
4106: ex,
4107: FormUtils.getFormattedBundleString(
4108: "FMT_ERR_CannotSaveProperty3", // NOI18N
4109: new Object[] { valueType.getClass()
4110: .getName() }));
4111: nonfatalErrors.add(ex);
4112: return false;
4113: }
4114: }
4115: }
4116:
4117: buf.append(indent);
4118:
4119: if (encodedValue != null) {
4120: addLeafElementOpenAttr(buf, XML_VALUE, new String[] {
4121: ATTR_PROPERTY_TYPE, ATTR_PROPERTY_VALUE },
4122: new String[] { valueType.getName(), encodedValue });
4123: } else {
4124: addElementOpenAttr(buf, XML_VALUE, new String[] {
4125: ATTR_PROPERTY_TYPE, ATTR_PROPERTY_EDITOR },
4126: new String[] { valueType.getName(),
4127: prEd.getClass().getName() });
4128:
4129: if (valueNode != null) {
4130: saveNodeIntoText(buf, valueNode, indent + ONE_INDENT);
4131: } else {
4132: buf.append(indent + ONE_INDENT);
4133: addLeafElementOpenAttr(buf,
4134: XML_SERIALIZED_PROPERTY_VALUE,
4135: new String[] { ATTR_PROPERTY_VALUE },
4136: new String[] { encodedSerializeValue });
4137: }
4138: buf.append(indent);
4139: addElementClose(buf, XML_VALUE);
4140: }
4141: return true;
4142: }
4143:
4144: private void saveBindingProperties(RADComponent component,
4145: StringBuffer buf, String indent) {
4146: boolean anyProp = false;
4147: String indent2 = null;
4148:
4149: BindingProperty[] props = component.getAllBindingProperties();
4150: for (int i = 0; i < props.length; i++) {
4151: BindingProperty prop = props[i];
4152:
4153: Object value = null;
4154: try {
4155: value = prop.getValue();
4156: } catch (Exception ex) {
4157: ErrorManager.getDefault().annotate(
4158: ex,
4159: FormUtils.getFormattedBundleString(
4160: "FMT_ERR_CannotGetPropertyValue", // NOI18N
4161: new Object[] { prop.getName() }));
4162: nonfatalErrors.add(ex);
4163: continue;
4164: }
4165:
4166: // don't save default values
4167: if (value == null)
4168: continue;
4169:
4170: // PENDING encodePrimitiveValue(value);
4171:
4172: if (!anyProp) {
4173: buf.append(indent);
4174: addElementOpen(buf, XML_BINDING_PROPERTIES);
4175: indent2 = indent + ONE_INDENT;
4176: anyProp = true;
4177: }
4178:
4179: saveBinding(prop, buf, indent2);
4180: }
4181:
4182: if (anyProp) {
4183: buf.append(indent);
4184: addElementClose(buf, XML_BINDING_PROPERTIES);
4185: }
4186: }
4187:
4188: private void saveBindingParameters(MetaBinding binding,
4189: StringBuffer buf, String indent) {
4190: Map<String, String> parameters = binding.getParameters();
4191: Iterator<Map.Entry<String, String>> iter = parameters
4192: .entrySet().iterator();
4193: while (iter.hasNext()) {
4194: Map.Entry<String, String> entry = iter.next();
4195: buf.append(indent);
4196: addLeafElementOpenAttr(buf, XML_BINDING_PARAMETER,
4197: new String[] { ATTR_BINDING_PARAMETER_NAME,
4198: ATTR_BINDING_PARAMETER_VALUE },
4199: new String[] { entry.getKey(), entry.getValue() });
4200: }
4201: }
4202:
4203: private void saveBinding(BindingProperty prop, StringBuffer buf,
4204: String indent) {
4205: String propName = prop.getName();
4206: MetaBinding binding = prop.getValue();
4207: buf.append(indent);
4208: if (binding.hasSubBindings()
4209: || !binding.getParameters().isEmpty()
4210: || binding.isIncompletePathValueSpecified()
4211: || binding.isNullValueSpecified()
4212: || binding.isConverterSpecified()
4213: || binding.isValidatorSpecified()
4214: || binding.isNameSpecified()) {
4215: addElementOpenAttr(buf, XML_BINDING_PROPERTY, new String[] {
4216: ATTR_PROPERTY_NAME, ATTR_BINDING_SOURCE,
4217: ATTR_BINDING_SOURCE_PATH, ATTR_BINDING_TARGET,
4218: ATTR_BINDING_TARGET_PATH,
4219: ATTR_BINDING_UPDATE_STRATEGY,
4220: ATTR_BINDING_IMMEDIATELY }, new String[] {
4221: propName, binding.getSource().getName(),
4222: binding.getSourcePath(),
4223: binding.getTarget().getName(),
4224: binding.getTargetPath(),
4225: Integer.toString(binding.getUpdateStrategy()),
4226: Boolean.toString(binding.isBindImmediately()) });
4227:
4228: // Save parameters
4229: String indent2 = indent + ONE_INDENT;
4230: saveBindingParameters(binding, buf, indent2);
4231:
4232: if (binding.isNullValueSpecified()) {
4233: saveProperty(prop.getNullValueProperty(), prop
4234: .getNullValueProperty().getName(), buf, indent2);
4235: }
4236: if (binding.isIncompletePathValueSpecified()) {
4237: saveProperty(prop.getIncompleteValueProperty(), prop
4238: .getIncompleteValueProperty().getName(), buf,
4239: indent2);
4240: }
4241: if (binding.isConverterSpecified()) {
4242: saveProperty(prop.getConverterProperty(), prop
4243: .getConverterProperty().getName(), buf, indent2);
4244: }
4245: if (binding.isValidatorSpecified()) {
4246: saveProperty(prop.getValidatorProperty(), prop
4247: .getValidatorProperty().getName(), buf, indent2);
4248: }
4249: if (binding.isNameSpecified()) {
4250: saveProperty(prop.getNameProperty(), prop
4251: .getNameProperty().getName(), buf, indent2);
4252: }
4253:
4254: // Save subbindings
4255: if (binding.hasSubBindings()) {
4256: for (MetaBinding subbinding : binding.getSubBindings()) {
4257: buf.append(indent2);
4258: addElementOpenAttr(buf, XML_SUBBINDING,
4259: new String[] { ATTR_BINDING_SOURCE_PATH,
4260: ATTR_BINDING_TARGET_PATH },
4261: new String[] { subbinding.getSourcePath(),
4262: subbinding.getTargetPath() });
4263:
4264: // Save parameters
4265: String indent3 = indent2 + ONE_INDENT;
4266: saveBindingParameters(subbinding, buf, indent3);
4267:
4268: buf.append(indent2);
4269: addElementClose(buf, XML_SUBBINDING);
4270: }
4271: }
4272:
4273: buf.append(indent);
4274: addElementClose(buf, XML_BINDING_PROPERTY);
4275: } else {
4276: addLeafElementOpenAttr(buf, XML_BINDING_PROPERTY,
4277: new String[] { ATTR_PROPERTY_NAME,
4278: ATTR_BINDING_SOURCE,
4279: ATTR_BINDING_SOURCE_PATH,
4280: ATTR_BINDING_TARGET,
4281: ATTR_BINDING_TARGET_PATH,
4282: ATTR_BINDING_UPDATE_STRATEGY,
4283: ATTR_BINDING_IMMEDIATELY }, new String[] {
4284: propName,
4285: binding.getSource().getName(),
4286: binding.getSourcePath(),
4287: binding.getTarget().getName(),
4288: binding.getTargetPath(),
4289: Integer.toString(binding
4290: .getUpdateStrategy()),
4291: Boolean.toString(binding
4292: .isBindImmediately()) });
4293: }
4294: }
4295:
4296: private void saveSyntheticProperties(RADComponent component,
4297: StringBuffer buf, String indent) {
4298: boolean anyProp = false;
4299: String indent2 = null;
4300:
4301: // compatibility hack for saving form's menu bar (part III)
4302: if (component instanceof RADVisualFormContainer) {
4303: RADComponent menuComp = ((RADVisualFormContainer) component)
4304: .getContainerMenu();
4305: if (menuComp != null) {
4306: buf.append(indent);
4307: addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
4308: indent2 = indent + ONE_INDENT;
4309: anyProp = true;
4310:
4311: buf.append(indent2);
4312: addLeafElementOpenAttr(
4313: buf,
4314: XML_SYNTHETIC_PROPERTY,
4315: new String[] { ATTR_PROPERTY_NAME,
4316: ATTR_PROPERTY_TYPE, ATTR_PROPERTY_VALUE },
4317: new String[] { "menuBar", // NOI18N
4318: "java.lang.String", // NOI18N
4319: menuComp.getName() });
4320: }
4321: }
4322:
4323: Node.Property[] props = component.getSyntheticProperties();
4324: for (int i = 0; i < props.length; i++) {
4325: Node.Property prop = props[i];
4326:
4327: if (!prop.canWrite())
4328: continue; // don't save read-only properties
4329:
4330: if (Boolean.TRUE.equals(prop.getValue("defaultValue"))) // NOI18N
4331: continue; // don't save default values
4332:
4333: Object value = null;
4334: try {
4335: value = prop.getValue();
4336: } catch (Exception ex) {
4337: ErrorManager.getDefault().annotate(
4338: ex,
4339: FormUtils.getFormattedBundleString(
4340: "FMT_ERR_CannotGetPropertyValue", // NOI18N
4341: new Object[] { prop.getName() }));
4342: nonfatalErrors.add(ex);
4343: continue;
4344: }
4345: String valueType = prop.getValueType().getName();
4346: String encodedValue = encodePrimitiveValue(value);
4347: if (encodedValue == null) {
4348: try {
4349: encodedValue = encodeValue(value);
4350: } catch (Exception ex) {
4351: ErrorManager.getDefault().annotate(
4352: ex,
4353: FormUtils.getFormattedBundleString(
4354: "FMT_ERR_CannotSaveProperty", // NOI18N
4355: new Object[] { prop.getName() }));
4356: nonfatalErrors.add(ex);
4357: continue;
4358: }
4359: }
4360:
4361: if (!anyProp) {
4362: buf.append(indent);
4363: addElementOpen(buf, XML_SYNTHETIC_PROPERTIES);
4364: indent2 = indent + ONE_INDENT;
4365: anyProp = true;
4366: }
4367:
4368: buf.append(indent2);
4369: addLeafElementOpenAttr(buf, XML_SYNTHETIC_PROPERTY,
4370: new String[] { ATTR_PROPERTY_NAME,
4371: ATTR_PROPERTY_TYPE, ATTR_PROPERTY_VALUE, },
4372: new String[] { prop.getName(), valueType,
4373: encodedValue, });
4374: }
4375:
4376: if (anyProp) {
4377: buf.append(indent);
4378: addElementClose(buf, XML_SYNTHETIC_PROPERTIES);
4379: }
4380: }
4381:
4382: private void saveEvents(Event[] events, StringBuffer buf,
4383: String indent) {
4384: boolean anyEvent = false;
4385: String indent2 = null;
4386: StringBuffer strbuf;
4387:
4388: for (int i = 0; i < events.length; i++) {
4389: Event event = events[i];
4390: if (!event.hasEventHandlers())
4391: continue;
4392:
4393: if (!anyEvent) {
4394: buf.append(indent);
4395: addElementOpen(buf, XML_EVENTS);
4396: indent2 = indent + ONE_INDENT;
4397: anyEvent = true;
4398: }
4399:
4400: strbuf = new StringBuffer(50);
4401: Class[] params = event.getListenerMethod()
4402: .getParameterTypes();
4403: for (int j = 0; j < params.length; j++) {
4404: strbuf.append(params[j].getName());
4405: if (j + 1 < params.length)
4406: strbuf.append(","); // NOI18N
4407: }
4408: String paramString = strbuf.toString();
4409:
4410: strbuf = new StringBuffer(50);
4411: String[] handlers = event.getEventHandlers();
4412: for (int j = 0; j < handlers.length; j++) {
4413: strbuf.append(handlers[j]);
4414: if (j + 1 < handlers.length)
4415: strbuf.append(","); // NOI18N
4416: }
4417: String handlerString = strbuf.toString();
4418:
4419: buf.append(indent2);
4420: addLeafElementOpenAttr(buf, XML_EVENT, new String[] {
4421: ATTR_EVENT_NAME, ATTR_EVENT_LISTENER,
4422: ATTR_EVENT_PARAMS, ATTR_EVENT_HANDLER },
4423: new String[] {
4424: event.getListenerMethod().getName(),
4425: event.getListenerMethod()
4426: .getDeclaringClass().getName(),
4427: paramString, handlerString });
4428: }
4429:
4430: if (anyEvent) {
4431: buf.append(indent);
4432: addElementClose(buf, XML_EVENTS);
4433: }
4434: }
4435:
4436: private void saveAuxValues(Map<String, Object> auxValues,
4437: StringBuffer buf, String indent) {
4438: for (Iterator<Map.Entry<String, Object>> it = auxValues
4439: .entrySet().iterator(); it.hasNext();) {
4440: Map.Entry<String, Object> entry = it.next();
4441: String valueName = entry.getKey();
4442: Object value = entry.getValue();
4443: if (value == null)
4444: continue; // such values are not saved
4445: String valueType = value.getClass().getName();
4446: String encodedValue = encodePrimitiveValue(value);
4447: if (encodedValue == null) {
4448: try {
4449: encodedValue = encodeValue(value);
4450: } catch (Exception ex) {
4451: ErrorManager.getDefault().annotate(
4452: ex,
4453: FormUtils.getFormattedBundleString(
4454: "FMT_ERR_CannotSaveProperty", // NOI18N
4455: new Object[] { valueName }));
4456: nonfatalErrors.add(ex);
4457: continue;
4458: }
4459: }
4460:
4461: buf.append(indent);
4462: addLeafElementOpenAttr(buf, XML_AUX_VALUE,
4463: new String[] { ATTR_AUX_NAME, ATTR_AUX_VALUE_TYPE,
4464: ATTR_AUX_VALUE }, new String[] { valueName,
4465: valueType, encodedValue });
4466: }
4467: }
4468:
4469: private PropertyEditor createPropertyEditor(Class editorClass,
4470: Class propertyType, FormProperty property)
4471: throws InstantiationException, IllegalAccessException {
4472: PropertyEditor ed;
4473: if (editorClass.equals(RADConnectionPropertyEditor.class)) {
4474: ed = new RADConnectionPropertyEditor(propertyType);
4475: } else if (editorClass.equals(ComponentChooserEditor.class)) {
4476: ed = new ComponentChooserEditor(
4477: new Class[] { propertyType });
4478: } else {
4479: ed = (PropertyEditor) editorClass.newInstance();
4480: }
4481:
4482: if (property != null)
4483: property.getPropertyContext().initPropertyEditor(ed,
4484: property);
4485: else if (ed instanceof FormAwareEditor)
4486: ((FormAwareEditor) ed).setContext(formModel, null);
4487:
4488: return ed;
4489: }
4490:
4491: // ---------------------
4492: // The following code ensures persistence of code structure in XML. The
4493: // code is quite general except special hacks for meta components which
4494: // must be handled specially (as references) - as we don't save full code
4495: // yet but only its parts; components are saved separately. [This feature
4496: // is used only for saving/loading code of non-standard layout supports.]
4497: //
4498: // There are two possible ways how to save the code structure - to save
4499: // the code flow or the static structure.
4500: //
4501: // In the first case (code flow), a sequence of code statements is saved
4502: // (together with epxressions used by the statements). In the second case
4503: // (static structure), root code expressions are saved as trees including
4504: // all used expressions and all defined statements. Which style is used
4505: // is controlled by the codeFlow variable. [We use only code flow now.]
4506:
4507: // XML persistence of code structure - saving
4508:
4509: private void saveCodeExpression(CodeExpression exp,
4510: StringBuffer buf, String indent) {
4511: buf.append(indent);
4512:
4513: Object value = getExpressionsMap().get(exp);
4514: if (value != null) { // save expression reference only
4515: addLeafElementOpenAttr(buf, XML_CODE_EXPRESSION,
4516: new String[] { ATTR_EXPRESSION_ID },
4517: new String[] { value.toString() });
4518: } else { // save complete expression
4519: // create expression ID
4520: lastExpId++;
4521: String expId = Integer.toString(lastExpId);
4522: CodeVariable var = exp.getVariable();
4523: if (var != null)
4524: expId += "_" + var.getName(); // NOI18N
4525: getExpressionsMap().put(exp, expId);
4526:
4527: addElementOpenAttr(buf, XML_CODE_EXPRESSION,
4528: new String[] { ATTR_EXPRESSION_ID },
4529: new String[] { expId });
4530:
4531: String subIndent = indent + ONE_INDENT;
4532:
4533: if (var != null)
4534: saveCodeVariable(var, buf, subIndent);
4535:
4536: saveExpressionOrigin(exp.getOrigin(), buf, subIndent);
4537:
4538: if (!codeFlow) {
4539: // if static code structure is being saved, statements are
4540: // saved inside their parent expressions
4541: Iterator it = CodeStructure
4542: .getDefinedStatementsIterator(exp);
4543: if (it.hasNext()) {
4544: buf.append(subIndent);
4545: addElementOpen(buf, XML_CODE_STATEMENTS);
4546:
4547: String subSubIndent = subIndent + ONE_INDENT;
4548: do {
4549: saveCodeStatement((CodeStatement) it.next(),
4550: buf, subSubIndent);
4551: } while (it.hasNext());
4552:
4553: buf.append(subIndent);
4554: addElementClose(buf, XML_CODE_STATEMENTS);
4555: }
4556: }
4557:
4558: buf.append(indent);
4559: addElementClose(buf, XML_CODE_EXPRESSION);
4560: }
4561: }
4562:
4563: private void saveCodeVariable(CodeVariable var, StringBuffer buf,
4564: String indent) {
4565: buf.append(indent);
4566: if (getVariableSet().contains(var)) {
4567: addLeafElementOpenAttr(buf, XML_CODE_VARIABLE,
4568: new String[] { ATTR_VAR_NAME }, new String[] { var
4569: .getName() });
4570: } else {
4571: addLeafElementOpenAttr(buf, XML_CODE_VARIABLE,
4572: new String[] { ATTR_VAR_NAME, ATTR_VAR_TYPE,
4573: ATTR_VAR_DECLARED_TYPE }, new String[] {
4574: var.getName(),
4575: Integer.toString(var.getType()),
4576: var.getDeclaredType().getName() });
4577:
4578: getVariableSet().add(var);
4579: }
4580: }
4581:
4582: private void saveExpressionOrigin(CodeExpressionOrigin origin,
4583: StringBuffer buf, String indent) {
4584: buf.append(indent);
4585: addElementOpen(buf, XML_CODE_ORIGIN);
4586:
4587: String subIndent = indent + ONE_INDENT;
4588:
4589: CodeExpression parentExp = origin.getParentExpression();
4590: if (parentExp != null)
4591: saveCodeExpression(parentExp, buf, subIndent);
4592:
4593: Object metaObject = origin.getMetaObject();
4594: if (metaObject != null)
4595: saveOriginMetaObject(metaObject, buf, subIndent);
4596: else
4597: saveValue(origin.getValue(), origin.getType(), null, buf,
4598: subIndent);
4599:
4600: saveParameters(origin.getCreationParameters(), buf, subIndent);
4601:
4602: buf.append(indent);
4603: addElementClose(buf, XML_CODE_ORIGIN);
4604: }
4605:
4606: private void saveCodeStatement(CodeStatement statement,
4607: StringBuffer buf, String indent) {
4608: buf.append(indent);
4609: addElementOpen(buf, XML_CODE_STATEMENT);
4610:
4611: String subIndent = indent + ONE_INDENT;
4612:
4613: if (codeFlow) {
4614: // if code flow is being saved, also the parent expression of
4615: // the statement must be saved for it
4616: CodeExpression parentExp = statement.getParentExpression();
4617: if (parentExp != null)
4618: saveCodeExpression(parentExp, buf, subIndent);
4619: }
4620:
4621: Object metaObject = statement.getMetaObject();
4622: if (metaObject != null)
4623: saveStatementMetaObject(metaObject, buf, subIndent);
4624:
4625: saveParameters(statement.getStatementParameters(), buf,
4626: subIndent);
4627:
4628: buf.append(indent);
4629: addElementClose(buf, XML_CODE_STATEMENT);
4630: }
4631:
4632: private void saveOriginMetaObject(Object metaObject,
4633: StringBuffer buf, String indent) {
4634: if (metaObject instanceof Node.Property) {
4635: Node.Property property = (Node.Property) metaObject;
4636: Object value;
4637: try {
4638: value = property.getValue();
4639: } catch (Exception ex) { // should not happen
4640: org.openide.ErrorManager.getDefault().notify(
4641: org.openide.ErrorManager.INFORMATIONAL, ex);
4642: return;
4643: }
4644:
4645: PropertyEditor prEd = property instanceof FormProperty ? ((FormProperty) property)
4646: .getCurrentEditor()
4647: : property.getPropertyEditor();
4648: saveValue(value, property.getValueType(), prEd, buf, indent);
4649: return;
4650: }
4651:
4652: StringBuffer buf2 = new StringBuffer();
4653: String subIndent = indent + ONE_INDENT;
4654: String originType = null;
4655:
4656: if (metaObject instanceof Constructor) {
4657: Constructor ctor = (Constructor) metaObject;
4658: StringBuffer buf3 = new StringBuffer();
4659: Class[] paramTypes = ctor.getParameterTypes();
4660:
4661: for (int i = 0; i < paramTypes.length; i++) {
4662: buf3.append(paramTypes[i].getName());
4663: if (i + 1 < paramTypes.length)
4664: buf3.append(", "); // NOI18N
4665: }
4666:
4667: buf2.append(subIndent);
4668: addLeafElementOpenAttr(buf2, XML_CODE_CONSTRUCTOR,
4669: new String[] { ATTR_MEMBER_CLASS,
4670: ATTR_MEMBER_PARAMS }, new String[] {
4671: ctor.getDeclaringClass().getName(),
4672: buf3.toString() });
4673:
4674: originType = XML_CODE_CONSTRUCTOR;
4675: }
4676:
4677: // special code for handling meta component references
4678: else if (metaObject instanceof RADComponent) {
4679: RADComponent metacomp = (RADComponent) metaObject;
4680:
4681: buf2.append(subIndent);
4682: addLeafElementOpenAttr(buf2, XML_COMPONENT_REF,
4683: new String[] { ATTR_COMPONENT_NAME },
4684: new String[] { metacomp != formModel
4685: .getTopRADComponent() ? metacomp.getName()
4686: : "." }); // NOI18N
4687:
4688: originType = XML_COMPONENT_REF;
4689: }
4690:
4691: else if (metaObject instanceof Method) {
4692: saveMethod((Method) metaObject, buf2, subIndent);
4693: originType = XML_CODE_METHOD;
4694: }
4695:
4696: else if (metaObject instanceof Field) {
4697: saveField((Field) metaObject, buf2, subIndent);
4698: originType = XML_CODE_FIELD;
4699: }
4700:
4701: if (originType == null)
4702: return; // unknown origin
4703:
4704: buf.append(indent);
4705: addElementOpenAttr(buf, XML_ORIGIN_META_OBJECT,
4706: new String[] { ATTR_META_OBJECT_TYPE },
4707: new String[] { originType });
4708: buf.append(buf2);
4709: buf.append(indent);
4710: addElementClose(buf, XML_ORIGIN_META_OBJECT);
4711: }
4712:
4713: private void saveStatementMetaObject(Object metaObject,
4714: StringBuffer buf, String indent) {
4715: StringBuffer buf2 = new StringBuffer();
4716: String subIndent = indent + ONE_INDENT;
4717: String statementType = null;
4718:
4719: if (metaObject instanceof Method) {
4720: saveMethod((Method) metaObject, buf2, subIndent);
4721: statementType = XML_CODE_METHOD;
4722: } else if (metaObject instanceof Field) {
4723: saveField((Field) metaObject, buf2, subIndent);
4724: statementType = XML_CODE_FIELD;
4725: } else if (metaObject instanceof CodeExpression) { // variable assignment
4726: CodeExpression exp = (CodeExpression) metaObject;
4727: if (exp.getVariable() != null) {
4728: saveCodeExpression(exp, buf2, subIndent);
4729: statementType = XML_CODE_EXPRESSION;
4730: }
4731: }
4732: // [... variable declaration statement]
4733:
4734: if (statementType == null)
4735: return; // unknown statement
4736:
4737: buf.append(indent);
4738: addElementOpenAttr(buf, XML_STATEMENT_META_OBJECT,
4739: new String[] { ATTR_META_OBJECT_TYPE },
4740: new String[] { statementType });
4741: buf.append(buf2);
4742: buf.append(indent);
4743: addElementClose(buf, XML_STATEMENT_META_OBJECT);
4744: }
4745:
4746: private void saveParameters(CodeExpression[] parameters,
4747: StringBuffer buf, String indent) {
4748: if (parameters.length > 0) {
4749: buf.append(indent);
4750: addElementOpen(buf, XML_CODE_PARAMETERS);
4751:
4752: String subIndent = indent + ONE_INDENT;
4753: for (int i = 0; i < parameters.length; i++)
4754: saveCodeExpression(parameters[i], buf, subIndent);
4755:
4756: buf.append(indent);
4757: addElementClose(buf, XML_CODE_PARAMETERS);
4758: }
4759: }
4760:
4761: private static void saveMethod(Method method, StringBuffer buf,
4762: String indent) {
4763: StringBuffer buf2 = new StringBuffer();
4764: Class[] paramTypes = method.getParameterTypes();
4765:
4766: for (int i = 0; i < paramTypes.length; i++) {
4767: buf2.append(paramTypes[i].getName());
4768: if (i + 1 < paramTypes.length)
4769: buf2.append(", "); // NOI18N
4770: }
4771:
4772: buf.append(indent);
4773: addLeafElementOpenAttr(buf, XML_CODE_METHOD,
4774: new String[] { ATTR_MEMBER_NAME, ATTR_MEMBER_CLASS,
4775: ATTR_MEMBER_PARAMS }, new String[] {
4776: method.getName(),
4777: method.getDeclaringClass().getName(),
4778: buf2.toString() });
4779: }
4780:
4781: private static void saveField(Field field, StringBuffer buf,
4782: String indent) {
4783: buf.append(indent);
4784: addLeafElementOpenAttr(buf, XML_CODE_FIELD, new String[] {
4785: ATTR_MEMBER_NAME, ATTR_MEMBER_CLASS }, new String[] {
4786: field.getName(), field.getDeclaringClass().getName() });
4787: }
4788:
4789: // -----------
4790: // XML persistence of code structure - loading
4791:
4792: private CodeExpression loadCodeExpression(org.w3c.dom.Node node) {
4793: String expId = getAttribute(node, ATTR_EXPRESSION_ID);
4794: if (expId == null)
4795: return null; // missing ID error
4796:
4797: CodeExpression exp = (CodeExpression) getExpressionsMap().get(
4798: expId);
4799: if (exp != null)
4800: return exp;
4801:
4802: org.w3c.dom.NodeList childNodes = node.getChildNodes();
4803: if (childNodes == null)
4804: return null; // missing subnodes (expression content) error
4805:
4806: org.w3c.dom.Node variableNode = null;
4807: org.w3c.dom.Node originNode = null;
4808: org.w3c.dom.Node statementsNode = null;
4809:
4810: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
4811: org.w3c.dom.Node childNode = childNodes.item(i);
4812: if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
4813: continue; // ignore text nodes
4814:
4815: String nodeName = childNode.getNodeName();
4816:
4817: if (XML_CODE_VARIABLE.equals(nodeName))
4818: variableNode = childNode;
4819: else if (XML_CODE_ORIGIN.equals(nodeName))
4820: originNode = childNode;
4821: else if (!codeFlow && XML_CODE_STATEMENTS.equals(nodeName))
4822: statementsNode = childNode;
4823: }
4824:
4825: if (originNode == null)
4826: return null; // missing origin error
4827:
4828: CodeExpressionOrigin origin = loadExpressionOrigin(originNode);
4829: if (origin == null)
4830: return null; // origin loading error
4831:
4832: // special code for handling meta component references
4833: Object originMetaObject = origin.getMetaObject();
4834: if (originMetaObject instanceof RADComponent) {
4835: // use the expression from meta component
4836: exp = ((RADComponent) originMetaObject).getCodeExpression();
4837: } else { // create a new expression normally
4838: exp = getCodeStructure().createExpression(origin);
4839:
4840: CodeVariable var = variableNode != null ? loadCodeVariable(variableNode)
4841: : null;
4842: if (var != null)
4843: getCodeStructure().attachExpressionToVariable(exp, var);
4844: }
4845:
4846: getExpressionsMap().put(expId, exp);
4847:
4848: if (statementsNode != null) {
4849: childNodes = statementsNode.getChildNodes();
4850: if (childNodes != null) {
4851: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
4852: org.w3c.dom.Node childNode = childNodes.item(i);
4853:
4854: if (XML_CODE_STATEMENT.equals(childNode
4855: .getNodeName()))
4856: loadCodeStatement(childNode, exp);
4857: }
4858: }
4859: }
4860:
4861: return exp;
4862: }
4863:
4864: private CodeVariable loadCodeVariable(org.w3c.dom.Node node) {
4865: org.w3c.dom.NamedNodeMap attr = node.getAttributes();
4866: if (attr == null)
4867: return null; // no attributes error
4868:
4869: node = attr.getNamedItem(ATTR_VAR_NAME);
4870: if (node == null)
4871: return null; // missing variable name error
4872: String name = node.getNodeValue();
4873:
4874: CodeVariable var = getCodeStructure().getVariable(name);
4875: if (var != null)
4876: return var;
4877:
4878: node = attr.getNamedItem(ATTR_VAR_TYPE);
4879: if (node == null)
4880: return null; // missing variable type error
4881: int type = Integer.parseInt(node.getNodeValue());
4882:
4883: node = attr.getNamedItem(ATTR_VAR_DECLARED_TYPE);
4884: if (node == null)
4885: return null; // missing variable declared type error
4886: Class declaredType = null;
4887:
4888: try {
4889: declaredType = getClassFromString(node.getNodeValue());
4890: } catch (ClassNotFoundException ex) {
4891: org.openide.ErrorManager.getDefault().notify(
4892: org.openide.ErrorManager.INFORMATIONAL, ex);
4893: }
4894: if (declaredType == null)
4895: return null; // variable declared type loading error
4896:
4897: return getCodeStructure().createVariable(type, declaredType,
4898: name);
4899: }
4900:
4901: private CodeExpressionOrigin loadExpressionOrigin(
4902: org.w3c.dom.Node node) {
4903: org.w3c.dom.NodeList childNodes = node.getChildNodes();
4904: if (childNodes == null)
4905: return null; // missing subnodes (origin content) error
4906:
4907: org.w3c.dom.Node parentExpNode = null;
4908: org.w3c.dom.Node metaObjectNode = null;
4909: org.w3c.dom.Node valueNode = null;
4910: org.w3c.dom.Node parametersNode = null;
4911:
4912: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
4913: org.w3c.dom.Node childNode = childNodes.item(i);
4914: if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
4915: continue; // ignore text nodes
4916:
4917: String nodeName = childNode.getNodeName();
4918:
4919: if (XML_CODE_EXPRESSION.equals(nodeName))
4920: parentExpNode = childNode;
4921: else if (XML_ORIGIN_META_OBJECT.equals(nodeName))
4922: metaObjectNode = childNode;
4923: else if (XML_VALUE.equals(nodeName))
4924: valueNode = childNode;
4925: else if (XML_CODE_PARAMETERS.equals(nodeName))
4926: parametersNode = childNode;
4927: }
4928:
4929: if (metaObjectNode == null && valueNode == null)
4930: return null; // missing origin metaobject or value error
4931:
4932: CodeExpression parentExp;
4933: if (parentExpNode != null) {
4934: parentExp = loadCodeExpression(parentExpNode);
4935: if (parentExp == null)
4936: return null; // parent expression loading error
4937: } else
4938: parentExp = null; // origin without parent expression
4939:
4940: CodeExpression[] parameters = parametersNode != null ? loadParameters(parametersNode)
4941: : CodeStructure.EMPTY_PARAMS;
4942: if (parameters == null)
4943: return null; // error loading parameters
4944:
4945: CodeExpressionOrigin origin = null;
4946:
4947: if (metaObjectNode != null) {
4948: String metaObjectType = getAttribute(metaObjectNode,
4949: ATTR_META_OBJECT_TYPE);
4950: childNodes = metaObjectNode.getChildNodes();
4951: if (metaObjectType != null && childNodes != null) {
4952: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
4953: org.w3c.dom.Node childNode = childNodes.item(i);
4954:
4955: String nodeName = childNode.getNodeName();
4956: if (!metaObjectType.equals(nodeName))
4957: continue;
4958:
4959: if (XML_VALUE.equals(nodeName)) {
4960: valueNode = childNode;
4961: break;
4962: }
4963:
4964: if (XML_CODE_CONSTRUCTOR.equals(nodeName)) {
4965: org.w3c.dom.NamedNodeMap attr = childNode
4966: .getAttributes();
4967: if (attr == null)
4968: return null; // no attributes error
4969:
4970: node = attr.getNamedItem(ATTR_MEMBER_CLASS);
4971: if (node == null)
4972: return null; // missing constructor class error
4973:
4974: Class ctorClass;
4975: try {
4976: ctorClass = getClassFromString(node
4977: .getNodeValue());
4978: } catch (ClassNotFoundException ex) {
4979: org.openide.ErrorManager
4980: .getDefault()
4981: .notify(
4982: org.openide.ErrorManager.INFORMATIONAL,
4983: ex);
4984: return null; // constructor class loading error
4985: }
4986:
4987: node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
4988: if (node == null)
4989: return null; // missing constructor parameter types error
4990:
4991: Class[] paramTypes;
4992: StringTokenizer paramTokens = new StringTokenizer(
4993: node.getNodeValue(), ", "); // NOI18N
4994: List<Class> typeList = new ArrayList<Class>();
4995: try {
4996: while (paramTokens.hasMoreTokens()) {
4997: typeList
4998: .add(getClassFromString(paramTokens
4999: .nextToken()));
5000: }
5001: paramTypes = new Class[typeList.size()];
5002: typeList.toArray(paramTypes);
5003: } catch (ClassNotFoundException ex) {
5004: org.openide.ErrorManager
5005: .getDefault()
5006: .notify(
5007: org.openide.ErrorManager.INFORMATIONAL,
5008: ex);
5009: return null; // parameters classes loading error
5010: }
5011:
5012: Constructor ctor;
5013: try {
5014: ctor = ctorClass.getConstructor(paramTypes);
5015: } catch (NoSuchMethodException ex) {
5016: org.openide.ErrorManager
5017: .getDefault()
5018: .notify(
5019: org.openide.ErrorManager.INFORMATIONAL,
5020: ex);
5021: return null; // constructor not found error
5022: }
5023:
5024: origin = CodeStructure.createOrigin(ctor,
5025: parameters);
5026: break;
5027: }
5028:
5029: // special code for handling meta component references
5030: if (XML_COMPONENT_REF.equals(nodeName)) {
5031: String name = getAttribute(childNode,
5032: ATTR_COMPONENT_NAME);
5033: if (name == null)
5034: return null; // missing component name error
5035:
5036: RADComponent comp = name.equals(".") ? // NOI18N
5037: formModel.getTopRADComponent()
5038: : getComponentsMap().get(name);
5039: if (comp == null)
5040: return null; // no such component error
5041:
5042: origin = comp.getCodeExpression().getOrigin();
5043: break;
5044: }
5045:
5046: if (XML_CODE_METHOD.equals(nodeName)) {
5047: Method m = loadMethod(childNode);
5048: if (m == null)
5049: return null; // method loading error
5050:
5051: origin = CodeStructure.createOrigin(parentExp,
5052: m, parameters);
5053: break;
5054: }
5055:
5056: if (XML_CODE_FIELD.equals(nodeName)) {
5057: Field f = loadField(childNode);
5058: if (f == null)
5059: return null; // field loading error
5060:
5061: origin = CodeStructure.createOrigin(parentExp,
5062: f);
5063: break;
5064: }
5065: }
5066: }
5067: }
5068:
5069: if (origin == null) {
5070: if (valueNode == null)
5071: return null; // origin metaobject loading error
5072:
5073: String typeStr = getAttribute(valueNode, ATTR_PROPERTY_TYPE);
5074: if (typeStr == null)
5075: return null; // missing value type error
5076:
5077: Object editorOrValue = getPropertyEditorOrValue(valueNode);
5078: if (editorOrValue == NO_VALUE)
5079: return null; // value loading error
5080:
5081: Class valueType;
5082: try {
5083: valueType = getClassFromString(typeStr);
5084: } catch (Exception ex) { // does not happen
5085: return null; // value loading error
5086: }
5087:
5088: origin = editorOrValue instanceof PropertyEditor ? FormCodeSupport
5089: .createOrigin(valueType,
5090: (PropertyEditor) editorOrValue)
5091: : CodeStructure.createOrigin(valueType,
5092: editorOrValue,
5093: editorOrValue != null ? editorOrValue
5094: .toString() : "null"); // NOI18N
5095: }
5096:
5097: return origin;
5098: }
5099:
5100: private CodeStatement loadCodeStatement(org.w3c.dom.Node node,
5101: CodeExpression parentExp) {
5102: org.w3c.dom.NodeList childNodes = node.getChildNodes();
5103: if (childNodes == null)
5104: return null; // missing subnodes (statement content) error
5105:
5106: org.w3c.dom.Node parentExpNode = null;
5107: org.w3c.dom.Node metaObjectNode = null;
5108: org.w3c.dom.Node parametersNode = null;
5109:
5110: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
5111: org.w3c.dom.Node childNode = childNodes.item(i);
5112: if (childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
5113: continue; // ignore text nodes
5114:
5115: String nodeName = childNode.getNodeName();
5116:
5117: if (XML_CODE_EXPRESSION.equals(nodeName)) {
5118: if (parentExp == null)
5119: parentExpNode = childNode;
5120: } else if (XML_STATEMENT_META_OBJECT.equals(nodeName))
5121: metaObjectNode = childNode;
5122: else if (XML_CODE_PARAMETERS.equals(nodeName))
5123: parametersNode = childNode;
5124: }
5125:
5126: if (metaObjectNode == null)
5127: return null; // missing statement metaobject error
5128:
5129: if (parentExpNode != null) {
5130: parentExp = loadCodeExpression(parentExpNode);
5131: if (parentExp == null)
5132: return null; // parent expression loading error
5133: }
5134:
5135: CodeExpression[] parameters = parametersNode != null ? loadParameters(parametersNode)
5136: : CodeStructure.EMPTY_PARAMS;
5137: if (parameters == null)
5138: return null; // error loading parameters
5139:
5140: CodeStatement statement = null;
5141:
5142: String metaObjectType = getAttribute(metaObjectNode,
5143: ATTR_META_OBJECT_TYPE);
5144: childNodes = metaObjectNode.getChildNodes();
5145: if (metaObjectType != null && childNodes != null) {
5146: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
5147: org.w3c.dom.Node childNode = childNodes.item(i);
5148:
5149: String nodeName = childNode.getNodeName();
5150: if (!metaObjectType.equals(nodeName))
5151: continue;
5152:
5153: if (XML_CODE_METHOD.equals(nodeName)) {
5154: Method m = loadMethod(childNode);
5155: if (m == null)
5156: return null; // method loading error
5157:
5158: statement = CodeStructure.createStatement(
5159: parentExp, m, parameters);
5160: break;
5161: }
5162:
5163: if (XML_CODE_FIELD.equals(nodeName)) {
5164: Field f = loadField(childNode);
5165: if (f == null)
5166: return null; // field loading error
5167:
5168: if (parameters.length != 1)
5169: return null; // inconsistent data error
5170:
5171: statement = CodeStructure.createStatement(
5172: parentExp, f, parameters[0]);
5173: break;
5174: }
5175:
5176: if (XML_CODE_EXPRESSION.equals(nodeName)) {
5177: // variable assignment
5178: CodeExpression exp = loadCodeExpression(childNode);
5179: if (exp != parentExp)
5180: return null; // inconsistent data error
5181:
5182: CodeVariable var = exp.getVariable();
5183: if (var == null)
5184: return null; // non-existing variable error
5185:
5186: statement = var.getAssignment(exp);
5187: break;
5188: }
5189: }
5190: }
5191:
5192: return statement;
5193: }
5194:
5195: private CodeExpression[] loadParameters(org.w3c.dom.Node node) {
5196: List<CodeExpression> paramList = new ArrayList<CodeExpression>();
5197: org.w3c.dom.NodeList childNodes = node.getChildNodes();
5198: if (childNodes != null) {
5199: for (int i = 0, n = childNodes.getLength(); i < n; i++) {
5200: org.w3c.dom.Node childNode = childNodes.item(i);
5201:
5202: if (XML_CODE_EXPRESSION.equals(childNode.getNodeName())) {
5203: CodeExpression exp = loadCodeExpression(childNode);
5204: if (exp == null)
5205: return null; // parameter loading error
5206:
5207: paramList.add(exp);
5208: }
5209: }
5210:
5211: CodeExpression[] params = new CodeExpression[paramList
5212: .size()];
5213: paramList.toArray(params);
5214: return params;
5215: } else
5216: return CodeStructure.EMPTY_PARAMS;
5217: }
5218:
5219: private/*static */Method loadMethod(org.w3c.dom.Node node) {
5220: org.w3c.dom.NamedNodeMap attr = node.getAttributes();
5221: if (attr == null)
5222: return null; // no attributes error
5223:
5224: node = attr.getNamedItem(ATTR_MEMBER_NAME);
5225: if (node == null)
5226: return null; // missing method name error
5227: String name = node.getNodeValue();
5228:
5229: node = attr.getNamedItem(ATTR_MEMBER_CLASS);
5230: if (node == null)
5231: return null; // missing method class error
5232:
5233: Class methodClass;
5234: try {
5235: methodClass = getClassFromString(node.getNodeValue());
5236: } catch (ClassNotFoundException ex) {
5237: org.openide.ErrorManager.getDefault().notify(
5238: org.openide.ErrorManager.INFORMATIONAL, ex);
5239: return null; // method class loading error
5240: }
5241:
5242: node = attr.getNamedItem(ATTR_MEMBER_PARAMS);
5243: if (node == null)
5244: return null; // missing method parameter types error
5245:
5246: Class[] paramTypes;
5247: StringTokenizer paramTokens = new StringTokenizer(node
5248: .getNodeValue(), ", "); // NOI18N
5249: List<Class> typeList = new ArrayList<Class>();
5250: try {
5251: while (paramTokens.hasMoreTokens()) {
5252: typeList
5253: .add(getClassFromString(paramTokens.nextToken()));
5254: }
5255: paramTypes = new Class[typeList.size()];
5256: typeList.toArray(paramTypes);
5257: } catch (ClassNotFoundException ex) {
5258: org.openide.ErrorManager.getDefault().notify(
5259: org.openide.ErrorManager.INFORMATIONAL, ex);
5260: return null; // parameters classes loading error
5261: }
5262:
5263: try {
5264: return methodClass.getMethod(name, paramTypes);
5265: } catch (NoSuchMethodException ex) {
5266: org.openide.ErrorManager.getDefault().notify(
5267: org.openide.ErrorManager.INFORMATIONAL, ex);
5268: return null; // method not found error
5269: }
5270: }
5271:
5272: private/*static */Field loadField(org.w3c.dom.Node node) {
5273: org.w3c.dom.NamedNodeMap attr = node.getAttributes();
5274: if (attr == null)
5275: return null; // no attributes error
5276:
5277: node = attr.getNamedItem(ATTR_MEMBER_NAME);
5278: if (node == null)
5279: return null; // missing field name error
5280: String name = node.getNodeValue();
5281:
5282: node = attr.getNamedItem(ATTR_MEMBER_CLASS);
5283: if (node == null)
5284: return null; // missing field class error
5285:
5286: Class fieldClass;
5287: try {
5288: fieldClass = getClassFromString(node.getNodeValue());
5289: } catch (ClassNotFoundException ex) {
5290: org.openide.ErrorManager.getDefault().notify(
5291: org.openide.ErrorManager.INFORMATIONAL, ex);
5292: return null; // field class loading error
5293: }
5294:
5295: try {
5296: return fieldClass.getField(name);
5297: } catch (NoSuchFieldException ex) {
5298: org.openide.ErrorManager.getDefault().notify(
5299: org.openide.ErrorManager.INFORMATIONAL, ex);
5300: return null; // field not found error
5301: }
5302: }
5303:
5304: // -------
5305:
5306: private CodeStructure getCodeStructure() {
5307: return formModel.getCodeStructure();
5308: }
5309:
5310: // -------
5311:
5312: private Map<Object/*String or CodeExpression*/, Object/*String or CodeExpression*/> getExpressionsMap() {
5313: if (expressions == null)
5314: expressions = new HashMap<Object, Object>(100);
5315: return expressions;
5316: }
5317:
5318: private Set<CodeVariable> getVariableSet() {
5319: if (savedVariables == null)
5320: savedVariables = new HashSet<CodeVariable>(50);
5321: return savedVariables;
5322: }
5323:
5324: private Map<String, RADComponent> getComponentsMap() {
5325: if (loadedComponents == null)
5326: loadedComponents = new HashMap<String, RADComponent>(50);
5327: return loadedComponents;
5328: }
5329:
5330: // -----------------
5331: // Value encoding and decoding methods
5332:
5333: private Object getPropertyEditorOrValue(org.w3c.dom.Node node) {
5334: org.w3c.dom.NamedNodeMap attrs = node.getAttributes();
5335: if (attrs == null)
5336: return NO_VALUE; // no attributes, ignore property
5337:
5338: org.w3c.dom.Node typeNode = attrs
5339: .getNamedItem(ATTR_PROPERTY_TYPE);
5340: org.w3c.dom.Node editorNode = attrs
5341: .getNamedItem(ATTR_PROPERTY_EDITOR);
5342: org.w3c.dom.Node valueNode = attrs
5343: .getNamedItem(ATTR_PROPERTY_VALUE);
5344: org.w3c.dom.Node resourceNode = attrs
5345: .getNamedItem(ATTR_PROPERTY_RES_KEY);
5346:
5347: // get the type of stored property value
5348: if (typeNode == null) {
5349: PersistenceException ex = new PersistenceException(
5350: "Missing property type"); // NOI18N
5351: String msg = createLoadingErrorMessage(FormUtils
5352: .getBundleString("MSG_ERR_MissingPropertyType"), // NOI18N
5353: node);
5354: ErrorManager.getDefault().annotate(ex, ErrorManager.ERROR,
5355: null, msg, null, null);
5356: nonfatalErrors.add(ex);
5357: return NO_VALUE;
5358: }
5359:
5360: Class propertyType = null;
5361: Throwable t = null;
5362: try {
5363: propertyType = getClassFromString(typeNode.getNodeValue());
5364: } catch (Exception ex) {
5365: t = ex;
5366: } catch (LinkageError ex) {
5367: t = ex;
5368: }
5369: if (t != null) {
5370: String msg = createLoadingErrorMessage(FormUtils
5371: .getFormattedBundleString(
5372: "FMT_ERR_CannotLoadClass2", // NOI18N
5373: new Object[] { typeNode.getNodeValue() }),
5374: node);
5375: ErrorManager.getDefault().annotate(t, msg);
5376: nonfatalErrors.add(t);
5377: return NO_VALUE;
5378: }
5379:
5380: // load the property editor class and create an instance of it
5381: PropertyEditor prEd = null;
5382: if (editorNode != null) {
5383: Class editorClass = null;
5384: try {
5385: editorClass = PersistenceObjectRegistry.loadClass(
5386: editorNode.getNodeValue(), formFile);
5387: } catch (Exception ex) {
5388: t = ex;
5389: } catch (LinkageError ex) {
5390: t = ex;
5391: }
5392: if (t != null) {
5393: String msg = createLoadingErrorMessage(FormUtils
5394: .getFormattedBundleString(
5395: "FMT_ERR_CannotLoadClass3", // NOI18N
5396: new Object[] { editorNode
5397: .getNodeValue() }), node);
5398: ErrorManager.getDefault().annotate(t, msg);
5399: nonfatalErrors.add(t);
5400: return NO_VALUE;
5401: }
5402:
5403: try {
5404: prEd = createPropertyEditor(editorClass, propertyType,
5405: null);
5406: } catch (Exception ex) {
5407: t = ex;
5408: } catch (LinkageError ex) {
5409: t = ex;
5410: }
5411: if (t != null) {
5412: String msg = createLoadingErrorMessage(FormUtils
5413: .getFormattedBundleString(
5414: "FMT_ERR_CannotCreateInstance2", // NOI18N
5415: new Object[] { editorNode
5416: .getNodeValue() }), node);
5417: ErrorManager.getDefault().annotate(t, msg);
5418: nonfatalErrors.add(t);
5419: return NO_VALUE;
5420: }
5421: }
5422:
5423: // load the property value
5424: Object value = NO_VALUE;
5425: if (valueNode != null) { // it is a primitive value
5426: try {
5427: value = decodePrimitiveValue(valueNode.getNodeValue(),
5428: propertyType);
5429: if (prEd != null)
5430: prEd.setValue(value);
5431: } catch (IllegalArgumentException ex) {
5432: String msg = createLoadingErrorMessage(FormUtils
5433: .getFormattedBundleString(
5434: "FMT_ERR_CannotDecodePrimitive", // NOI18N
5435: new Object[] {
5436: valueNode.getNodeValue(),
5437: propertyType.getName() }), node);
5438: ErrorManager.getDefault().annotate(ex, msg);
5439: nonfatalErrors.add(ex);
5440: return NO_VALUE;
5441: }
5442: } else if (resourceNode != null) {
5443: value = ResourceSupport.findResource(formModel,
5444: resourceNode.getNodeValue(), propertyType);
5445: return value != null ? value : NO_VALUE;
5446: } else { // the value is serialized or saved by XMLPropertyEditor
5447: org.w3c.dom.NodeList children = node.getChildNodes();
5448: int n = children != null ? children.getLength() : 0;
5449: if (n > 0) {
5450: try {
5451: boolean serialized = false;
5452: // first try if the value is serialized
5453: for (int i = 0; i < n; i++) {
5454: if (XML_SERIALIZED_PROPERTY_VALUE
5455: .equals(children.item(i).getNodeName())) { // here is the value serialized in XML
5456: String serValue = getAttribute(children
5457: .item(i), ATTR_PROPERTY_VALUE);
5458: if (serValue != null) {
5459: serialized = true;
5460: value = decodeValue(serValue);
5461: prEd = null;
5462: }
5463: break;
5464: }
5465: }
5466:
5467: if (!serialized) {
5468: if (prEd instanceof XMLPropertyEditor) {
5469: // the value is saved by XMLPropertyEditor
5470: for (int i = 0; i < n; i++) {
5471: if (children.item(i).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { // here is the element of stored value
5472: ((XMLPropertyEditor) prEd)
5473: .readFromXML(children
5474: .item(i));
5475: value = prEd.getValue();
5476: break;
5477: }
5478: }
5479: }
5480: }
5481: } catch (Exception ex) {
5482: t = ex;
5483: } catch (LinkageError ex) {
5484: t = ex;
5485: }
5486: if (t != null) {
5487: String msg = createLoadingErrorMessage(
5488: FormUtils
5489: .getBundleString("MSG_ERR_CannotReadPropertyValue"), // NOI18N
5490: node);
5491: ErrorManager.getDefault().annotate(t, msg);
5492: nonfatalErrors.add(t);
5493: return NO_VALUE;
5494: }
5495: }
5496:
5497: if (value == NO_VALUE) { // the value is missing
5498: PersistenceException ex = new PersistenceException(
5499: "Missing property value"); // NOI18N
5500: String msg = createLoadingErrorMessage(
5501: FormUtils
5502: .getBundleString("MSG_ERR_MissingPropertyValue"), // NOI18N
5503: node);
5504: ErrorManager.getDefault().annotate(ex,
5505: ErrorManager.ERROR, null, msg, null, null);
5506: nonfatalErrors.add(ex);
5507: return NO_VALUE;
5508: }
5509: }
5510:
5511: if (prEd != null)
5512: return prEd;
5513:
5514: return value;
5515: }
5516:
5517: private/*static */Class getClassFromString(String type)
5518: throws ClassNotFoundException {
5519: if ("int".equals(type)) // NOI18N
5520: return Integer.TYPE;
5521: else if ("short".equals(type)) // NOI18N
5522: return Short.TYPE;
5523: else if ("byte".equals(type)) // NOI18N
5524: return Byte.TYPE;
5525: else if ("long".equals(type)) // NOI18N
5526: return Long.TYPE;
5527: else if ("float".equals(type)) // NOI18N
5528: return Float.TYPE;
5529: else if ("double".equals(type)) // NOI18N
5530: return Double.TYPE;
5531: else if ("boolean".equals(type)) // NOI18N
5532: return Boolean.TYPE;
5533: else if ("char".equals(type)) // NOI18N
5534: return Character.TYPE;
5535: else {
5536: if (type.startsWith("[")) { // NOI18N
5537: // load array element class first to avoid failure
5538: for (int i = 1, n = type.length(); i < n; i++) {
5539: char c = type.charAt(i);
5540: if (c == 'L' && type.endsWith(";")) { // NOI18N
5541: String clsName = type.substring(i + 1, n - 1);
5542: PersistenceObjectRegistry.loadClass(clsName,
5543: formFile);
5544: break;
5545: } else if (c != '[')
5546: break;
5547: }
5548: }
5549:
5550: return PersistenceObjectRegistry.loadClass(type, formFile);
5551: }
5552: }
5553:
5554: /** Decodes a primitive value of given type from the specified String.
5555: * @return decoded value
5556: * @exception IllegalArgumentException thrown if specified object is not
5557: * of supported type
5558: */
5559: private Object decodePrimitiveValue(String encoded, Class type) {
5560: if ("null".equals(encoded)) // NOI18N
5561: return null;
5562:
5563: if (Integer.class.isAssignableFrom(type)
5564: || Integer.TYPE.equals(type))
5565: return Integer.valueOf(encoded);
5566: if (Short.class.isAssignableFrom(type)
5567: || Short.TYPE.equals(type))
5568: return Short.valueOf(encoded);
5569: if (Byte.class.isAssignableFrom(type) || Byte.TYPE.equals(type))
5570: return Byte.valueOf(encoded);
5571: if (Long.class.isAssignableFrom(type) || Long.TYPE.equals(type))
5572: return Long.valueOf(encoded);
5573: if (Float.class.isAssignableFrom(type)
5574: || Float.TYPE.equals(type))
5575: return Float.valueOf(encoded);
5576: if (Double.class.isAssignableFrom(type)
5577: || Double.TYPE.equals(type))
5578: return Double.valueOf(encoded);
5579: if (Boolean.class.isAssignableFrom(type)
5580: || Boolean.TYPE.equals(type))
5581: return Boolean.valueOf(encoded);
5582: if (Character.class.isAssignableFrom(type)
5583: || Character.TYPE.equals(type))
5584: return new Character(encoded.charAt(0));
5585: if (String.class.isAssignableFrom(type))
5586: return encoded;
5587:
5588: if (Class.class.isAssignableFrom(type)) {
5589: Throwable t;
5590: try {
5591: return PersistenceObjectRegistry.loadClass(encoded,
5592: formFile);
5593: } catch (Exception ex) {
5594: t = ex;
5595: } catch (LinkageError ex) {
5596: t = ex;
5597: }
5598: IllegalArgumentException ex = new IllegalArgumentException(
5599: "Cannot load class: " + encoded); // NOI18N
5600: ErrorManager.getDefault().annotate(ex, t);
5601: throw ex;
5602: }
5603:
5604: throw new IllegalArgumentException();
5605: }
5606:
5607: /** Encodes specified value into a String. Supported types are: <UL>
5608: * <LI> Class
5609: * <LI> String
5610: * <LI> Integer, Short, Byte, Long, Float, Double, Boolean, Character </UL>
5611: *
5612: * @param value value to encode.
5613: * @return String containing encoded value or null if specified object is not of supported type
5614: */
5615: public static String encodePrimitiveValue(Object value) {
5616: if (value instanceof Integer || value instanceof Short
5617: || value instanceof Byte || value instanceof Long
5618: || value instanceof Float || value instanceof Double
5619: || value instanceof Boolean
5620: || value instanceof Character)
5621: return value.toString();
5622:
5623: if (value instanceof String) {
5624: try {
5625: XMLUtil.toAttributeValue((String) value);
5626: return (String) value;
5627: } catch (CharConversionException ex) {
5628: // can't be stored in XML document, needs to be encoded as bytes
5629: return null;
5630: }
5631: }
5632:
5633: if (value instanceof Class)
5634: return ((Class) value).getName();
5635:
5636: if (value == null)
5637: return "null"; // NOI18N
5638:
5639: return null; // is not a primitive type
5640: }
5641:
5642: /** Decodes a value from String containing textual representation of
5643: * serialized stream.
5644: *
5645: * @param strValue value to decode.
5646: * @return decoded object
5647: * @exception IOException thrown if an error occurres during deserializing
5648: * the object
5649: * @throws java.lang.ClassNotFoundException if the corresponding class cannot be loaded.
5650: */
5651: public Object decodeValue(String strValue) throws IOException,
5652: ClassNotFoundException {
5653: if (strValue == null || strValue.length() == 0)
5654: return null;
5655:
5656: char[] bisChars = strValue.toCharArray();
5657: byte[] bytes = new byte[bisChars.length];
5658: StringBuffer singleNum = new StringBuffer();
5659: int count = 0;
5660: for (int i = 0; i < bisChars.length; i++) {
5661: if (',' == bisChars[i]) {
5662: bytes[count++] = Byte.parseByte(singleNum.toString());
5663: singleNum = new StringBuffer();
5664: } else {
5665: singleNum.append(bisChars[i]);
5666: }
5667: }
5668:
5669: // add the last byte
5670: bytes[count++] = Byte.parseByte(singleNum.toString());
5671: ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 0,
5672: count);
5673: return new OIS(bis).readObject();
5674: }
5675:
5676: /** Encodes specified value to a String containing textual representation of serialized stream.
5677: *
5678: * @param value value to encode.
5679: * @return String containing textual representation of the serialized object
5680: * @throws java.io.IOException when some problem occurs during encoding.
5681: */
5682: public static String encodeValue(Object value) throws IOException {
5683: ByteArrayOutputStream bos = new ByteArrayOutputStream();
5684: ObjectOutputStream oos = new ObjectOutputStream(bos);
5685:
5686: oos.writeObject(value);
5687: oos.close();
5688:
5689: byte[] bosBytes = bos.toByteArray();
5690: StringBuffer buf = new StringBuffer(bosBytes.length * 4);
5691: for (int i = 0; i < bosBytes.length; i++) {
5692: if (i + 1 < bosBytes.length)
5693: buf.append(bosBytes[i] + ","); // NOI18N
5694: else
5695: buf.append("" + bosBytes[i]); // NOI18N
5696: }
5697: return buf.toString();
5698: }
5699:
5700: // ObjectInputStream subclass for reading serialized property values
5701: private class OIS extends ObjectInputStream {
5702: public OIS(InputStream is) throws IOException {
5703: super (is);
5704: }
5705:
5706: @Override
5707: protected Class resolveClass(ObjectStreamClass streamCls)
5708: throws IOException, ClassNotFoundException {
5709: String name = streamCls.getName();
5710: if (name.startsWith("[")) { // NOI18N
5711: // load array element class first to avoid failure
5712: for (int i = 1, n = name.length(); i < n; i++) {
5713: char c = name.charAt(i);
5714: if (c == 'L' && name.endsWith(";")) { // NOI18N
5715: String clsName = name.substring(i + 1, n - 1);
5716: PersistenceObjectRegistry.loadClass(clsName,
5717: formFile);
5718: break;
5719: } else if (c != '[')
5720: return super .resolveClass(streamCls);
5721: }
5722: }
5723: return PersistenceObjectRegistry.loadClass(name, formFile);
5724: }
5725: }
5726:
5727: // --------------------------------------------------------------------------------------
5728: // Utility formatting methods
5729:
5730: private static void addElementOpen(StringBuffer buf,
5731: String elementName) {
5732: buf.append("<"); // NOI18N
5733: buf.append(elementName);
5734: buf.append(">\n"); // NOI18N
5735: }
5736:
5737: private static void addElementOpenAttr(StringBuffer buf,
5738: String elementName, String[] attrNames, String[] attrValues) {
5739: buf.append("<"); // NOI18N
5740: buf.append(elementName);
5741: for (int i = 0; i < attrNames.length; i++) {
5742: if (attrValues[i] == null)
5743: continue;
5744: buf.append(" "); // NOI18N
5745: buf.append(attrNames[i]);
5746: buf.append("=\""); // NOI18N
5747: buf.append(encodeToProperXML(attrValues[i]));
5748: buf.append("\""); // NOI18N
5749: }
5750: buf.append(">\n"); // NOI18N
5751: }
5752:
5753: private static void addLeafElementOpenAttr(StringBuffer buf,
5754: String elementName, String[] attrNames, String[] attrValues) {
5755: buf.append("<"); // NOI18N
5756: buf.append(elementName);
5757: for (int i = 0; i < attrNames.length; i++) {
5758: if (attrValues[i] == null)
5759: continue;
5760: buf.append(" "); // NOI18N
5761: buf.append(attrNames[i]);
5762: buf.append("=\""); // NOI18N
5763: buf.append(encodeToProperXML(attrValues[i]));
5764: buf.append("\""); // NOI18N
5765: }
5766: buf.append("/>\n"); // NOI18N
5767: }
5768:
5769: private static void addElementClose(StringBuffer buf,
5770: String elementName) {
5771: buf.append("</"); // NOI18N
5772: buf.append(elementName);
5773: buf.append(">\n"); // NOI18N
5774: }
5775:
5776: private void saveNodeIntoText(StringBuffer buf,
5777: org.w3c.dom.Node valueNode, String indent) {
5778: buf.append(indent);
5779: buf.append("<"); // NOI18N
5780: buf.append(valueNode.getNodeName());
5781:
5782: org.w3c.dom.NamedNodeMap attributes = valueNode.getAttributes();
5783:
5784: if (attributes != null) {
5785: List<org.w3c.dom.Node> attribList = new ArrayList<org.w3c.dom.Node>(
5786: attributes.getLength());
5787: for (int i = 0; i < attributes.getLength(); i++) {
5788: attribList.add(attributes.item(i));
5789: }
5790:
5791: // sort the attributes by attribute name
5792: // probably not necessary, but there is no guarantee that
5793: // the order of attributes will remain the same in DOM
5794: Collections.sort(attribList,
5795: new Comparator<org.w3c.dom.Node>() {
5796: public int compare(org.w3c.dom.Node n1,
5797: org.w3c.dom.Node n2) {
5798: return n1.getNodeName().compareTo(
5799: n2.getNodeName());
5800: }
5801: });
5802:
5803: for (Iterator it = attribList.iterator(); it.hasNext();) {
5804: org.w3c.dom.Node attrNode = (org.w3c.dom.Node) it
5805: .next();
5806: String attrName = attrNode.getNodeName();
5807: String attrValue = attrNode.getNodeValue();
5808:
5809: buf.append(" "); // NOI18N
5810: buf.append(encodeToProperXML(attrName));
5811: buf.append("=\""); // NOI18N
5812: buf.append(encodeToProperXML(attrValue));
5813: buf.append("\""); // NOI18N
5814: }
5815: }
5816: // [PENDING - CNODES, TEXT NODES, ...]
5817:
5818: org.w3c.dom.NodeList children = valueNode.getChildNodes();
5819: if ((children == null) || (children.getLength() == 0)) {
5820: buf.append("/>\n"); // NOI18N
5821: } else {
5822: buf.append(">\n"); // NOI18N
5823: for (int i = 0; i < children.getLength(); i++) {
5824: if (children.item(i).getNodeType() == org.w3c.dom.Node.TEXT_NODE)
5825: continue; // ignore text nodes
5826: saveNodeIntoText(buf, children.item(i), indent
5827: + ONE_INDENT);
5828: }
5829: buf.append(indent);
5830: buf.append("</"); // NOI18N
5831: buf.append(encodeToProperXML(valueNode.getNodeName()));
5832: buf.append(">\n"); // NOI18N
5833: }
5834: }
5835:
5836: // --------------------------------------------------------------------------------------
5837: // Utility DOM access methods
5838:
5839: private static String encodeToProperXML(String text) {
5840: if (text == null)
5841: return ""; // NOI18N
5842:
5843: StringBuffer sb = new StringBuffer(text.length());
5844: for (int i = 0; i < text.length(); i++) {
5845: char c = text.charAt(i);
5846: if (c >= 0x0020 && c <= 0x007f) {
5847: switch (c) {
5848: case '&':
5849: sb.append("&");
5850: break; // NOI18N
5851: case '<':
5852: sb.append("<");
5853: break; // NOI18N
5854: case '>':
5855: sb.append(">");
5856: break; // NOI18N
5857: case '\'':
5858: sb.append("'");
5859: break; // NOI18N
5860: case '\"':
5861: sb.append(""");
5862: break; // NOI18N
5863: default:
5864: sb.append(c);
5865: break;
5866: }
5867: } else {
5868: sb.append("&#x" + Integer.toHexString(c) + ";"); // NOI18N
5869: }
5870: }
5871:
5872: return sb.toString();
5873: }
5874:
5875: /** Finds first subnode of given node with specified name.
5876: * @param node the node whose subnode we are looking for
5877: * @param name requested name of the subnode
5878: * @return the found subnode or null if no such subnode exists
5879: */
5880: private org.w3c.dom.Node findSubNode(org.w3c.dom.Node node,
5881: String name) {
5882: org.w3c.dom.NodeList children = node.getChildNodes();
5883: if (children != null) {
5884: for (int i = 0; i < children.getLength(); i++) {
5885: if (children.item(i).getNodeType() == org.w3c.dom.Node.TEXT_NODE)
5886: continue; // ignore text nodes
5887: if (name.equals(children.item(i).getNodeName())) {
5888: return children.item(i);
5889: }
5890: }
5891: }
5892: return null;
5893: }
5894:
5895: /** Finds all subnodes of given node with specified name.
5896: * @param node the node whose subnode we are looking for
5897: * @param name requested name of the subnode
5898: * @return array of the found subnodes
5899: */
5900: private org.w3c.dom.Node[] findSubNodes(org.w3c.dom.Node node,
5901: String name) {
5902: org.w3c.dom.NodeList children = node.getChildNodes();
5903: if (children == null)
5904: return new org.w3c.dom.Node[0];
5905:
5906: List<org.w3c.dom.Node> nodeList = new ArrayList<org.w3c.dom.Node>();
5907:
5908: for (int i = 0, n = children.getLength(); i < n; i++) {
5909: org.w3c.dom.Node subnode = children.item(i);
5910: if (subnode.getNodeType() == org.w3c.dom.Node.TEXT_NODE)
5911: continue; // ignore text nodes
5912: if (name.equals(subnode.getNodeName()))
5913: nodeList.add(subnode);
5914: }
5915:
5916: org.w3c.dom.Node[] nodes = new org.w3c.dom.Node[nodeList.size()];
5917: nodeList.toArray(nodes);
5918: return nodes;
5919: }
5920:
5921: /** Utility method to obtain given attribute value from specified Node.
5922: * @return attribute name or null if the attribute is not present
5923: */
5924: private static String getAttribute(org.w3c.dom.Node node,
5925: String attrName) {
5926: org.w3c.dom.Node valueNode = node.getAttributes().getNamedItem(
5927: attrName);
5928: return valueNode != null ? valueNode.getNodeValue() : null;
5929: }
5930:
5931: // --------------
5932:
5933: private String createLoadingErrorMessage(String errMsg,
5934: org.w3c.dom.Node node) {
5935: String nodeName = node.getNodeName();
5936:
5937: List<String> path = new ArrayList<String>();
5938: boolean leaf = true;
5939: boolean layout = false;
5940: boolean layoutConstr = false;
5941: boolean inOthers = false;
5942:
5943: do {
5944: String name = node.getNodeName();
5945: if (XML_COMPONENT.equals(name)
5946: || XML_CONTAINER.equals(name)
5947: || XML_MENU_COMPONENT.equals(name)
5948: || XML_MENU_CONTAINER.equals(name)
5949: || XML_PROPERTY.equals(name)
5950: || XML_SYNTHETIC_PROPERTY.equals(name)
5951: || XML_AUX_VALUE.equals(name)) {
5952: name = getAttribute(node, "name"); // NOI18N
5953: if (name != null || !leaf)
5954: path.add(name);
5955: if (name != null)
5956: leaf = false;
5957: } else if (XML_NON_VISUAL_COMPONENTS.equals(name)) {
5958: inOthers = true;
5959: } else if (XML_LAYOUT.equals(name)
5960: || XML_LAYOUT_CODE.equals(name)) {
5961: path.add(FormUtils.getBundleString("CTL_PathLayout")); // NOI18N
5962: layout = true;
5963: } else if (XML_CONSTRAINTS.equals(name)) {
5964: path.add(FormUtils
5965: .getBundleString("CTL_PathLayoutConstraints")); // NOI18N
5966: layoutConstr = true;
5967: }
5968:
5969: node = node.getParentNode();
5970: } while (node != null);
5971:
5972: if (inOthers)
5973: path.add(FormUtils
5974: .getBundleString("CTL_NonVisualComponents")); // NOI18N
5975: else if (formModel.getFormBaseClass() != null)
5976: path.add(FormUtils.getFormattedBundleString(
5977: "FMT_UnnamedComponentNodeName", // NOI18N
5978: new Object[] { Utilities
5979: .getShortClassName(formModel
5980: .getFormBaseClass()) }));
5981:
5982: if (path.isEmpty())
5983: return errMsg;
5984:
5985: String link = null;
5986: StringBuffer pathBuf = new StringBuffer();
5987: for (int i = path.size() - 1; i >= 0; i--) {
5988: pathBuf.append(path.get(i));
5989: if (i > 0) {
5990: if (link == null)
5991: link = FormUtils.getBundleString("CTL_PathLink"); // NOI18N
5992: pathBuf.append(link);
5993: }
5994: }
5995:
5996: if (errMsg == null)
5997: return pathBuf.toString();
5998:
5999: boolean property = XML_PROPERTY.equals(nodeName)
6000: || XML_SYNTHETIC_PROPERTY.equals(nodeName)
6001: || XML_AUX_VALUE.equals(nodeName);
6002:
6003: String format;
6004: if (!layoutConstr)
6005: if (!layout)
6006: format = property ? "FMT_ERR_LoadingComponentProperty" : // NOI18N
6007: "FMT_ERR_LoadingComponent"; // NOI18N
6008: else
6009: format = property ? "FMT_ERR_LoadingLayoutProperty" : // NOI18N
6010: "FMT_ERR_LoadingLayout"; // NOI18N
6011: else
6012: format = property ? "FMT_ERR_LoadingLayoutConstraintsProperty"
6013: : // NOI18N
6014: "FMT_ERR_LoadingLayoutConstraints"; // NOI18N
6015:
6016: StringBuffer buf = new StringBuffer();
6017: buf.append(FormUtils.getFormattedBundleString(format,
6018: new Object[] { pathBuf.toString() }));
6019: buf.append("\n"); // NOI18N
6020: buf.append(errMsg);
6021:
6022: return buf.toString();
6023: }
6024:
6025: // --------------
6026:
6027: // private void raiseFormatVersion(String ver) {
6028: // if (ver != formatVersion
6029: // && (formatVersion == NB32_VERSION
6030: // || (formatVersion == NB33_VERSION && ver == NB34_VERSION)
6031: // || ((formatVersion == NB33_VERSION || formatVersion == NB34_VERSION) && ver == NB42_VERSION)
6032: // || ver == NB60_VERSION))
6033: // formatVersion = ver;
6034: // }
6035:
6036: private static boolean isSupportedFormatVersion(String ver) {
6037: return NB32_VERSION.equals(ver) || NB33_VERSION.equals(ver)
6038: || NB34_VERSION.equals(ver) || NB50_VERSION.equals(ver)
6039: || NB60_PRE_VERSION.equals(ver)
6040: || NB60_VERSION.equals(ver) || NB61_VERSION.equals(ver);
6041: }
6042:
6043: private static FormModel.FormVersion formVersionForVersionString(
6044: String version) {
6045: if (version != null) {
6046: if (NB32_VERSION.equals(version)
6047: || NB33_VERSION.equals(version)
6048: || NB34_VERSION.equals(version)) {
6049: return FormModel.FormVersion.BASIC;
6050: }
6051: if (NB50_VERSION.equals(version)) {
6052: return FormModel.FormVersion.NB50;
6053: }
6054: if (NB60_PRE_VERSION.equals(version)) {
6055: return FormModel.FormVersion.NB60_PRE;
6056: }
6057: if (NB60_VERSION.equals(version)) {
6058: return FormModel.FormVersion.NB60;
6059: }
6060: if (NB61_VERSION.equals(version)) {
6061: return FormModel.FormVersion.NB61;
6062: }
6063: }
6064: return null;
6065: }
6066:
6067: private static String versionStringForFormVersion(
6068: FormModel.FormVersion version) {
6069: if (version != null) {
6070: switch (version) {
6071: case BASIC:
6072: return NB34_VERSION;
6073: case NB50:
6074: return NB50_VERSION;
6075: case NB60_PRE:
6076: return NB60_PRE_VERSION;
6077: case NB60:
6078: return NB60_VERSION;
6079: case NB61:
6080: return NB61_VERSION;
6081: }
6082: }
6083: return null;
6084: }
6085:
6086: // --------------
6087: // NB 3.2 compatibility - dealing with FormInfo
6088:
6089: /** In NB 3.2, the declared superclass in java source was not used, so
6090: * it could be changed incompatibly to the FormInfo type (typically to
6091: * some unrelated non-visual class, moving the generated code to an
6092: * innerclass). We try to detect this and use the FormInfo type
6093: * preferentially in such case.
6094: */
6095: private static Class checkDeclaredSuperclass(
6096: Class declaredSuperclass, String formInfoName) {
6097: if (!java.awt.Component.class
6098: .isAssignableFrom(declaredSuperclass)
6099: && formInfoName != null) {
6100: Class formInfoType = getCompatibleFormClass(formInfoName);
6101: if (formInfoType != null)
6102: return formInfoType;
6103: }
6104: return declaredSuperclass;
6105: }
6106:
6107: /**
6108: * @return class corresponding to given FormInfo class name
6109: */
6110: private static Class getCompatibleFormClass(String formInfoName) {
6111: if (formInfoName == null)
6112: return null; // no FormInfo name found in form file
6113:
6114: return getClassForKnownFormInfo(formInfoName);
6115: // ignore unknown FormInfo - it's deep past...
6116: }
6117:
6118: private static Class getCompatibleFormClass(Class formBaseClass) {
6119: return getClassForKnownFormInfo(getFormInfoForKnownClass(formBaseClass));
6120: }
6121:
6122: private Class getFormDesignClass(String declaredSuperclassName) {
6123: for (ComponentConverter c : FormUtils.getClassConverters()) {
6124: Class convClass = c.getDesignClass(declaredSuperclassName,
6125: formFile);
6126: if (convClass != null) {
6127: return convClass;
6128: }
6129: }
6130: return null;
6131: }
6132:
6133: private Class getFormDesignClass(Class declaredSuperclass) {
6134: for (ComponentConverter c : FormUtils.getClassConverters()) {
6135: Class convClass = c.getDesignClass(declaredSuperclass,
6136: formFile);
6137: if (convClass != null) {
6138: return convClass;
6139: }
6140: }
6141: return null;
6142: }
6143:
6144: private class ConnectedProperties {
6145: private class ConnectedProperty {
6146: private final Property property;
6147: private final String beanName;
6148: private final RADConnectionPropertyEditor.RADConnectionDesignValue value;
6149: private final String tostring;
6150: private final Object auxiliaryValue;
6151: private String valueName = null;
6152:
6153: private ConnectedProperty(
6154: Property property,
6155: RADConnectionPropertyEditor.RADConnectionDesignValue value,
6156: String beanName, Object auxiliaryValue) {
6157: this .property = property;
6158: this .beanName = beanName;
6159: this .value = value;
6160: this .tostring = getKey(beanName, property.getName());
6161: this .auxiliaryValue = auxiliaryValue;
6162: }
6163:
6164: @Override
6165: public boolean equals(Object obj) {
6166: if (!(obj instanceof ConnectedProperty))
6167: return false;
6168: if (this == obj)
6169: return true;
6170: ConnectedProperty cp = (ConnectedProperty) obj;
6171: return beanName.equals(cp.beanName)
6172: && property.equals(cp.property);
6173: }
6174:
6175: @Override
6176: public int hashCode() {
6177: return tostring.hashCode();
6178: }
6179:
6180: RADConnectionPropertyEditor.RADConnectionDesignValue getValue() {
6181: return value;
6182: }
6183:
6184: private String getValueName() {
6185: if (valueName == null) {
6186: if (value.getType() == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_PROPERTY) {
6187: valueName = value.getProperty().getName();
6188: } else if (value.getType() == RADConnectionPropertyEditor.RADConnectionDesignValue.TYPE_METHOD) {
6189: RADComponent component = value
6190: .getRADComponent();
6191: String methodName = value.getMethod().getName();
6192: PropertyDescriptor[] descs = component
6193: .getBeanInfo().getPropertyDescriptors();
6194: for (int i = 0; i < descs.length; i++) {
6195: Method method = descs[i].getReadMethod();
6196: if (method != null
6197: && method.getName().equals(
6198: methodName)) {
6199: methodName = descs[i].getName();
6200: break;
6201: }
6202: }
6203: valueName = methodName;
6204: }
6205: }
6206: return valueName;
6207: }
6208:
6209: Object getAuxiliaryValue() {
6210: return auxiliaryValue;
6211: }
6212:
6213: String getKey() {
6214: return getKey(beanName, property.getName());
6215: }
6216:
6217: String getSourceKey() {
6218: return getKey(value.getRADComponent().getName(),
6219: getValueName());
6220: }
6221:
6222: private String getKey(String beanName, String propertyName) {
6223: StringBuffer sb = new StringBuffer();
6224: sb.append("["); // NOI18N
6225: sb.append(beanName);
6226: sb.append(", "); // NOI18N
6227: sb.append(propertyName);
6228: sb.append("]"); // NOI18N
6229: return sb.toString();
6230: }
6231:
6232: @Override
6233: public String toString() {
6234: return tostring;
6235: }
6236: }
6237:
6238: private Map<String, ConnectedProperty> properties = new HashMap<String, ConnectedProperty>();
6239:
6240: public void put(
6241: Property property,
6242: RADConnectionPropertyEditor.RADConnectionDesignValue value,
6243: String beanName, Object auxiliaryValue) {
6244: ConnectedProperty cp = new ConnectedProperty(property,
6245: value, beanName, auxiliaryValue);
6246: properties.put(cp.getKey(), cp);
6247: }
6248:
6249: private ConnectedProperty get(String key) {
6250: return properties.get(key);
6251: }
6252:
6253: public void setValues() {
6254: Collection sorted = sort();
6255: for (Iterator it = sorted.iterator(); it.hasNext();) {
6256: ConnectedProperty compProperty = (ConnectedProperty) it
6257: .next();
6258: try {
6259: compProperty.property.setValue(compProperty
6260: .getValue());
6261: } catch (Exception ex) {
6262: org.w3c.dom.Node node = (org.w3c.dom.Node) compProperty
6263: .getAuxiliaryValue();
6264: createLoadingErrorMessage(ex, node);
6265: }
6266: }
6267: }
6268:
6269: private Collection<ConnectedProperty> sort() {
6270: List<ConnectedProperty> sortedValues = null;
6271: try {
6272: sortedValues = Utilities.topologicalSort(properties
6273: .values(), getEdges());
6274: } catch (TopologicalSortException tse) {
6275: Set[] sets = tse.topologicalSets();
6276: sortedValues = new ArrayList<ConnectedProperty>();
6277: for (int i = 0; i < sets.length; i++) {
6278: for (Iterator it = sets[i].iterator(); it.hasNext();) {
6279: sortedValues.add((ConnectedProperty) it.next());
6280: }
6281: }
6282: }
6283: if (sortedValues != null) {
6284: Collections.reverse(sortedValues);
6285: return sortedValues;
6286: }
6287: // something went wrong, let's fall back
6288: // on the unsorted values
6289: return properties.values();
6290: }
6291:
6292: private Map<ConnectedProperty, List<ConnectedProperty>> getEdges() {
6293: Map<ConnectedProperty, List<ConnectedProperty>> edges = new HashMap<ConnectedProperty, List<ConnectedProperty>>();
6294: for (Iterator it = properties.values().iterator(); it
6295: .hasNext();) {
6296: ConnectedProperty target = (ConnectedProperty) it
6297: .next();
6298: ConnectedProperty source = get(target.getSourceKey());
6299: if (source != null) {
6300: List<ConnectedProperty> l = new ArrayList<ConnectedProperty>();
6301: l.add(source);
6302: edges.put(target, l);
6303: }
6304: }
6305: return edges;
6306: }
6307: }
6308:
6309: // FormInfo names used in NB 3.2
6310: private static final String[] defaultFormInfoNames = {
6311: "JFrameFormInfo", // NOI18N
6312: "JPanelFormInfo", // NOI18N
6313: "JDialogFormInfo", // NOI18N
6314: "JInternalFrameFormInfo", // NOI18N
6315: "JAppletFormInfo", // NOI18N
6316: "FrameFormInfo", // NOI18N
6317: "AppletFormInfo", // NOI18N
6318: "DialogFormInfo", // NOI18N
6319: "PanelFormInfo" }; // NOI18N
6320:
6321: private static Class getClassForKnownFormInfo(String infoName) {
6322: if (infoName == null)
6323: return null;
6324: int i = infoName.lastIndexOf('.');
6325: String shortName = infoName.substring(i + 1);
6326:
6327: if (defaultFormInfoNames[0].equals(shortName))
6328: return javax.swing.JFrame.class;
6329: else if (defaultFormInfoNames[1].equals(shortName))
6330: return javax.swing.JPanel.class;
6331: else if (defaultFormInfoNames[2].equals(shortName))
6332: return javax.swing.JDialog.class;
6333: else if (defaultFormInfoNames[3].equals(shortName))
6334: return javax.swing.JInternalFrame.class;
6335: else if (defaultFormInfoNames[4].equals(shortName))
6336: return javax.swing.JApplet.class;
6337: else if (defaultFormInfoNames[5].equals(shortName))
6338: return java.awt.Frame.class;
6339: else if (defaultFormInfoNames[6].equals(shortName))
6340: return java.applet.Applet.class;
6341: else if (defaultFormInfoNames[7].equals(shortName))
6342: return java.awt.Dialog.class;
6343: else if (defaultFormInfoNames[8].equals(shortName))
6344: return java.awt.Panel.class;
6345:
6346: return null;
6347: }
6348:
6349: private static String getFormInfoForKnownClass(Class formType) {
6350: String shortName;
6351:
6352: if (javax.swing.JFrame.class.isAssignableFrom(formType))
6353: shortName = defaultFormInfoNames[0];
6354: else if (javax.swing.JPanel.class.isAssignableFrom(formType))
6355: shortName = defaultFormInfoNames[1];
6356: else if (javax.swing.JDialog.class.isAssignableFrom(formType))
6357: shortName = defaultFormInfoNames[2];
6358: else if (javax.swing.JInternalFrame.class
6359: .isAssignableFrom(formType))
6360: shortName = defaultFormInfoNames[3];
6361: else if (javax.swing.JApplet.class.isAssignableFrom(formType))
6362: shortName = defaultFormInfoNames[4];
6363: else if (java.awt.Frame.class.isAssignableFrom(formType))
6364: shortName = defaultFormInfoNames[5];
6365: else if (java.applet.Applet.class.isAssignableFrom(formType))
6366: shortName = defaultFormInfoNames[6];
6367: else if (java.awt.Dialog.class.isAssignableFrom(formType))
6368: shortName = defaultFormInfoNames[7];
6369: else if (java.awt.Panel.class.isAssignableFrom(formType))
6370: shortName = defaultFormInfoNames[8];
6371: else if (org.openide.windows.TopComponent.class.getName()
6372: .equals(formType.getName()))
6373: shortName = defaultFormInfoNames[1]; // fallback TopComponent to JPanel (issue 79695)
6374: else
6375: return null;
6376:
6377: return "org.netbeans.modules.form.forminfo." + shortName; // NOI18N
6378: }
6379:
6380: // --------
6381: // NB 3.1 compatibility - layout persistence conversion tables
6382:
6383: private static final int LAYOUT_BORDER = 0;
6384: private static final int LAYOUT_FLOW = 1;
6385: private static final int LAYOUT_BOX = 2;
6386: private static final int LAYOUT_GRIDBAG = 3;
6387: private static final int LAYOUT_GRID = 4;
6388: private static final int LAYOUT_CARD = 5;
6389: private static final int LAYOUT_ABSOLUTE = 6;
6390: private static final int LAYOUT_NULL = 7;
6391: private static final int LAYOUT_JSCROLL = 8;
6392: private static final int LAYOUT_SCROLL = 9;
6393: private static final int LAYOUT_JSPLIT = 10;
6394: private static final int LAYOUT_JTAB = 11;
6395: private static final int LAYOUT_JLAYER = 12;
6396: private static final int LAYOUT_TOOLBAR = 13;
6397:
6398: private static final int LAYOUT_UNKNOWN = -1;
6399: private static final int LAYOUT_FROM_CODE = -2;
6400: private static final int LAYOUT_NATURAL = -3;
6401:
6402: private static final String[] layout31Names = {
6403: "org.netbeans.modules.form.compat2.layouts.DesignBorderLayout", // NOI18N
6404: "org.netbeans.modules.form.compat2.layouts.DesignFlowLayout", // NOI18N
6405: "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout", // NOI18N
6406: "org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout", // NOI18N
6407: "org.netbeans.modules.form.compat2.layouts.DesignGridLayout", // NOI18N
6408: "org.netbeans.modules.form.compat2.layouts.DesignCardLayout", // NOI18N
6409: "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout", // NOI18N
6410: "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout", // NOI18N
6411: "org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout", // NOI18N
6412: "org.netbeans.modules.form.compat2.layouts.support.ScrollPaneSupportLayout", // NOI18N
6413: "org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout", // NOI18N
6414: "org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout", // NOI18N
6415: "org.netbeans.modules.form.compat2.layouts.support.JLayeredPaneSupportLayout", // NOI18N
6416: "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout" // NOI18N
6417: }; // fixed table, do not change!
6418:
6419: private static final String[] layout31ConstraintsNames = {
6420: "org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription", // NOI18N
6421: "org.netbeans.modules.form.compat2.layouts.DesignFlowLayout$FlowConstraintsDescription", // NOI18N,
6422: "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout$BoxConstraintsDescription", // NOI18N
6423: "org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription", // NOI18N
6424: "org.netbeans.modules.form.compat2.layouts.DesignGridLayout$GridConstraintsDescription", // NOI18N
6425: "org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription", // NOI18N
6426: "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription", // NOI18N
6427: "org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription", // NOI18N
6428: "org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout$JScrollPaneConstraintsDescription", // NOI18N
6429: "org.netbeans.modules.form.compat2.layouts.support.ScrollPaneSupportLayout$ScrollPaneConstraintsDescription", // NOI18N
6430: "org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription", // NOI18N
6431: "org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription", // NOI18N
6432: "org.netbeans.modules.form.compat2.layouts.support.JLayeredPaneSupportLayout$JLayeredPaneConstraintsDescription", // NOI18N
6433: "org.netbeans.modules.form.compat2.layouts.DesignBoxLayout$BoxConstraintsDescription" // NOI18N
6434: }; // fixed table, do not change!
6435:
6436: private static final boolean[] reasonable31Constraints = { true,
6437: false, false, true, false, true, true, true, false, false,
6438: true, true, true, false }; // fixed table, do not change!
6439:
6440: private static final String[] supportedClassNames = {
6441: "java.awt.BorderLayout", // NOI18N
6442: "java.awt.FlowLayout", // NOI18N
6443: "javax.swing.BoxLayout", // NOI18N
6444: "java.awt.GridBagLayout", // NOI18N
6445: "java.awt.GridLayout", // NOI18N
6446: "java.awt.CardLayout", // NOI18N
6447: "org.netbeans.lib.awtextra.AbsoluteLayout", // NOI18N
6448: null, "javax.swing.JScrollPane", // NOI18N
6449: "java.awt.ScrollPane", // NOI18N
6450: "javax.swing.JSplitPane", // NOI18N
6451: "javax.swing.JTabbedPane", // NOI18N
6452: "javax.swing.JLayeredPane", // NOI18N
6453: "javax.swing.JToolBar" // NOI18N
6454: }; // fixed table, do not change!
6455:
6456: private static final String[][] layout31PropertyNames = {
6457: { "horizontalGap", "verticalGap" }, // BorderLayout // NOI18N
6458: { "alignment", "horizontalGap", "verticalGap" }, // FlowLayout // NOI18N
6459: { "axis" }, // BoxLayout // NOI18N
6460: {}, // GridBagLayout
6461: { "rows", "columns", "horizontalGap", "verticalGap" }, // GridLayout // NOI18N
6462: { "horizontalGap", "verticalGap" }, // CardLayout (ignoring "currentCard") // NOI18N
6463: { "useNullLayout" }, // AbsoluteLayout // NOI18N
6464: { "useNullLayout" }, // AbsoluteLayout // NOI18N
6465: {}, // JScrollPane
6466: {}, // ScrollPane
6467: {}, // JSplitPane
6468: {}, // JTabbedPane
6469: {}, // JLayeredPane
6470: { "axis" } // BoxLayout // NOI18N
6471: }; // fixed table, do not change!
6472:
6473: private static final String[][] layoutDelegatePropertyNames = {
6474: { "hgap", "vgap" }, // BorderLayout // NOI18N
6475: { "alignment", "hgap", "vgap" }, // FlowLayout // NOI18N
6476: { "axis" }, // BoxLayout // NOI18N
6477: {}, // GridBagLayout
6478: { "rows", "columns", "hgap", "vgap" }, // GridLayout // NOI18N
6479: { "hgap", "vgap" }, // CardLayout (ignoring "currentCard") // NOI18N
6480: { null }, // AbsoluteLayout
6481: { null }, // null layout
6482: {}, // JScrollPane
6483: {}, // ScrollPane
6484: {}, // JSplitPane
6485: {}, // JTabbedPane
6486: {}, // JLayeredPane
6487: { null } // JToolBar
6488: }; // fixed table, do not change!
6489:
6490: // methods and constructors for creating code structure
6491: private static Method setLayoutMethod;
6492: private static Method simpleAddMethod;
6493: private static Method addWithConstrMethod;
6494: private static Method addTabMethod1;
6495: private static Method addTabMethod2;
6496: private static Method addTabMethod3;
6497: private static Method setLeftComponentMethod;
6498: private static Method setRightComponentMethod;
6499: private static Method setTopComponentMethod;
6500: private static Method setBottomComponentMethod;
6501: private static Method setBoundsMethod;
6502: private static Method setViewportViewMethod;
6503: private static Constructor gridBagConstrConstructor;
6504: private static Constructor insetsConstructor;
6505: private static Constructor absoluteConstraintsConstructor;
6506:
6507: // Special static field holding last loaded layout index. This is hack for
6508: // dealing with multiple constraints types saved by NB 3.1 - we load only
6509: // constraints matching with the current layout. At time of loading
6510: // constraints, the layout is already loaded but the layout support is not
6511: // established yet, so the loadConstraints method cannot find out what the
6512: // current layout of container is.
6513: private static int layoutConvIndex = LAYOUT_UNKNOWN;
6514: }
|