0001: /*
0002: Copyright (c) 2003-2006, Dennis M. Sosnoski
0003: All rights reserved.
0004:
0005: Redistribution and use in source and binary forms, with or without modification,
0006: are permitted provided that the following conditions are met:
0007:
0008: * Redistributions of source code must retain the above copyright notice, this
0009: list of conditions and the following disclaimer.
0010: * Redistributions in binary form must reproduce the above copyright notice,
0011: this list of conditions and the following disclaimer in the documentation
0012: and/or other materials provided with the distribution.
0013: * Neither the name of JiBX nor the names of its contributors may be used
0014: to endorse or promote products derived from this software without specific
0015: prior written permission.
0016:
0017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
0021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027: */
0028:
0029: package org.jibx.binding.def;
0030:
0031: import java.io.IOException;
0032: import java.net.MalformedURLException;
0033: import java.net.URL;
0034: import java.util.ArrayList;
0035: import java.util.HashSet;
0036:
0037: import org.apache.bcel.classfile.Utility;
0038: import org.jibx.binding.classes.ClassCache;
0039: import org.jibx.binding.classes.ClassFile;
0040: import org.jibx.binding.classes.ClassItem;
0041: import org.jibx.runtime.JiBXException;
0042: import org.jibx.runtime.QName;
0043: import org.jibx.runtime.impl.UnmarshallingContext;
0044:
0045: /**
0046: * Binding definition builder. This processes the binding definition file to
0047: * generate the code generation structure.
0048: *
0049: * @author Dennis M. Sosnoski
0050: * @version 1.0
0051: */
0052:
0053: public abstract class BindingBuilder {
0054: /** Element namespace used for binding definition file. */
0055: private static final String URI_ELEMENTS = null;
0056:
0057: /** Attribute namespace used for binding definition file. */
0058: private static final String URI_ATTRIBUTES = null;
0059:
0060: /* Common style attribute. */
0061: private static final String COMMON_STYLE = "value-style";
0062:
0063: /* Common linkage attributes. */
0064: private static final String COMMON_AUTOLINK = "auto-link";
0065: private static final String COMMON_ACCESSLEVEL = "access-level";
0066: private static final String COMMON_STRIPPREFIX = "strip-prefix";
0067: private static final String COMMON_STRIPSUFFIX = "strip-suffix";
0068: private static final String COMMON_NAMESTYLE = "name-style";
0069:
0070: /* Common name attributes. */
0071: private static final String COMMON_NAME = "name";
0072: private static final String COMMON_NAMESPACE = "ns";
0073:
0074: /* Common object attributes. */
0075: private static final String COMMON_FACTORY = "factory";
0076: private static final String COMMON_PRESET = "pre-set";
0077: private static final String COMMON_POSTSET = "post-set";
0078: private static final String COMMON_PREGET = "pre-get";
0079: private static final String COMMON_MARSHALLER = "marshaller";
0080: private static final String COMMON_UNMARSHALLER = "unmarshaller";
0081: private static final String COMMON_CREATETYPE = "create-type";
0082:
0083: /* Common property attributes. */
0084: private static final String COMMON_FIELD = "field";
0085: private static final String COMMON_TYPE = "type";
0086: private static final String COMMON_USAGE = "usage";
0087: private static final String COMMON_TESTMETHOD = "test-method";
0088: private static final String COMMON_GETMETHOD = "get-method";
0089: private static final String COMMON_SETMETHOD = "set-method";
0090:
0091: /* Common string attributes. */
0092: private static final String COMMON_DEFAULT = "default";
0093: private static final String COMMON_SERIALIZER = "serializer";
0094: private static final String COMMON_DESERIALIZER = "deserializer";
0095:
0096: /* Common label attributes. */
0097: private static final String COMMON_LABEL = "label";
0098: private static final String COMMON_USING = "using";
0099:
0100: /* Common ordered and choice attributes. */
0101: private static final String COMMON_ORDERED = "ordered";
0102: private static final String COMMON_CHOICE = "choice";
0103: private static final String COMMON_FLEXIBLE = "flexible";
0104: private static final String COMMON_DUPLICATES = "allow-repeats";
0105:
0106: /* Common nillable attribute. */
0107: private static final String COMMON_NILLABLE = "nillable";
0108:
0109: /** Definitions for "binding" element use "BINDING" prefix. */
0110: private static final String BINDING_ELEMENT = "binding";
0111: private static final String BINDING_NAME = "name";
0112: private static final String BINDING_DIRECTION = "direction";
0113: private static final String BINDING_GLOBALID = "global-id";
0114: private static final String BINDING_FORWARDS = "forwards";
0115: private static final String BINDING_PACKAGE = "package";
0116: private static final String BINDING_TRACKING = "track-source";
0117: private static final String BINDING_FORCE = "force-classes";
0118: // also COMMON_STYLE, and linkage group
0119:
0120: /** Definitions for "namespace" element use "NAMESPACE" prefix. */
0121: private static final String NAMESPACE_ELEMENT = "namespace";
0122: private static final String NAMESPACE_URI = "uri";
0123: private static final String NAMESPACE_PREFIX = "prefix";
0124: private static final String NAMESPACE_DEFAULT = "default";
0125:
0126: /** Definitions for "format" element use "FORMAT" prefix. */
0127: private static final String FORMAT_ELEMENT = "format";
0128: private static final String FORMAT_NAME = "label";
0129: private static final String FORMAT_TYPE = "type";
0130: // also string group
0131:
0132: /** Definitions for "mapping" element use "MAPPING" prefix. */
0133: private static final String MAPPING_ELEMENT = "mapping";
0134: private static final String MAPPING_CLASS = "class";
0135: private static final String MAPPING_ABSTRACT = "abstract";
0136: private static final String MAPPING_EXTENDS = "extends";
0137: private static final String MAPPING_TYPENAME = "type-name";
0138: // also COMMON_STYLE, name, object, ordered, and linkage groups
0139:
0140: /** Definitions for "value" element use "VALUE" prefix. */
0141: private static final String VALUE_ELEMENT = "value";
0142: private static final String VALUE_STYLE = "style";
0143: private static final String VALUE_FORMAT = "format";
0144: private static final String VALUE_CONSTANT = "constant";
0145: private static final String VALUE_IDENT = "ident";
0146: // also name, property, and string groups
0147:
0148: /** Definitions for "structure" element use "STRUCTURE" prefix. */
0149: private static final String STRUCTURE_ELEMENT = "structure";
0150: private static final String STRUCTURE_MAPAS = "map-as";
0151: // also COMMON_STYLE, name, object, ordered, property, and label groups
0152:
0153: /** Definitions for "collection" element use "COLLECTION" prefix. */
0154: private static final String COLLECTION_ELEMENT = "collection";
0155: private static final String COLLECTION_LOADMETHOD = "load-method";
0156: private static final String COLLECTION_SIZEMETHOD = "size-method";
0157: private static final String COLLECTION_STOREMETHOD = "store-method";
0158: private static final String COLLECTION_ADDMETHOD = "add-method";
0159: private static final String COLLECTION_ITERMETHOD = "iter-method";
0160: private static final String COLLECTION_ITEMTYPE = "item-type";
0161: // also COMMON_STYLE, name, ordered, property, and label groups
0162:
0163: /** Definitions for "include" element use "INCLUDE" prefix. */
0164: private static final String INCLUDE_ELEMENT = "include";
0165: private static final String INCLUDE_PATH = "path";
0166:
0167: //
0168: // Value style enumeration.
0169:
0170: private static final String[] VALUE_STYLE_NAMES = { "attribute",
0171: "cdata", "element", "text" };
0172: private static final int[] VALUE_STYLE_NUMS = {
0173: ValueChild.ATTRIBUTE_STYLE, ValueChild.CDATA_STYLE,
0174: ValueChild.ELEMENT_STYLE, ValueChild.TEXT_STYLE };
0175:
0176: private static final String[] CONTAINING_STYLE_NAMES = {
0177: "attribute", "element" };
0178: private static final int[] CONTAINING_STYLE_NUMS = {
0179: ValueChild.ATTRIBUTE_STYLE, ValueChild.ELEMENT_STYLE };
0180:
0181: //
0182: // Enumeration for auto-link types.
0183:
0184: /*package*/static final int LINK_NONE = 0;
0185: /*package*/static final int LINK_FIELDS = 1;
0186: /*package*/static final int LINK_METHODS = 2;
0187:
0188: private static final String[] AUTO_LINK_NAMES = { "fields", "none",
0189: "methods" };
0190: private static final int[] AUTO_LINK_NUMS = { LINK_FIELDS,
0191: LINK_NONE, LINK_METHODS };
0192:
0193: //
0194: // Enumeration for access level.
0195:
0196: /*package*/static final int ACC_PRIVATE = 0;
0197: /*package*/static final int ACC_PACKAGE = 1;
0198: /*package*/static final int ACC_PROTECTED = 2;
0199: /*package*/static final int ACC_PUBLIC = 3;
0200:
0201: private static final String[] ACCESS_LEVEL_NAMES = { "package",
0202: "private", "protected", "public" };
0203: private static final int[] ACCESS_LEVEL_NUMS = { ACC_PACKAGE,
0204: ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC };
0205:
0206: //
0207: // Enumeration for name generation styles.
0208:
0209: /*package*/static final int NAME_HYPHENS = 0;
0210: /*package*/static final int NAME_MIXED = 1;
0211:
0212: private static final String[] NAME_GENERATE_NAMES = { "hyphens",
0213: "mixed-case" };
0214: private static final int[] NAME_GENERATE_NUMS = { NAME_HYPHENS,
0215: NAME_MIXED };
0216:
0217: //
0218: // Attributes that imply a component object
0219:
0220: private static final String[] COMPONENT_OBJECT_NAMESPACES = {
0221: URI_ATTRIBUTES, URI_ATTRIBUTES, URI_ATTRIBUTES,
0222: URI_ATTRIBUTES };
0223: private static final String[] COMPONENT_OBJECT_NAMES = {
0224: COMMON_FACTORY, COMMON_PRESET, COMMON_POSTSET,
0225: COMMON_PREGET };
0226:
0227: //
0228: // Enumeration for namespace usage.
0229:
0230: private static final String[] NAMESPACEACCESS_NAMES = { "all",
0231: "attributes", "elements", "none" };
0232: private static final int[] NAMESPACEACCESS_NUMS = {
0233: NamespaceDefinition.ALLDEFAULT_USAGE,
0234: NamespaceDefinition.ATTRIBUTES_USAGE,
0235: NamespaceDefinition.ELEMENTS_USAGE,
0236: NamespaceDefinition.NODEFAULT_USAGE };
0237:
0238: //
0239: // Ident type enumeration.
0240:
0241: private static final String[] IDENTTYPE_NAMES = { "auto", "def",
0242: "direct", "ref" };
0243: private static final int[] IDENTTYPE_NUMS = {
0244: ValueChild.AUTO_IDENT, ValueChild.DEF_IDENT,
0245: ValueChild.DIRECT_IDENT, ValueChild.REF_IDENT };
0246:
0247: //
0248: // Binding direction enumeration.
0249:
0250: private static final int DIRECTION_INPUT = 0;
0251: private static final int DIRECTION_OUTPUT = 1;
0252: private static final int DIRECTION_BOTH = 2;
0253:
0254: private static final String[] BINDINGDIR_NAMES = { "both", "input",
0255: "output" };
0256: private static final int[] BINDINGDIR_NUMS = { DIRECTION_BOTH,
0257: DIRECTION_INPUT, DIRECTION_OUTPUT };
0258:
0259: //
0260: // Constants for property usage values
0261:
0262: private static final String USAGE_OPTIONAL = "optional";
0263: private static final String USAGE_REQUIRED = "required";
0264:
0265: //
0266: // Checking and code generation constants
0267:
0268: private static final String UNMARSHALLER_INTERFACE = "org.jibx.runtime.IUnmarshaller";
0269: private static final String MARSHALLER_INTERFACE = "org.jibx.runtime.IMarshaller";
0270: private static final String UNMARSHALLER_INTERFACETYPE = "Lorg/jibx/runtime/IUnmarshaller;";
0271: private static final String MARSHALLER_INTERFACETYPE = "Lorg/jibx/runtime/IMarshaller;";
0272:
0273: /**
0274: * Check if attributes supply a name definition.
0275: *
0276: * @param ctx unmarshalling context information
0277: * @return <code>true</code> if attributes define a name,
0278: * <code>false</code> if not
0279: */
0280:
0281: private static boolean isNamePresent(UnmarshallingContext ctx) {
0282: return ctx.attributeText(URI_ATTRIBUTES, COMMON_NAME, null) != null;
0283: }
0284:
0285: /**
0286: * Check for property definition present. Just checks the attributes of
0287: * the current element.
0288: *
0289: * @param ctx unmarshalling context information
0290: */
0291:
0292: private static boolean isPropertyPresent(UnmarshallingContext ctx) {
0293: return ctx.attributeText(URI_ATTRIBUTES, COMMON_FIELD, null) != null
0294: || ctx.attributeText(URI_ATTRIBUTES, COMMON_GETMETHOD,
0295: null) != null
0296: || ctx.attributeText(URI_ATTRIBUTES, COMMON_SETMETHOD,
0297: null) != null
0298: || ctx.attributeText(URI_ATTRIBUTES, COMMON_TESTMETHOD,
0299: null) != null;
0300: }
0301:
0302: /**
0303: * Check if attributes define a direct object reference. Just checks the
0304: * attributes of the current element.
0305: *
0306: * @param ctx unmarshalling context information
0307: */
0308:
0309: private static boolean isDirectObject(UnmarshallingContext ctx) {
0310: return ctx.attributeText(URI_ATTRIBUTES, COMMON_MARSHALLER,
0311: null) != null
0312: || ctx.attributeText(URI_ATTRIBUTES,
0313: COMMON_UNMARSHALLER, null) != null;
0314: }
0315:
0316: /**
0317: * Check if attributes define a mapping reference.
0318: *
0319: * @param ctx unmarshalling context information
0320: * @return <code>true</code> if attributes define a mapping reference,
0321: * <code>false</code> if not
0322: * @throws JiBXException if error in unmarshalling
0323: */
0324:
0325: private static boolean isMappingRef(UnmarshallingContext ctx)
0326: throws JiBXException {
0327: return ctx.hasAttribute(URI_ATTRIBUTES, STRUCTURE_MAPAS);
0328: }
0329:
0330: /**
0331: * Check for component object present. Just checks the attributes of the
0332: * current element, so this is not definitive - there may still be child
0333: * binding definitions even without attributes.
0334: *
0335: * @param ctx unmarshalling context information
0336: * @throws JiBXException if error in unmarshalling
0337: */
0338:
0339: private static boolean isObjectBinding(UnmarshallingContext ctx)
0340: throws JiBXException {
0341: return ctx.hasAnyAttribute(COMPONENT_OBJECT_NAMESPACES,
0342: COMPONENT_OBJECT_NAMES);
0343: }
0344:
0345: /**
0346: * Unmarshal name definition. This unmarshals directly from attributes of
0347: * the current element.
0348: *
0349: * @param ctx unmarshalling context information
0350: * @param attr flag for attribute name definition
0351: * @throws JiBXException if error in unmarshalling
0352: */
0353:
0354: private static NameDefinition unmarshalName(
0355: UnmarshallingContext ctx, boolean attr)
0356: throws JiBXException {
0357: String name = ctx.attributeText(URI_ATTRIBUTES, COMMON_NAME);
0358: String ns = ctx.attributeText(URI_ATTRIBUTES, COMMON_NAMESPACE,
0359: null);
0360: return new NameDefinition(name, ns, attr);
0361: }
0362:
0363: /**
0364: * Unmarshal namespace definition.
0365: *
0366: * @param ctx unmarshalling context information
0367: * @throws JiBXException if error in unmarshalling
0368: */
0369:
0370: private static NamespaceDefinition unmarshalNamespace(
0371: UnmarshallingContext ctx) throws JiBXException {
0372:
0373: // set up the basic information
0374: String uri = ctx.attributeText(URI_ATTRIBUTES, NAMESPACE_URI);
0375: String prefix = ctx.attributeText(URI_ATTRIBUTES,
0376: NAMESPACE_PREFIX, null);
0377: if ("".equals(prefix)) {
0378: prefix = null;
0379: }
0380:
0381: // check default usage attribute
0382: int usage = ctx.attributeEnumeration(URI_ATTRIBUTES,
0383: NAMESPACE_DEFAULT, NAMESPACEACCESS_NAMES,
0384: NAMESPACEACCESS_NUMS,
0385: NamespaceDefinition.NODEFAULT_USAGE);
0386:
0387: // finish parsing the element
0388: ctx.parsePastEndTag(URI_ELEMENTS, NAMESPACE_ELEMENT);
0389: return new NamespaceDefinition(uri, prefix, usage);
0390: }
0391:
0392: /**
0393: * Unmarshal string conversion. Unmarshals conversion information directly
0394: * from the attributes of the current start tag.
0395: *
0396: * @param ctx unmarshalling context information
0397: * @param base conversion used as base for this conversion
0398: * @param type fully qualified class name of type handled by conversion
0399: * @throws JiBXException if error in unmarshalling
0400: */
0401:
0402: private static StringConversion unmarshalStringConversion(
0403: UnmarshallingContext ctx, StringConversion base, String type)
0404: throws JiBXException {
0405: String dflt = ctx.attributeText(URI_ATTRIBUTES, COMMON_DEFAULT,
0406: null);
0407: String ser = ctx.attributeText(URI_ATTRIBUTES,
0408: COMMON_SERIALIZER, null);
0409: String dser = ctx.attributeText(URI_ATTRIBUTES,
0410: COMMON_DESERIALIZER, null);
0411: return base.derive(type, ser, dser, dflt);
0412: }
0413:
0414: /**
0415: * Check for optional property. Just checks for the attribute and makes sure
0416: * it has a valid value if present, returning either the default or the
0417: * defined value.
0418: *
0419: * @param ctx unmarshalling context information
0420: * @return <code>true</code> if attribute present with value "true",
0421: * <code>false</code> otherwise
0422: * @throws JiBXException if error in unmarshalling
0423: */
0424:
0425: private static boolean isOptionalProperty(UnmarshallingContext ctx)
0426: throws JiBXException {
0427: boolean opt = false;
0428: String value = ctx.attributeText(URI_ATTRIBUTES, COMMON_USAGE,
0429: USAGE_REQUIRED);
0430: if (USAGE_OPTIONAL.equals(value)) {
0431: opt = true;
0432: } else if (!USAGE_REQUIRED.equals(value)) {
0433: ctx.throwStartTagException("Illegal value for \""
0434: + COMMON_USAGE + "\" attribute");
0435: }
0436: return opt;
0437: }
0438:
0439: /**
0440: * Unmarshal property definition. This unmarshals directly from attributes
0441: * of the current element.
0442: *
0443: * @param ctx unmarshalling context information
0444: * @param parent containing binding definition structure
0445: * @param cobj context object information
0446: * @param opt force optional value flag
0447: * @throws JiBXException if error in unmarshalling
0448: */
0449:
0450: private static PropertyDefinition unmarshalProperty(
0451: UnmarshallingContext ctx, IContainer parent,
0452: IContextObj cobj, boolean opt) throws JiBXException {
0453:
0454: // read basic attribute values for property definition
0455: String type = ctx.attributeText(URI_ATTRIBUTES, COMMON_TYPE,
0456: null);
0457: if (!(parent instanceof NestedCollection)
0458: && isOptionalProperty(ctx)) {
0459: opt = true;
0460: }
0461:
0462: // read and validate method and/or field attribute values
0463: PropertyDefinition pdef = null;
0464: try {
0465: String fname = ctx.attributeText(URI_ATTRIBUTES,
0466: COMMON_FIELD, null);
0467: String test = ctx.attributeText(URI_ATTRIBUTES,
0468: COMMON_TESTMETHOD, null);
0469: String get = ctx.attributeText(URI_ATTRIBUTES,
0470: COMMON_GETMETHOD, null);
0471: String set = ctx.attributeText(URI_ATTRIBUTES,
0472: COMMON_SETMETHOD, null);
0473: boolean isthis = fname == null && get == null
0474: && set == null;
0475: pdef = new PropertyDefinition(parent, cobj, type, isthis ,
0476: opt, fname, test, get, set);
0477:
0478: } catch (JiBXException ex) {
0479:
0480: // rethrow error message with position information
0481: ctx.throwStartTagException(ex.getMessage());
0482: }
0483: return pdef;
0484: }
0485:
0486: /**
0487: * Unmarshal value definition. This handles the complete element supplying
0488: * the value binding.
0489: *
0490: * @param ctx unmarshalling context information
0491: * @param parent containing binding definition structure
0492: * @param cobj context object information
0493: * @param uord unordered collection member flag
0494: * @param impl implicit value from collection flag
0495: * @param itype base type for value
0496: * @throws JiBXException if error in unmarshalling
0497: */
0498:
0499: private static ValueChild unmarshalValue(UnmarshallingContext ctx,
0500: IContainer parent, IContextObj cobj, boolean uord,
0501: boolean impl, String itype) throws JiBXException {
0502:
0503: // find the style for this value
0504: int style = ctx.attributeEnumeration(URI_ATTRIBUTES,
0505: VALUE_STYLE, VALUE_STYLE_NAMES, VALUE_STYLE_NUMS,
0506: parent.getStyleDefault());
0507:
0508: // set up the basic structures
0509: boolean isatt = style == ValueChild.ATTRIBUTE_STYLE;
0510: NameDefinition name = null;
0511: if (isatt || style == ValueChild.ELEMENT_STYLE) {
0512: name = unmarshalName(ctx, isatt);
0513: name.fixNamespace(parent.getDefinitionContext());
0514: } else if (isNamePresent(ctx)) {
0515: ctx
0516: .throwStartTagException("Name not allowed for text or CDATA value");
0517: }
0518: String constant = ctx.attributeText(URI_ATTRIBUTES,
0519: VALUE_CONSTANT, null);
0520:
0521: // handle property information (unless auto ident or implicit value)
0522: int ident = ctx.attributeEnumeration(URI_ATTRIBUTES,
0523: VALUE_IDENT, IDENTTYPE_NAMES, IDENTTYPE_NUMS,
0524: ValueChild.DIRECT_IDENT);
0525: PropertyDefinition prop = null;
0526: if (ident == ValueChild.AUTO_IDENT) {
0527: ctx
0528: .throwStartTagException("Automatic id generation not yet supported");
0529: } else if (impl) {
0530: String type = ctx.attributeText(URI_ATTRIBUTES,
0531: COMMON_TYPE, itype);
0532: prop = new PropertyDefinition(type, cobj,
0533: !(parent instanceof NestedCollection)
0534: && isOptionalProperty(ctx));
0535: } else {
0536: prop = unmarshalProperty(ctx, parent, cobj, ctx
0537: .hasAttribute(URI_ATTRIBUTES, COMMON_DEFAULT));
0538: /* if (constant == null && prop.isThis()) {
0539: ctx.throwStartTagException("No property for value");
0540: } else if (prop.isOptional()) {
0541: if (ident == ValueChild.DEF_IDENT) {
0542: ctx.throwStartTagException("Object ID cannot be optional");
0543: }
0544: } else if (uord) {
0545: ctx.throwStartTagException("All items in unordered " +
0546: "structure must be optional");
0547: } */
0548: }
0549: if (ident != ValueChild.DIRECT_IDENT && uord) {
0550: ctx.throwStartTagException(VALUE_IDENT
0551: + " not allowed in unordered structure");
0552: }
0553:
0554: // find the basic converter to use
0555: StringConversion convert = null;
0556: String type = (prop == null || constant != null) ? "java.lang.String"
0557: : prop.getTypeName();
0558: String format = ctx.attributeText(URI_ATTRIBUTES, VALUE_FORMAT,
0559: null);
0560: DefinitionContext defc = parent.getDefinitionContext();
0561: if (format == null) {
0562:
0563: // no format name, get specific convertor for type or best match
0564: convert = defc.getSpecificConversion(type);
0565: if (convert == null) {
0566:
0567: // find best match converter for type
0568: ClassFile target = ClassCache.getClassFile(type);
0569: convert = defc.getConversion(target);
0570:
0571: // check for a Java 5 enumeration
0572: boolean isenum = false;
0573: ClassFile sclas = target;
0574: while ((sclas = sclas.getSuperFile()) != null) {
0575: if (sclas.getName().equals("java.lang.Enum")) {
0576: isenum = true;
0577: break;
0578: }
0579: }
0580:
0581: // generate specific converter based on general form
0582: if (isenum) {
0583: String dser = type + '.' + "valueOf";
0584: convert = convert.derive(type, null, dser, null);
0585: } else if (convert.getTypeName().equals(
0586: "java.lang.Object")) {
0587: convert = new ObjectStringConversion(type,
0588: (ObjectStringConversion) convert);
0589: }
0590: }
0591:
0592: } else {
0593:
0594: // format name supplied, look it up and check compatibility
0595: QName qname = QName.deserialize(format, ctx);
0596: convert = defc.getNamedConversion(qname);
0597: if (convert == null) {
0598: ctx.throwStartTagException("Unknown format \"" + format
0599: + "\"");
0600: }
0601: String ctype = convert.getTypeName();
0602: if (!ClassItem.isAssignable(type, ctype)
0603: && !ClassItem.isAssignable(ctype, type)) {
0604: ctx
0605: .throwStartTagException("Converter type not compatible with value type");
0606: }
0607: }
0608:
0609: // check for any special conversion handling
0610: String dflt = ctx.attributeText(URI_ATTRIBUTES, COMMON_DEFAULT,
0611: null);
0612: String ser = ctx.attributeText(URI_ATTRIBUTES,
0613: COMMON_SERIALIZER, null);
0614: String dser = ctx.attributeText(URI_ATTRIBUTES,
0615: COMMON_DESERIALIZER, null);
0616: if (dflt != null || ser != null || dser != null) {
0617: convert = convert.derive(type, ser, dser, dflt);
0618: }
0619:
0620: // create the instance to be returned
0621: boolean nillable = ctx.attributeBoolean(URI_ATTRIBUTES,
0622: COMMON_NILLABLE, false);
0623: if (nillable) {
0624: parent.getBindingRoot().setSchemaInstanceUsed();
0625: }
0626: ValueChild value = new ValueChild(parent, cobj, name, prop,
0627: convert, style, ident, constant, nillable);
0628:
0629: // handle identifier property flag
0630: if (ident == ValueChild.DEF_IDENT
0631: || ident == ValueChild.AUTO_IDENT) {
0632: if (!cobj.setIdChild(value)) {
0633: ctx
0634: .throwStartTagException("Duplicate ID definition for containing mapping");
0635: } else if (!"java.lang.String".equals(type)) {
0636: ctx
0637: .throwStartTagException("ID property must be a String");
0638: }
0639: }
0640:
0641: // finish with skipping past end tag
0642: ctx.parsePastEndTag(URI_ELEMENTS, VALUE_ELEMENT);
0643: return value;
0644: }
0645:
0646: /**
0647: * Unmarshal direct object component. Just constructs the component to
0648: * be returned along with the supporting objects, and verifies that no
0649: * disallowed properties are present.
0650: *
0651: * @param ctx unmarshalling context information
0652: * @param type fully qualified class name of object type handled
0653: * @param parent containing binding definition structure
0654: * @param defc definition context to be used (if separate from parent,
0655: * otherwise <code>null</code>)
0656: * @param slot marshaller/unmarshaller slot number
0657: * @param name element name information (<code>null</code> if no element
0658: * name)
0659: * @return constructed direct object component
0660: * @throws JiBXException if error in unmarshalling
0661: */
0662:
0663: private static DirectObject unmarshalDirectObj(
0664: UnmarshallingContext ctx, String type, IContainer parent,
0665: DefinitionContext defc, int slot, NameDefinition name)
0666: throws JiBXException {
0667:
0668: // define and validate marshaller
0669: ClassFile mcf = null;
0670: if (parent.getBindingRoot().isOutput()) {
0671: String clas = ctx.attributeText(URI_ATTRIBUTES,
0672: COMMON_MARSHALLER);
0673: mcf = ClassCache.getClassFile(clas);
0674: if (!mcf.isImplements(MARSHALLER_INTERFACETYPE)) {
0675: ctx.throwStartTagException("Marshaller class " + clas
0676: + " does not implement required interface "
0677: + MARSHALLER_INTERFACE);
0678: }
0679: }
0680:
0681: // define and validate unmarshaller
0682: ClassFile ucf = null;
0683: if (parent.getBindingRoot().isInput()) {
0684: String clas = ctx.attributeText(URI_ATTRIBUTES,
0685: COMMON_UNMARSHALLER);
0686: ucf = ClassCache.getClassFile(clas);
0687: if (!ucf.isImplements(UNMARSHALLER_INTERFACETYPE)) {
0688: ctx.throwStartTagException("Unmarshaller class " + clas
0689: + " does not implement required interface "
0690: + UNMARSHALLER_INTERFACE);
0691: }
0692: }
0693:
0694: // make sure none of the prohibited attributes are present
0695: if (isObjectBinding(ctx)) {
0696: ctx.throwStartTagException("Other object attributes not "
0697: + "allowed when using marshaller or unmarshaller");
0698: } else if (isMappingRef(ctx)) {
0699: ctx.throwStartTagException("Mapping not allowed when "
0700: + "using marshaller or unmarshaller");
0701: } else if (ctx.hasAttribute(URI_ATTRIBUTES, COMMON_USING)) {
0702: ctx
0703: .throwStartTagException(COMMON_USING
0704: + " attribute not allowed when using marshaller or unmarshaller");
0705: }
0706:
0707: // return constructed instance
0708: return new DirectObject(parent, defc, ClassCache
0709: .getClassFile(type), false, mcf, ucf, slot, name);
0710: }
0711:
0712: /**
0713: * Unmarshal mapping reference component. Just constructs the component to
0714: * be returned along with the supporting objects, and verifies that no
0715: * disallowed properties are present.
0716: *
0717: * @param ctx unmarshalling context information
0718: * @param parent containing binding definition structure
0719: * @param objc current object context
0720: * @param prop property definition
0721: * @param name reference name definition (only allowed with abstract
0722: * mappings)
0723: * @return constructed mapping reference component
0724: * @throws JiBXException if error in unmarshalling
0725: */
0726: private static IComponent unmarshalMappingRef(
0727: UnmarshallingContext ctx, IContainer parent,
0728: IContextObj objc, PropertyDefinition prop,
0729: NameDefinition name) throws JiBXException {
0730:
0731: // make sure no forbidden attributes are present
0732: if (isObjectBinding(ctx)) {
0733: ctx.throwStartTagException("Other object attributes not "
0734: + "allowed when using mapping reference");
0735: } else if (ctx.hasAttribute(URI_ATTRIBUTES, COMMON_USING)) {
0736: ctx
0737: .throwStartTagException(COMMON_USING
0738: + " attribute not allowed when using mapping reference");
0739: }
0740:
0741: // build the actual component to be returned
0742: String type = (prop == null) ? null : prop.getTypeName();
0743: String text = ctx.attributeText(URI_ATTRIBUTES,
0744: STRUCTURE_MAPAS, type);
0745: QName qname = QName.deserialize(text, ctx);
0746: boolean nillable = ctx.attributeBoolean(URI_ATTRIBUTES,
0747: COMMON_NILLABLE, false);
0748: if (nillable) {
0749: parent.getBindingRoot().setSchemaInstanceUsed();
0750: }
0751: return new MappingReference(parent, prop, type, text, qname
0752: .toString(), objc, name, false, nillable);
0753: }
0754:
0755: /**
0756: * Unmarshal structure reference component. Just constructs the component to
0757: * be returned along with the supporting objects, and verifies that no
0758: * disallowed properties are present.
0759: *
0760: * @param ctx unmarshalling context information
0761: * @param contain containing binding component
0762: * @param name element name information (<code>null</code> if no element
0763: * name)
0764: * @param prop property definition (<code>null</code> if no separate
0765: * property)
0766: * @param cobj context object
0767: * @return constructed structure reference component
0768: * @throws JiBXException if error in unmarshalling
0769: */
0770: private static IComponent unmarshalStructureRef(
0771: UnmarshallingContext ctx, IContainer contain,
0772: NameDefinition name, PropertyDefinition prop,
0773: IContextObj cobj) throws JiBXException {
0774:
0775: // make sure no forbidden attributes are present
0776: if (isObjectBinding(ctx)) {
0777: ctx.throwStartTagException("Other object attributes not "
0778: + "allowed when using structure reference");
0779: }
0780:
0781: // build the actual component to be returned
0782: String ident = ctx.attributeText(URI_ATTRIBUTES, COMMON_USING);
0783: IComponent comp = new StructureReference(contain, ident, prop,
0784: name != null, cobj);
0785: if (name != null) {
0786: boolean nillable = ctx.attributeBoolean(URI_ATTRIBUTES,
0787: COMMON_NILLABLE, false);
0788: if (nillable) {
0789: contain.getBindingRoot().setSchemaInstanceUsed();
0790: }
0791: comp = new ElementWrapper(contain.getDefinitionContext(),
0792: name, comp, nillable);
0793: if (prop != null && prop.isOptional()) {
0794: ((ElementWrapper) comp).setOptionalNormal(true);
0795: ((ElementWrapper) comp).setStructureObject(true);
0796: comp = new OptionalStructureWrapper(comp, prop, true);
0797: prop.setOptional(false);
0798: }
0799: }
0800: return comp;
0801: }
0802:
0803: /**
0804: * Unmarshal child bindings for a nested structure definition.
0805: *
0806: * @param ctx unmarshalling context information
0807: * @param nest nested structure definition
0808: * @param objc context object definition
0809: * @param impl property value implicit flag
0810: * @param itype item type for child components
0811: * @throws JiBXException if error in unmarshalling
0812: */
0813:
0814: private static void unmarshalStructureChildren(
0815: UnmarshallingContext ctx, NestedBase nest,
0816: IContextObj objc, boolean impl, String itype)
0817: throws JiBXException {
0818: boolean uord = !nest.isContentOrdered();
0819: while (true) {
0820:
0821: // unmarshal next child binding definition
0822: IComponent comp;
0823: if (ctx.isAt(URI_ELEMENTS, VALUE_ELEMENT)) {
0824: ValueChild child = unmarshalValue(ctx, nest, objc,
0825: uord, impl, itype);
0826: comp = child;
0827: } else if (ctx.isAt(URI_ELEMENTS, STRUCTURE_ELEMENT)) {
0828: comp = unmarshalStructure(ctx, nest, objc, false, uord,
0829: impl);
0830: } else if (ctx.isAt(URI_ELEMENTS, COLLECTION_ELEMENT)) {
0831: comp = unmarshalStructure(ctx, nest, objc, true, uord,
0832: impl);
0833: } else {
0834: break;
0835: }
0836:
0837: // add component to structure
0838: nest.addComponent(comp);
0839: }
0840: }
0841:
0842: /**
0843: * Unmarshal object binding component. Just constructs the component to
0844: * be returned along with the supporting objects. This handles both the
0845: * unmarshalling of attributes, and of nested binding components.
0846: *
0847: * @param ctx unmarshalling context information
0848: * @param parent containing binding definition structure
0849: * @param objc current object context
0850: * @param type fully qualified name of object class
0851: * @return constructed structure reference component
0852: * @throws JiBXException if error in unmarshalling
0853: */
0854:
0855: private static ObjectBinding unmarshalObjectBinding(
0856: UnmarshallingContext ctx, IContextObj objc,
0857: IContainer parent, String type) throws JiBXException {
0858:
0859: // set method names from attributes of start tag
0860: String fact = ctx.attributeText(URI_ATTRIBUTES, COMMON_FACTORY,
0861: null);
0862: String pres = ctx.attributeText(URI_ATTRIBUTES, COMMON_PRESET,
0863: null);
0864: String posts = ctx.attributeText(URI_ATTRIBUTES,
0865: COMMON_POSTSET, null);
0866: String preg = ctx.attributeText(URI_ATTRIBUTES, COMMON_PREGET,
0867: null);
0868: String ctype = ctx.attributeText(URI_ATTRIBUTES,
0869: COMMON_CREATETYPE, null);
0870: ObjectBinding bind = null;
0871: try {
0872: bind = new ObjectBinding(parent, objc, type, fact, pres,
0873: posts, preg, ctype);
0874: } catch (JiBXException ex) {
0875: ctx.throwStartTagException(ex.getMessage(), ex);
0876: }
0877: return bind;
0878: }
0879:
0880: /**
0881: * Unmarshal namespace definitions. Any namespace definitions present are
0882: * unmarshalled and added to the supplied definition context.
0883: *
0884: * @param ctx unmarshalling context information
0885: * @param defc definition context for defined namespaces
0886: * @throws JiBXException if error in unmarshalling
0887: */
0888:
0889: private static void unmarshalNamespaces(UnmarshallingContext ctx,
0890: DefinitionContext defc) throws JiBXException {
0891: while (ctx.isAt(URI_ELEMENTS, NAMESPACE_ELEMENT)) {
0892: defc.addNamespace(unmarshalNamespace(ctx));
0893: }
0894: }
0895:
0896: /**
0897: * Unmarshal format definitions. Any format definitions present are
0898: * unmarshalled and added to the supplied definition context.
0899: *
0900: * @param ctx unmarshalling context information
0901: * @param defc definition context for defined formats
0902: * @throws JiBXException if error in unmarshalling
0903: */
0904:
0905: private static void unmarshalFormats(UnmarshallingContext ctx,
0906: DefinitionContext defc) throws JiBXException {
0907:
0908: // process all format definitions at level
0909: while (ctx.isAt(URI_ELEMENTS, FORMAT_ELEMENT)) {
0910:
0911: // find the current default format information for type
0912: String type = ctx
0913: .attributeText(URI_ATTRIBUTES, FORMAT_TYPE);
0914: String sig = Utility.getSignature(type);
0915: StringConversion base = null;
0916: if (sig.length() == 1) {
0917:
0918: // must be a primitive, check type directly
0919: base = defc.getSpecificConversion(type);
0920: if (base == null) {
0921: ctx.throwStartTagException("Unsupported \""
0922: + FORMAT_TYPE + "\" value");
0923: }
0924:
0925: } else {
0926:
0927: // must be an object type, find best match
0928: ClassFile cf = ClassCache.getClassFile(type);
0929: base = defc.getConversion(cf);
0930:
0931: }
0932:
0933: // unmarshal with defaults provided by existing format
0934: StringConversion format = unmarshalStringConversion(ctx,
0935: base, type);
0936:
0937: // handle based on presence or absence of name attribute
0938: String text = ctx.attributeText(URI_ATTRIBUTES,
0939: FORMAT_NAME, null);
0940: if (text == null) {
0941: defc.setConversion(format);
0942: } else {
0943: QName qname = QName.deserialize(text, ctx);
0944: defc.setNamedConversion(qname, format);
0945: }
0946:
0947: // scan past end of definition
0948: ctx.parsePastEndTag(URI_ELEMENTS, FORMAT_ELEMENT);
0949: }
0950: }
0951:
0952: /**
0953: * Unmarshal mapping definitions. Any mapping definitions present are
0954: * unmarshalled and added to the supplied definition context.
0955: *
0956: * @param ctx unmarshalling context information
0957: * @param parent containing binding definition structure
0958: * @param nss extra namespaces to be included in this mapping definition
0959: * (may be <code>null</code>)
0960: * @param uord container is unordered structure flag
0961: * @throws JiBXException if error in unmarshalling
0962: */
0963:
0964: private static void unmarshalMappings(UnmarshallingContext ctx,
0965: IContainer parent, ArrayList nss, boolean uord)
0966: throws JiBXException {
0967: while (ctx.isAt(URI_ELEMENTS, MAPPING_ELEMENT)) {
0968: unmarshalMapping(ctx, parent, nss, uord);
0969: }
0970: }
0971:
0972: /**
0973: * Unmarshal subclass instance for structure definition. This handles all
0974: * combinations of attributes on the start tag, generating the appropriate
0975: * structure of nested components and other classes to represent the binding
0976: * information within the current element. This must be called with the
0977: * parse positioned at the start tag of the element to be unmarshalled.
0978: *
0979: * TODO: At least split this up, or organize a better way to build binding
0980: *
0981: * @param ctx unmarshalling context information
0982: * @param contain containing binding definition structure
0983: * @param cobj context object information
0984: * @param coll collection structure flag
0985: * @param uord container is unordered structure flag
0986: * @param implic property value implicit flag
0987: * @return root of component tree constructed from binding
0988: * @throws JiBXException if error in unmarshalling
0989: */
0990:
0991: public static IComponent unmarshalStructure(
0992: UnmarshallingContext ctx, IContainer contain,
0993: IContextObj cobj, boolean coll, boolean uord, boolean implic)
0994: throws JiBXException {
0995:
0996: // get name definition if supplied (check later to see if valid)
0997: NameDefinition name = null;
0998: if (isNamePresent(ctx)) {
0999: name = unmarshalName(ctx, false);
1000: }
1001:
1002: // check for optional flag on structure
1003: boolean opt = isOptionalProperty(ctx);
1004: boolean incoll = false;
1005: if (contain instanceof NestedCollection) {
1006: incoll = true;
1007: opt = false;
1008: }
1009:
1010: // check for property definition supplied
1011: IComponent comp;
1012: boolean hasprop = isPropertyPresent(ctx);
1013: boolean this ref = false;
1014: if (!hasprop) {
1015: this ref = incoll
1016: || ctx.hasAttribute(URI_ATTRIBUTES, COMMON_TYPE);
1017: }
1018: boolean mapping = isMappingRef(ctx);
1019: if (hasprop || coll || implic || this ref) {
1020:
1021: // set up the property definition to be used
1022: PropertyDefinition prop = null;
1023: boolean hasobj = hasprop;
1024: if (implic) {
1025:
1026: // make sure no override of implicit property from collection
1027: if (hasprop) {
1028: ctx
1029: .throwStartTagException("Property definition not "
1030: + "allowed for collection items");
1031: } else {
1032: String type = ctx.attributeText(URI_ATTRIBUTES,
1033: COMMON_TYPE, null);
1034: if (type == null) {
1035: if (!mapping) {
1036: if (incoll) {
1037: type = ((NestedCollection) contain)
1038: .getItemType();
1039: hasobj = true;
1040: } else {
1041: type = "java.lang.Object";
1042: }
1043: }
1044: } else {
1045: hasobj = true;
1046: }
1047: prop = new PropertyDefinition(type, cobj, opt);
1048: }
1049:
1050: } else if (hasprop || this ref) {
1051: prop = unmarshalProperty(ctx, contain, cobj, opt);
1052: } else {
1053: prop = new PropertyDefinition(cobj, opt);
1054: }
1055:
1056: // check if using direct object marshalling and unmarshalling
1057: if (isDirectObject(ctx)) {
1058:
1059: // validate and configure direct marshalling and unmarshalling
1060: comp = new DirectProperty(prop, unmarshalDirectObj(ctx,
1061: prop.getTypeName(), contain, null, -1, name));
1062:
1063: } else if (mapping) {
1064:
1065: // validate and configure reference to mapping in context
1066: comp = unmarshalMappingRef(ctx, contain, cobj, prop,
1067: name);
1068:
1069: } else {
1070:
1071: // check for object binding needed
1072: IContextObj icobj = cobj;
1073: ObjectBinding bind = null;
1074: boolean typed = false;
1075: if (implic) {
1076: typed = !prop.getTypeName().equals(
1077: "java.lang.Object");
1078: } else {
1079: typed = !prop.getTypeName().equals(
1080: cobj.getBoundClass().getClassName());
1081: }
1082: if ((hasobj && !prop.isThis()) || (!hasobj && typed)) {
1083: bind = unmarshalObjectBinding(ctx, cobj, contain,
1084: prop.getTypeName());
1085: icobj = bind;
1086: }
1087:
1088: // validate and configure reference to structure in context
1089: if (ctx.hasAttribute(URI_ATTRIBUTES, COMMON_USING)) {
1090: comp = unmarshalStructureRef(ctx, contain, name,
1091: prop, icobj);
1092: } else {
1093:
1094: // validate and configure actual binding definition
1095: DefinitionContext defc = contain
1096: .getDefinitionContext();
1097: IComponent top = bind;
1098:
1099: // check for optional label definition
1100: String label = ctx.attributeText(URI_ATTRIBUTES,
1101: COMMON_LABEL, null);
1102:
1103: // set load and store handlers for collection
1104: NestedCollection.CollectionLoad load = null;
1105: NestedCollection.CollectionStore store = null;
1106: String itype = null;
1107: if (coll) {
1108:
1109: // get any method names and type supplied by user
1110: String stname = ctx.attributeText(
1111: URI_ATTRIBUTES, COLLECTION_STOREMETHOD,
1112: null);
1113: String aname = ctx.attributeText(
1114: URI_ATTRIBUTES, COLLECTION_ADDMETHOD,
1115: null);
1116: String lname = ctx.attributeText(
1117: URI_ATTRIBUTES, COLLECTION_LOADMETHOD,
1118: null);
1119: String szname = ctx.attributeText(
1120: URI_ATTRIBUTES, COLLECTION_SIZEMETHOD,
1121: null);
1122: String iname = ctx.attributeText(
1123: URI_ATTRIBUTES, COLLECTION_ITERMETHOD,
1124: null);
1125: itype = ctx
1126: .attributeText(URI_ATTRIBUTES,
1127: COLLECTION_ITEMTYPE,
1128: "java.lang.Object");
1129:
1130: // verify combinations of attributes supplied
1131: if ((lname == null || szname == null)
1132: && !(lname == null && szname == null)) {
1133: ctx
1134: .throwStartTagException(COLLECTION_LOADMETHOD
1135: + " and "
1136: + COLLECTION_SIZEMETHOD
1137: + " attributes must be used together");
1138: }
1139: if (iname != null && lname != null) {
1140: ctx
1141: .throwStartTagException(COLLECTION_ITERMETHOD
1142: + " and "
1143: + COLLECTION_LOADMETHOD
1144: + " attributes cannot be used together");
1145: }
1146: if (aname != null && stname != null) {
1147: ctx
1148: .throwStartTagException(COLLECTION_ADDMETHOD
1149: + " and "
1150: + COLLECTION_STOREMETHOD
1151: + " attributes cannot be used together");
1152: }
1153:
1154: // set defaults based on collection type
1155: ClassFile cf = ClassCache.getClassFile(prop
1156: .getTypeName());
1157: if (cf.isSuperclass("java.util.Vector")
1158: || cf
1159: .isSuperclass("java.util.ArrayList")) {
1160: if (stname == null && aname == null) {
1161: aname = "add";
1162: }
1163: if (iname == null && lname == null) {
1164: lname = "get";
1165: szname = "size";
1166: }
1167: } else if (cf
1168: .isImplements("Ljava/util/Collection;")) {
1169: if (stname == null && aname == null) {
1170: aname = "add";
1171: }
1172: if (iname == null && lname == null) {
1173: iname = "iterator";
1174: }
1175: } else if (cf.isArray()) {
1176: String ptype = prop.getTypeName();
1177: itype = ptype.substring(0,
1178: ptype.length() - 2);
1179: }
1180:
1181: // check binding direction(s)
1182: BindingDefinition bdef = contain
1183: .getBindingRoot();
1184: boolean isdoub = "long".equals(itype)
1185: || "double".equals(itype);
1186: if (bdef.isInput()) {
1187:
1188: // define strategy for adding items to collection
1189: if (aname != null) {
1190: ClassItem meth = cf.getBestMethod(
1191: aname, null,
1192: new String[] { itype });
1193: if (meth == null) {
1194: ctx
1195: .throwStartTagException("Add method "
1196: + aname
1197: + " not found in collection type "
1198: + cf.getName());
1199: }
1200: boolean hasval = !"void".equals(meth
1201: .getTypeName());
1202: store = new NestedCollection.AddStore(
1203: meth, isdoub, hasval);
1204: } else if (stname != null) {
1205: ClassItem meth = cf.getBestMethod(
1206: stname, null, new String[] {
1207: "int", itype });
1208: if (meth == null) {
1209: ctx
1210: .throwStartTagException("Indexed store method "
1211: + stname
1212: + " not found in collection type "
1213: + cf.getName());
1214: }
1215: boolean hasval = !"void".equals(meth
1216: .getTypeName());
1217: store = new NestedCollection.IndexedStore(
1218: meth, isdoub, hasval);
1219: } else if (cf.isArray()) {
1220: store = new NestedCollection.ArrayStore(
1221: itype, isdoub);
1222: } else {
1223: ctx
1224: .throwStartTagException("Unknown collection "
1225: + "type with no add or store method defined");
1226: }
1227:
1228: }
1229: if (bdef.isOutput()) {
1230:
1231: // define strategy for loading items from collection
1232: if (lname != null) {
1233: ClassItem smeth = cf.getMethod(szname,
1234: "()I");
1235: if (smeth == null) {
1236: ctx
1237: .throwStartTagException("Size method "
1238: + szname
1239: + " not found in collection type "
1240: + cf.getName());
1241: }
1242: ClassItem lmeth = cf.getBestMethod(
1243: lname, itype,
1244: new String[] { "int" });
1245: if (lmeth == null) {
1246: ctx
1247: .throwStartTagException("Load method "
1248: + lname
1249: + " not found in collection type "
1250: + cf.getName());
1251: }
1252: load = new NestedCollection.IndexedLoad(
1253: smeth, isdoub, lmeth);
1254: } else if (iname != null) {
1255: String mname = "hasNext";
1256: String nname = "next";
1257: ClassItem meth = cf.getMethod(iname,
1258: "()Ljava/util/Iterator;");
1259: if (meth == null) {
1260: mname = "hasMoreElements";
1261: nname = "nextElement";
1262: meth = cf
1263: .getMethod(iname,
1264: "()Ljava/util/Enumeration;");
1265: if (meth == null) {
1266: ctx
1267: .throwStartTagException("Iterator method "
1268: + iname
1269: + " not found in collection type "
1270: + cf.getName());
1271: }
1272: }
1273: load = new NestedCollection.IteratorLoad(
1274: meth, isdoub,
1275: "java.util.Iterator." + mname,
1276: "java.util.Iterator." + nname);
1277: } else if (cf.isArray()) {
1278: load = new NestedCollection.ArrayLoad(
1279: itype, isdoub);
1280: } else {
1281: ctx
1282: .throwStartTagException("Unknown collection "
1283: + "type with no load method defined");
1284: }
1285: }
1286:
1287: }
1288:
1289: // unmarshal basics of nested structure
1290: NestedBase nest;
1291: boolean ordered = ctx.attributeBoolean(
1292: URI_ATTRIBUTES, COMMON_ORDERED, true);
1293: boolean flex = ctx.attributeBoolean(URI_ATTRIBUTES,
1294: COMMON_FLEXIBLE, false);
1295: boolean nillable = ctx.attributeBoolean(
1296: URI_ATTRIBUTES, COMMON_NILLABLE, false);
1297: if (nillable) {
1298: contain.getBindingRoot()
1299: .setSchemaInstanceUsed();
1300: }
1301: if (coll) {
1302:
1303: // create collection definition
1304: nest = new NestedCollection(contain, icobj,
1305: ordered, opt, flex, itype, load, store);
1306: nest.unmarshal(ctx);
1307: ctx.parsePastStartTag(URI_ELEMENTS,
1308: COLLECTION_ELEMENT);
1309:
1310: } else {
1311:
1312: // create structure definition
1313: boolean choice = ctx.attributeBoolean(
1314: URI_ATTRIBUTES, COMMON_CHOICE, false);
1315: boolean dupl = ctx.attributeBoolean(
1316: URI_ATTRIBUTES, COMMON_DUPLICATES,
1317: false);
1318: nest = new NestedStructure(contain, icobj,
1319: ordered, choice, flex, false, hasobj,
1320: dupl);
1321: nest.unmarshal(ctx);
1322: ctx.parsePastStartTag(URI_ELEMENTS,
1323: STRUCTURE_ELEMENT);
1324: }
1325:
1326: // unmarshal child bindings with optional label
1327: String ctype = (itype == null) ? "java.lang.Object"
1328: : itype;
1329: unmarshalFormats(ctx, nest.getDefinitionContext());
1330: unmarshalMappings(ctx, contain, null, uord);
1331: unmarshalStructureChildren(ctx, nest, icobj, coll
1332: | (implic && !hasobj), ctype);
1333: if (top == null) {
1334: top = nest;
1335: }
1336:
1337: // special check for structure wrapping value
1338: boolean impstruct = false;
1339: boolean childs = nest.hasContent();
1340: if (implic && !coll && childs) {
1341: ArrayList contents = nest.getContents();
1342: impstruct = true;
1343: for (int i = 0; i < contents.size(); i++) {
1344: if (!(contents.get(i) instanceof ValueChild)) {
1345: impstruct = false;
1346: break;
1347: } else {
1348: ValueChild vchild = (ValueChild) contents
1349: .get(i);
1350: if (!vchild.isImplicit()) {
1351: impstruct = false;
1352: break;
1353: }
1354: }
1355: }
1356: }
1357: if (impstruct) {
1358: comp = nest;
1359: nest.setObjectContext(cobj);
1360: if (name != null) {
1361: comp = new ElementWrapper(defc, name, comp,
1362: nillable);
1363: if (bind != null && implic) {
1364: if (!hasprop) {
1365: ArrayList contents = nest
1366: .getContents();
1367: impstruct = true;
1368: for (int i = 0; i < contents.size(); i++) {
1369: if (contents.get(i) instanceof ValueChild) {
1370: ValueChild vchild = (ValueChild) contents
1371: .get(i);
1372: vchild.switchProperty();
1373: }
1374: }
1375: }
1376: prop.setOptional(false);
1377: }
1378: }
1379: } else {
1380:
1381: // check for children defined
1382: boolean addref = false;
1383: if (!childs) {
1384: if (coll) {
1385:
1386: // add mapping as only child
1387: if (ctype.equals("java.lang.Object")) {
1388: nest
1389: .addComponent(new DirectGeneric(
1390: nest, null));
1391: } else {
1392: nest
1393: .addComponent(new MappingReference(
1394: contain,
1395: new PropertyDefinition(
1396: ctype,
1397: cobj, false),
1398: ctype, null, null,
1399: icobj, null, true,
1400: false));
1401: }
1402: childs = true;
1403:
1404: } else if (name != null) {
1405:
1406: // must be abstract mappping reference, create child
1407: addref = true;
1408:
1409: }
1410: }
1411:
1412: // handle nested children
1413: comp = top;
1414: if (childs || addref) {
1415:
1416: // define component property wrapping object binding
1417: boolean optprop = hasprop
1418: && prop.isOptional();
1419: if (bind != null) {
1420: boolean skip = name != null && optprop;
1421: comp = new ComponentProperty(prop,
1422: comp, skip);
1423: bind.setWrappedComponent(nest);
1424: }
1425:
1426: // create reference to mapping as special case
1427: // this allows structure with name but no children to
1428: // use abstract mapping
1429: if (addref) {
1430: PropertyDefinition this prop = new PropertyDefinition(
1431: bind, false);
1432: nest.addComponent(new MappingReference(
1433: nest, this prop, comp.getType(),
1434: null, null, icobj, null, false,
1435: false));
1436: }
1437: if (name != null) {
1438: comp = new ElementWrapper(defc, name,
1439: comp, nillable);
1440: if (bind != null && implic) {
1441: if (!hasprop) {
1442: ((ElementWrapper) comp)
1443: .setDirect(true);
1444: }
1445: prop.setOptional(false);
1446: }
1447: if (optprop) {
1448: ((ElementWrapper) comp)
1449: .setOptionalNormal(true);
1450: boolean isobj = bind != null;
1451: ((ElementWrapper) comp)
1452: .setStructureObject(isobj);
1453: ((ElementWrapper) comp)
1454: .setDirect(isobj);
1455: comp = new OptionalStructureWrapper(
1456: comp, prop, isobj);
1457: prop.setOptional(false);
1458: } else if (opt && !implic) {
1459: ((ElementWrapper) comp)
1460: .setOptionalNormal(true);
1461: comp = new OptionalStructureWrapper(
1462: comp, prop, false);
1463: prop.setOptional(false);
1464: }
1465: }
1466:
1467: } else {
1468:
1469: // treat as mapping, with either type or generic
1470: String type = prop.getTypeName();
1471: if (prop.equals("java.lang.Object")) {
1472: comp = new ComponentProperty(
1473: prop,
1474: new DirectGeneric(contain, null),
1475: false);
1476: } else {
1477: comp = new MappingReference(contain,
1478: prop, type, null, null, icobj,
1479: name, false, false);
1480: }
1481: }
1482: }
1483:
1484: // set object binding as definition for label
1485: if (label != null) {
1486: defc.addNamedStructure(label, top);
1487: }
1488: }
1489: }
1490:
1491: } else {
1492:
1493: // structure with no separate object, verify no forbidden attributes
1494: if (isObjectBinding(ctx)) {
1495: ctx.throwStartTagException("Object attributes not "
1496: + "allowed without property definition");
1497: } else if (isDirectObject(ctx)) {
1498: ctx
1499: .throwStartTagException("Marshaller and unmarshaller not "
1500: + "allowed without property definition");
1501: }
1502:
1503: // check for reference to structure defined elsewhere
1504: if (mapping) {
1505:
1506: // handle "this" reference as anonymous property
1507: PropertyDefinition prop = new PropertyDefinition(cobj,
1508: opt);
1509:
1510: // handle reference to defined mapping
1511: comp = unmarshalMappingRef(ctx, contain, cobj, prop,
1512: name);
1513: implic = true;
1514:
1515: } else if (ctx.hasAttribute(URI_ATTRIBUTES, COMMON_USING)) {
1516:
1517: // make sure forbidden attribute not used
1518: if (ctx.hasAttribute(URI_ATTRIBUTES, COMMON_ORDERED)) {
1519: ctx.throwStartTagException(COMMON_ORDERED
1520: + " attribute " + " not allowed with "
1521: + COMMON_USING + " attribute");
1522: }
1523:
1524: // validate and configure reference to structure in context
1525: comp = unmarshalStructureRef(ctx, contain, name, null,
1526: cobj);
1527:
1528: } else {
1529:
1530: // unmarshal children as nested structure
1531: boolean ordered = ctx.attributeBoolean(URI_ATTRIBUTES,
1532: COMMON_ORDERED, true);
1533: boolean choice = ctx.attributeBoolean(URI_ATTRIBUTES,
1534: COMMON_CHOICE, false);
1535: boolean flex = ctx.attributeBoolean(URI_ATTRIBUTES,
1536: COMMON_FLEXIBLE, false);
1537: boolean dupl = ctx.attributeBoolean(URI_ATTRIBUTES,
1538: COMMON_DUPLICATES, false);
1539: NestedStructure nest = new NestedStructure(contain,
1540: cobj, ordered, choice, flex, false, hasprop,
1541: dupl);
1542: nest.unmarshal(ctx);
1543:
1544: // unmarshal child bindings with optional label
1545: String label = ctx.attributeText(URI_ATTRIBUTES,
1546: COMMON_LABEL, null);
1547: ctx.parsePastStartTag(URI_ELEMENTS, STRUCTURE_ELEMENT);
1548: unmarshalFormats(ctx, nest.getDefinitionContext());
1549: unmarshalMappings(ctx, contain, null, uord);
1550: unmarshalStructureChildren(ctx, nest, cobj, false,
1551: "java.lang.Object");
1552:
1553: // check for children defined
1554: DefinitionContext defc = contain.getDefinitionContext();
1555: if (nest.hasContent()) {
1556:
1557: // build structure to access children or with elment wrapper
1558: if (name == null) {
1559: comp = nest;
1560: } else {
1561: comp = new ElementWrapper(defc, name, nest,
1562: false);
1563: if (opt) {
1564: ((ElementWrapper) comp)
1565: .setOptionalNormal(true);
1566: ((ElementWrapper) comp)
1567: .setStructureObject(true);
1568: }
1569: }
1570: if (label != null) {
1571: defc.addNamedStructure(label, nest);
1572: }
1573:
1574: } else {
1575:
1576: // make sure there's a name defined
1577: if (name == null) {
1578: ctx
1579: .throwException("Property, name, or child component required");
1580: }
1581:
1582: // treat as throwaway portion of document
1583: comp = new ElementWrapper(defc, name, null, false);
1584: if (opt) {
1585: ((ElementWrapper) comp)
1586: .setOptionalIgnored(true);
1587: }
1588:
1589: }
1590: }
1591: }
1592:
1593: // finish by parsing past end tag
1594: ctx.parsePastEndTag(URI_ELEMENTS, coll ? COLLECTION_ELEMENT
1595: : STRUCTURE_ELEMENT);
1596: return comp;
1597: }
1598:
1599: /**
1600: * Unmarshal mapping definition. This handles all combinations of attributes
1601: * on the start tag, generating the appropriate structure of nested
1602: * components and other classes to represent the binding information within
1603: * the current element. This must be called with the parse positioned at the
1604: * start tag of the element to be unmarshalled.
1605: *
1606: * @param ctx unmarshalling context information
1607: * @param parent containing binding definition structure
1608: * @param nss extra namespaces to be included in this mapping definition
1609: * (may be <code>null</code>)
1610: * @param uord container is unordered structure flag
1611: * @return mapping definition constructed from binding
1612: * @throws JiBXException if error in unmarshalling
1613: */
1614:
1615: public static IMapping unmarshalMapping(UnmarshallingContext ctx,
1616: IContainer parent, ArrayList nss, boolean uord)
1617: throws JiBXException {
1618:
1619: // first check for an abstract mapping
1620: boolean abs = ctx.attributeBoolean(URI_ATTRIBUTES,
1621: MAPPING_ABSTRACT, false);
1622: String type = ctx.attributeText(URI_ATTRIBUTES, MAPPING_CLASS);
1623:
1624: // get name definition if supplied
1625: NameDefinition name = null;
1626: if (isNamePresent(ctx)) {
1627: name = unmarshalName(ctx, false);
1628: }
1629:
1630: // get type name information
1631: String text = ctx.attributeText(URI_ATTRIBUTES,
1632: MAPPING_TYPENAME, null);
1633: String tname = null;
1634: if (text != null) {
1635: tname = QName.deserialize(text, ctx).toString();
1636: }
1637:
1638: // check if using direct object marshalling and unmarshalling
1639: IMapping mapping;
1640: if (isDirectObject(ctx)) {
1641:
1642: // check for definition context needed
1643: DefinitionContext defc = null;
1644: if (nss != null && nss.size() > 0) {
1645:
1646: // add all outer namespaces to context
1647: defc = new DefinitionContext(parent);
1648: if (nss != null && nss.size() > 0) {
1649: for (int j = 0; j < nss.size(); j++) {
1650: defc.addNamespace((NamespaceDefinition) nss
1651: .get(j));
1652: }
1653: }
1654: }
1655:
1656: // validate and configure direct marshalling and unmarshalling
1657: int slot = parent.getBindingRoot()
1658: .getMappedClassIndex(type);
1659: mapping = new MappingDirect(parent, type, tname,
1660: unmarshalDirectObj(ctx, type, parent, defc, slot,
1661: name), abs);
1662:
1663: } else {
1664:
1665: // not direct mapping, check for missing required name
1666: if (!abs && name == null) {
1667: ctx
1668: .throwStartTagException("Non-abstract mapping must define "
1669: + "an element name");
1670: }
1671:
1672: // check for optional definitions
1673: String label = ctx.attributeText(URI_ATTRIBUTES,
1674: COMMON_LABEL, null);
1675:
1676: // create definition context for namespaces and formats
1677: String base = ctx.attributeText(URI_ATTRIBUTES,
1678: MAPPING_EXTENDS, null);
1679: ObjectBinding bind = unmarshalObjectBinding(ctx, null,
1680: parent, type);
1681: boolean ordered = ctx.attributeBoolean(URI_ATTRIBUTES,
1682: COMMON_ORDERED, true);
1683: boolean choice = ctx.attributeBoolean(URI_ATTRIBUTES,
1684: COMMON_CHOICE, false);
1685: boolean flex = ctx.attributeBoolean(URI_ATTRIBUTES,
1686: COMMON_FLEXIBLE, false);
1687: boolean nillable = ctx.attributeBoolean(URI_ATTRIBUTES,
1688: COMMON_NILLABLE, false);
1689: if (nillable) {
1690: parent.getBindingRoot().setSchemaInstanceUsed();
1691: }
1692: boolean dupl = ctx.attributeBoolean(URI_ATTRIBUTES,
1693: COMMON_DUPLICATES, false);
1694: NestedStructure nest = new NestedStructure(parent, bind,
1695: ordered, choice, flex, true, true, dupl);
1696: nest.unmarshal(ctx);
1697:
1698: // add all outer namespaces to context
1699: DefinitionContext defc = nest.getDefinitionContext();
1700: if (nss != null && nss.size() > 0) {
1701: for (int j = 0; j < nss.size(); j++) {
1702: defc.addNamespace((NamespaceDefinition) nss.get(j));
1703: }
1704: }
1705:
1706: // unmarshal all contained binding information
1707: ctx.parsePastStartTag(URI_ELEMENTS, MAPPING_ELEMENT);
1708: unmarshalNamespaces(ctx, nest.getDefinitionContext());
1709: unmarshalFormats(ctx, nest.getDefinitionContext());
1710: unmarshalMappings(ctx, nest, null, uord);
1711: unmarshalStructureChildren(ctx, nest, bind, false,
1712: "java.lang.Object");
1713:
1714: // validate and configure actual binding definition
1715: bind.setWrappedComponent(nest);
1716: mapping = new MappingDefinition(parent, nest
1717: .getDefinitionContext(), type, name, tname, abs,
1718: base, bind, nillable);
1719:
1720: // set label if defined
1721: if (label != null) {
1722: defc.addNamedStructure(label, bind);
1723: }
1724: }
1725:
1726: // finish by adding mapping and parsing past end tag
1727: parent.getDefinitionContext().addMapping(mapping);
1728: ctx.parsePastEndTag(URI_ELEMENTS, MAPPING_ELEMENT);
1729: return mapping;
1730: }
1731:
1732: /**
1733: * Unmarshal included binding. This handles the actual include element along
1734: * with the actual included binding. The current implementation allows for
1735: * nested includes, but requires that all the included bindings use
1736: * compatible settings for the attributes of the root element, and only
1737: * allows mapping elements as children of the included bindings (no
1738: * namespace or format elements).
1739: *
1740: * @param ctx unmarshalling context information
1741: * @param bdef binding defintion at root of includes
1742: * @param root base URL for binding, or <code>null</code> if unknown
1743: * @param nslist list of namespaces defined
1744: * @param paths set of binding paths processed
1745: * @throws JiBXException if error in unmarshalling
1746: */
1747:
1748: public static void unmarshalInclude(UnmarshallingContext ctx,
1749: BindingDefinition bdef, URL root, ArrayList nslist,
1750: HashSet paths) throws JiBXException {
1751:
1752: // make sure path hasn't already been processed
1753: ctx.parseToStartTag(URI_ELEMENTS, INCLUDE_ELEMENT);
1754: String path = ctx.attributeText(URI_ATTRIBUTES, INCLUDE_PATH);
1755: URL url;
1756: try {
1757: if (root == null) {
1758: url = new URL(path);
1759: } else {
1760: url = new URL(root, path);
1761: }
1762: } catch (MalformedURLException e) {
1763: throw new JiBXException("Unable to handle include path "
1764: + path, e);
1765: }
1766: String fpath = url.toExternalForm();
1767: if (paths.add(fpath)) {
1768: try {
1769:
1770: // access the included binding as input stream
1771: UnmarshallingContext ictx = new UnmarshallingContext();
1772: ictx.setDocument(url.openStream(), null);
1773:
1774: // unmarshal namespaces (to apply to these mappings, only)
1775: ictx.parseToStartTag(URI_ELEMENTS, BINDING_ELEMENT);
1776: ictx.parsePastStartTag(URI_ELEMENTS, BINDING_ELEMENT);
1777: ArrayList nss = new ArrayList(nslist);
1778: while (ictx.isAt(URI_ELEMENTS, NAMESPACE_ELEMENT)) {
1779: nss.add(unmarshalNamespace(ictx));
1780: }
1781:
1782: // process any format definitions (for global context)
1783: unmarshalFormats(ictx, bdef.getDefinitionContext());
1784:
1785: // check for nested includes
1786: while (ictx.isAt(URI_ELEMENTS, INCLUDE_ELEMENT)) {
1787: unmarshalInclude(ictx, bdef, url, nss, paths);
1788: }
1789:
1790: // process all mappings defined in included binding
1791: unmarshalMappings(ictx, bdef, nss, false);
1792:
1793: } catch (IOException e) {
1794: throw new JiBXException(
1795: "Error accessing included binding with path "
1796: + path, e);
1797: }
1798: }
1799:
1800: // finish by skipping past end of tag in main binding
1801: ctx.parsePastEndTag(URI_ELEMENTS, INCLUDE_ELEMENT);
1802: }
1803:
1804: /**
1805: * Unmarshal binding definition. This handles the entire binding definition
1806: * document.
1807: *
1808: * @param ctx unmarshalling context information
1809: * @param name default name for binding
1810: * @param root base URL for binding, or <code>null</code> if unknown
1811: * @throws JiBXException if error in unmarshalling
1812: */
1813:
1814: public static BindingDefinition unmarshalBindingDefinition(
1815: UnmarshallingContext ctx, String name, URL root)
1816: throws JiBXException {
1817:
1818: // start by reading optional binding name
1819: ctx.parseToStartTag(URI_ELEMENTS, BINDING_ELEMENT);
1820: name = ctx.attributeText(URI_ATTRIBUTES, BINDING_NAME, name);
1821:
1822: // set the binding direction flags
1823: int dir = ctx.attributeEnumeration(URI_ATTRIBUTES,
1824: BINDING_DIRECTION, BINDINGDIR_NAMES, BINDINGDIR_NUMS,
1825: DIRECTION_BOTH);
1826: boolean ibind = dir == DIRECTION_BOTH || dir == DIRECTION_INPUT;
1827: boolean obind = dir == DIRECTION_BOTH
1828: || dir == DIRECTION_OUTPUT;
1829:
1830: // read other attribute values
1831: String tpack = ctx.attributeText(URI_ATTRIBUTES,
1832: BINDING_PACKAGE, null);
1833: boolean glob = ctx.attributeBoolean(URI_ATTRIBUTES,
1834: BINDING_GLOBALID, true);
1835: boolean forward = ctx.attributeBoolean(URI_ATTRIBUTES,
1836: BINDING_FORWARDS, true);
1837: boolean track = ctx.attributeBoolean(URI_ATTRIBUTES,
1838: BINDING_TRACKING, false);
1839: boolean force = ctx.attributeBoolean(URI_ATTRIBUTES,
1840: BINDING_FORCE, false);
1841:
1842: // create actual binding instance
1843: BindingDefinition bdef = new BindingDefinition(name, ibind,
1844: obind, tpack, glob, forward, track, force);
1845: bdef.unmarshal(ctx);
1846:
1847: // unmarshal namespaces and formats defined under root
1848: ctx.parsePastStartTag(URI_ELEMENTS, BINDING_ELEMENT);
1849: ArrayList nss = new ArrayList();
1850: while (ctx.isAt(URI_ELEMENTS, NAMESPACE_ELEMENT)) {
1851: nss.add(unmarshalNamespace(ctx));
1852: }
1853: unmarshalFormats(ctx, bdef.getDefinitionContext());
1854:
1855: // process any included binding definitions
1856: HashSet paths = new HashSet();
1857: if (root != null) {
1858: paths.add(root.toExternalForm());
1859: }
1860: while (ctx.isAt(URI_ELEMENTS, INCLUDE_ELEMENT)) {
1861: unmarshalInclude(ctx, bdef, root, nss, paths);
1862: }
1863:
1864: // finish with common handling for elements which can be nested
1865: unmarshalMappings(ctx, bdef, nss, false);
1866: ctx.parsePastEndTag(URI_ELEMENTS, BINDING_ELEMENT);
1867: return bdef;
1868: }
1869:
1870: /**
1871: * Base class for containers. This just handles unmarshalling and checking
1872: * the values of attributes used by all containers. The container class
1873: * should set the appropriate default values for all these attributes in its
1874: * constructor, using <code>-1</code> (for <code>int</code> values) and
1875: * <code>null</code> (for <code>String</code> values) if the default is to
1876: * simply use setting inherited from a containing component. The binding
1877: * definition root object must always define actual values as the defaults,
1878: * since otherwise the code will fall off the end of the chain of ancestors.
1879: */
1880:
1881: /*package*/static class ContainerBase {
1882:
1883: /** Containing binding component. */
1884: protected IContainer m_container;
1885:
1886: /** Default style for value expression. */
1887: protected int m_styleDefault;
1888:
1889: /** Auto-link style for default mappings. */
1890: protected int m_autoLink;
1891:
1892: /** Access level for default mappings. */
1893: protected int m_accessLevel;
1894:
1895: /** Prefix text to be stripped from names. */
1896: protected String m_stripPrefix;
1897:
1898: /** Suffix text to be stripped from names. */
1899: protected String m_stripSuffix;
1900:
1901: /** Style used for generating element or attribute names. */
1902: protected int m_nameStyle;
1903:
1904: /**
1905: * Constructor.
1906: *
1907: * @param parent containing binding definition context
1908: */
1909:
1910: public ContainerBase(IContainer parent) {
1911: m_container = parent;
1912: }
1913:
1914: /**
1915: * Unmarshal common container attributes.
1916: *
1917: * @param ctx unmarshalling context information
1918: * @throws JiBXException if error in unmarshalling
1919: */
1920:
1921: public void unmarshal(UnmarshallingContext ctx)
1922: throws JiBXException {
1923: m_styleDefault = ctx.attributeEnumeration(URI_ATTRIBUTES,
1924: COMMON_STYLE, CONTAINING_STYLE_NAMES,
1925: CONTAINING_STYLE_NUMS, m_styleDefault);
1926: m_autoLink = ctx.attributeEnumeration(URI_ATTRIBUTES,
1927: COMMON_AUTOLINK, AUTO_LINK_NAMES, AUTO_LINK_NUMS,
1928: m_autoLink);
1929: m_accessLevel = ctx.attributeEnumeration(URI_ATTRIBUTES,
1930: COMMON_ACCESSLEVEL, ACCESS_LEVEL_NAMES,
1931: ACCESS_LEVEL_NUMS, m_accessLevel);
1932: m_stripPrefix = ctx.attributeText(URI_ATTRIBUTES,
1933: COMMON_STRIPPREFIX, m_stripPrefix);
1934: m_stripSuffix = ctx.attributeText(URI_ATTRIBUTES,
1935: COMMON_STRIPSUFFIX, m_stripSuffix);
1936: m_nameStyle = ctx.attributeEnumeration(URI_ATTRIBUTES,
1937: COMMON_NAMESTYLE, NAME_GENERATE_NAMES,
1938: NAME_GENERATE_NUMS, m_nameStyle);
1939: }
1940:
1941: //
1942: // IContainer interface method definitions (partial list)
1943:
1944: public int getStyleDefault() {
1945: if (m_styleDefault >= 0) {
1946: return m_styleDefault;
1947: } else {
1948: return m_container.getStyleDefault();
1949: }
1950: }
1951: }
1952: }
|