0001: /*
0002: * GeoTools - OpenSource mapping toolkit
0003: * http://geotools.org
0004: * (C) 2004-2006, GeoTools Project Managment Committee (PMC)
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation;
0009: * version 2.1 of the License.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: */
0016: package org.geotools.xml.handlers.xsi;
0017:
0018: import java.io.IOException;
0019: import java.net.URI;
0020: import java.util.Arrays;
0021: import java.util.HashSet;
0022: import java.util.Iterator;
0023: import java.util.LinkedList;
0024: import java.util.List;
0025: import java.util.Map;
0026:
0027: import javax.naming.OperationNotSupportedException;
0028:
0029: import org.geotools.xml.PrintHandler;
0030: import org.geotools.xml.XSIElementHandler;
0031: import org.geotools.xml.schema.All;
0032: import org.geotools.xml.schema.Attribute;
0033: import org.geotools.xml.schema.AttributeGroup;
0034: import org.geotools.xml.schema.Choice;
0035: import org.geotools.xml.schema.ComplexType;
0036: import org.geotools.xml.schema.Element;
0037: import org.geotools.xml.schema.ElementGrouping;
0038: import org.geotools.xml.schema.ElementValue;
0039: import org.geotools.xml.schema.Group;
0040: import org.geotools.xml.schema.Sequence;
0041: import org.geotools.xml.schema.SimpleType;
0042: import org.geotools.xml.schema.Type;
0043: import org.geotools.xml.schema.impl.SimpleTypeGT;
0044: import org.xml.sax.Attributes;
0045: import org.xml.sax.SAXException;
0046: import org.xml.sax.SAXNotRecognizedException;
0047: import org.xml.sax.SAXNotSupportedException;
0048:
0049: /**
0050: * ComplexTypeHandler purpose.
0051: *
0052: * <p>
0053: * Represents a ComplexType element
0054: * </p>
0055: * <p>
0056: * When a specific method of encoding is not specified then the following output will be returned:
0057: *
0058: * ElementValue[]{(null,Attributes),(Element,Value)*,(null,String)?}
0059: * Where the last element will be included iff there is child text.
0060: * </p>
0061: *
0062: * @author dzwiers, Refractions Research, Inc. http://www.refractions.net
0063: * @author $Author:$ (last modification)
0064: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/xml/src/main/java/org/geotools/xml/handlers/xsi/ComplexTypeHandler.java $
0065: * @version $Id: ComplexTypeHandler.java 22546 2006-11-02 06:47:55Z jgarnett $
0066: */
0067: public class ComplexTypeHandler extends XSIElementHandler {
0068: private static final long serialVersionUID = -2001189506633342497L;
0069:
0070: /** 'complexType' */
0071: public final static String LOCALNAME = "complexType";
0072:
0073: /** ALL */
0074: public static final int ALL = 128;
0075: private static int offset = 0;
0076: private String id;
0077: private String name;
0078: private boolean abstracT;
0079: private boolean mixed;
0080: private int block;
0081: private int finaL;
0082: private List attrDecs = new LinkedList(); // attr or attrGrps
0083: private AnyAttributeHandler anyAttribute;
0084: private Object child; //should be either a ComplexType or a SimpleType,
0085: private int hashCodeOffset = getOffset();
0086: private ComplexType cache = null;
0087:
0088: /*
0089: * helper for hashCode();
0090: */
0091: private static int getOffset() {
0092: return offset++;
0093: }
0094:
0095: /**
0096: * @see java.lang.Object#hashCode()
0097: */
0098: public int hashCode() {
0099: return (LOCALNAME.hashCode()
0100: * ((id == null) ? 1 : id.hashCode())
0101: * ((attrDecs == null) ? 1 : attrDecs.hashCode()) * ((name == null) ? 1
0102: : name.hashCode()))
0103: + hashCodeOffset;
0104: }
0105:
0106: /**
0107: * @see org.geotools.xml.XSIElementHandler#getHandler(java.lang.String,
0108: * java.lang.String)
0109: */
0110: public XSIElementHandler getHandler(String namespaceURI,
0111: String localName) throws SAXException {
0112: if (SchemaHandler.namespaceURI.equalsIgnoreCase(namespaceURI)) {
0113: // child types
0114: //
0115: // group
0116: if (GroupHandler.LOCALNAME.equalsIgnoreCase(localName)) {
0117: GroupHandler sth = new GroupHandler();
0118:
0119: if (child == null) {
0120: child = sth;
0121: } else {
0122: throw new SAXNotRecognizedException(LOCALNAME
0123: + " may only have one child declaration.");
0124: }
0125:
0126: return sth;
0127: }
0128:
0129: // all
0130: if (AllHandler.LOCALNAME.equalsIgnoreCase(localName)) {
0131: AllHandler sth = new AllHandler();
0132:
0133: if (child == null) {
0134: child = sth;
0135: } else {
0136: throw new SAXNotRecognizedException(LOCALNAME
0137: + " may only have one child declaration.");
0138: }
0139:
0140: return sth;
0141: }
0142:
0143: // choice
0144: if (ChoiceHandler.LOCALNAME.equalsIgnoreCase(localName)) {
0145: ChoiceHandler sth = new ChoiceHandler();
0146:
0147: if (child == null) {
0148: child = sth;
0149: } else {
0150: throw new SAXNotRecognizedException(LOCALNAME
0151: + " may only have one child declaration.");
0152: }
0153:
0154: return sth;
0155: }
0156:
0157: // sequence
0158: if (SequenceHandler.LOCALNAME.equalsIgnoreCase(localName)) {
0159: SequenceHandler sth = new SequenceHandler();
0160:
0161: if (child == null) {
0162: child = sth;
0163: } else {
0164: throw new SAXNotRecognizedException(LOCALNAME
0165: + " may only have one child declaration.");
0166: }
0167:
0168: return sth;
0169: }
0170:
0171: // attribute
0172: if (AttributeHandler.LOCALNAME.equalsIgnoreCase(localName)) {
0173: if (attrDecs == null) {
0174: attrDecs = new LinkedList();
0175: }
0176:
0177: AttributeHandler ah = new AttributeHandler();
0178: attrDecs.add(ah);
0179:
0180: return ah;
0181: }
0182:
0183: // attributeGroup
0184: if (AttributeGroupHandler.LOCALNAME
0185: .equalsIgnoreCase(localName)) {
0186: if (attrDecs == null) {
0187: attrDecs = new LinkedList();
0188: }
0189:
0190: AttributeGroupHandler ah = new AttributeGroupHandler();
0191: attrDecs.add(ah);
0192:
0193: return ah;
0194: }
0195:
0196: // anyAttribute
0197: if (AnyAttributeHandler.LOCALNAME
0198: .equalsIgnoreCase(localName)) {
0199: AnyAttributeHandler sth = new AnyAttributeHandler();
0200:
0201: if (anyAttribute == null) {
0202: anyAttribute = sth;
0203: } else {
0204: throw new SAXNotRecognizedException(LOCALNAME
0205: + " may only have one child declaration.");
0206: }
0207:
0208: return sth;
0209: }
0210:
0211: // complexContent
0212: if (ComplexContentHandler.LOCALNAME
0213: .equalsIgnoreCase(localName)) {
0214: ComplexContentHandler sth = new ComplexContentHandler();
0215:
0216: if (child == null) {
0217: child = sth;
0218: } else {
0219: throw new SAXNotRecognizedException(LOCALNAME
0220: + " may only have one child declaration.");
0221: }
0222:
0223: return sth;
0224: }
0225:
0226: // simpleContent
0227: if (SimpleContentHandler.LOCALNAME
0228: .equalsIgnoreCase(localName)) {
0229: SimpleContentHandler sth = new SimpleContentHandler();
0230:
0231: if (child == null) {
0232: child = sth;
0233: } else {
0234: throw new SAXNotRecognizedException(LOCALNAME
0235: + " may only have one child declaration.");
0236: }
0237:
0238: return sth;
0239: }
0240: }
0241:
0242: return null;
0243: }
0244:
0245: /**
0246: * @see org.geotools.xml.XSIElementHandler#startElement(java.lang.String,
0247: * java.lang.String, org.xml.sax.Attributes)
0248: */
0249: public void startElement(String namespaceURI, String localName,
0250: Attributes atts) throws SAXException {
0251: id = atts.getValue("", "id");
0252:
0253: if (id == null) {
0254: id = atts.getValue(namespaceURI, "id");
0255: }
0256:
0257: name = atts.getValue("", "name");
0258:
0259: if (name == null) {
0260: name = atts.getValue(namespaceURI, "name");
0261: }
0262:
0263: String abstracT1 = atts.getValue("", "abstract");
0264:
0265: if (abstracT1 == null) {
0266: abstracT1 = atts.getValue(namespaceURI, "abstract");
0267: }
0268:
0269: if ((abstracT1 == null) || "".equals(abstracT1)) {
0270: this .abstracT = false;
0271: } else {
0272: this .abstracT = Boolean.valueOf(abstracT1).booleanValue();
0273: }
0274:
0275: String block1 = atts.getValue("", "block");
0276:
0277: if (block1 == null) {
0278: block1 = atts.getValue(namespaceURI, "block");
0279: }
0280:
0281: this .block = ComplexTypeHandler.findBlock(block1);
0282:
0283: String finaL1 = atts.getValue("", "final");
0284:
0285: if (finaL1 == null) {
0286: finaL1 = atts.getValue(namespaceURI, "final");
0287: }
0288:
0289: this .finaL = ComplexTypeHandler.findFinal(finaL1);
0290:
0291: String mixed1 = atts.getValue("", "mixed");
0292:
0293: if (mixed1 == null) {
0294: mixed1 = atts.getValue(namespaceURI, "mixed");
0295: }
0296:
0297: if ((mixed1 == null) || "".equalsIgnoreCase(mixed1)) {
0298: this .mixed = false;
0299: } else {
0300: this .mixed = Boolean.getBoolean(mixed1);
0301: }
0302:
0303: this .block = findBlock(block1);
0304: this .finaL = findFinal(finaL1);
0305: }
0306:
0307: /**
0308: * @see org.geotools.xml.XSIElementHandler#getLocalName()
0309: */
0310: public String getLocalName() {
0311: return LOCALNAME;
0312: }
0313:
0314: // Group, Sequence, All Choice
0315:
0316: /**
0317: * <p>
0318: * Converts a 'block' attribute value into an int mask
0319: * </p>
0320: *
0321: * @param block block
0322: *
0323: * @return int
0324: *
0325: * @throws SAXException
0326: */
0327: public static int findBlock(String block) throws SAXException {
0328: if ((block == null) || "".equalsIgnoreCase(block)) {
0329: return DEFAULT;
0330: }
0331:
0332: if ("extension".equalsIgnoreCase(block)) {
0333: return EXTENSION;
0334: }
0335:
0336: if ("restriction".equalsIgnoreCase(block)) {
0337: return RESTRICTION;
0338: }
0339:
0340: if ("#all".equalsIgnoreCase(block)) {
0341: return ALL;
0342: }
0343:
0344: throw new SAXException("Unknown Block Type: '" + block + "'");
0345: }
0346:
0347: /**
0348: * <p>
0349: * Reverses the translation from mask to String
0350: * </p>
0351: *
0352: * @param block
0353: *
0354: */
0355: public static String writeBlock(int block) {
0356: switch (block) {
0357: case EXTENSION:
0358: return "extension";
0359:
0360: case RESTRICTION:
0361: return "restriction";
0362:
0363: case ALL:
0364: return "#all";
0365:
0366: default:
0367: return "";
0368: }
0369: }
0370:
0371: /**
0372: * <p>
0373: * Converts a 'final' attribute value to an int mask
0374: * </p>
0375: *
0376: * @param finaL
0377: *
0378: *
0379: * @throws SAXException
0380: */
0381: public static int findFinal(String finaL) throws SAXException {
0382: try {
0383: return findBlock(finaL); // same enum
0384: } catch (SAXException e) {
0385: throw new SAXException("Unknown Final Type: '" + finaL
0386: + "'");
0387: }
0388: }
0389:
0390: /**
0391: * <p>
0392: * reverses the conversion of an int mask representing the 'final'
0393: * attribute to String
0394: * </p>
0395: *
0396: * @param finaL
0397: *
0398: */
0399: public static String writeFinal(int finaL) {
0400: return writeBlock(finaL); // same enum
0401: }
0402:
0403: /**
0404: * <p>
0405: * returns the complexType's name
0406: * </p>
0407: *
0408: */
0409: public String getName() {
0410: return name;
0411: }
0412:
0413: /**
0414: * <p>
0415: * compresses the inheritance tree, caching a more efficient copy.
0416: * </p>
0417: *
0418: * @param parent
0419: *
0420: *
0421: * @throws SAXException
0422: * @throws NullPointerException
0423: */
0424: protected ComplexType compress(SchemaHandler parent)
0425: throws SAXException {
0426: logger.fine("Start compressing ComplexType " + getName());
0427:
0428: if (cache != null) {
0429: return cache;
0430: }
0431:
0432: DefaultComplexType dct = new DefaultComplexType();
0433: dct.abstracT = abstracT;
0434: dct.anyAttributeNameSpace = (anyAttribute != null) ? anyAttribute
0435: .getNamespace()
0436: : null;
0437:
0438: HashSet attr = new HashSet();
0439:
0440: if (child instanceof SimpleContentHandler
0441: || child instanceof ComplexContentHandler) {
0442: if (child instanceof SimpleContentHandler) {
0443: logger.finest("SimpleContentHandler");
0444:
0445: SimpleContentHandler sch = (SimpleContentHandler) child;
0446:
0447: if (sch.getChild() instanceof ExtensionHandler) {
0448: ExtensionHandler ext = (ExtensionHandler) sch
0449: .getChild();
0450:
0451: // attributes
0452: if (ext.getAttributeDeclarations() != null) {
0453: Iterator it = ext.getAttributeDeclarations()
0454: .iterator();
0455:
0456: while (it.hasNext()) {
0457: Object o = it.next();
0458:
0459: if (o instanceof AttributeHandler) {
0460: AttributeHandler ah = (AttributeHandler) o;
0461: attr.add(ah.compress(parent));
0462: } else {
0463: AttributeGroupHandler agh = (AttributeGroupHandler) o;
0464: AttributeGroup ag = agh
0465: .compress(parent);
0466: attr.addAll(Arrays.asList(ag
0467: .getAttributes()));
0468: }
0469: }
0470: }
0471:
0472: SimpleType st;
0473:
0474: if ((ext.getBase() == null)
0475: || ext.getBase().equalsIgnoreCase("")) {
0476: st = ((SimpleTypeHandler) ext.getChild())
0477: .compress(parent);
0478: } else {
0479: st = parent.lookUpSimpleType(ext.getBase());
0480: }
0481:
0482: dct.parent = st;
0483: dct.simple = true;
0484: } else {
0485: // restriction
0486: RestrictionHandler rest = (RestrictionHandler) sch
0487: .getChild();
0488:
0489: // attributes
0490: if (rest.getAttributeDeclarations() != null) {
0491: Iterator it = rest.getAttributeDeclarations()
0492: .iterator();
0493:
0494: while (it.hasNext()) {
0495: Object o = it.next();
0496:
0497: if (o instanceof AttributeHandler) {
0498: AttributeHandler ah = (AttributeHandler) o;
0499: attr.add(ah.compress(parent));
0500: } else {
0501: AttributeGroupHandler agh = (AttributeGroupHandler) o;
0502: AttributeGroup ag = agh
0503: .compress(parent);
0504: attr.addAll(Arrays.asList(ag
0505: .getAttributes()));
0506: }
0507: }
0508: }
0509:
0510: SimpleType st = new SimpleTypeGT(id, name, parent
0511: .getTargetNamespace(),
0512: SimpleType.RESTRICTION, SimpleTypeHandler
0513: .getSimpleTypes(rest, parent),
0514: SimpleTypeHandler.getFacets(rest), finaL);
0515: dct.parent = st;
0516: dct.simple = true;
0517: }
0518:
0519: dct.mixed = true;
0520: } else {
0521: // ComplexContentHandler
0522: // TODO deal with these as a special case to incure call backs in the heiarchy
0523: ComplexContentHandler cch = (ComplexContentHandler) child;
0524:
0525: if (cch.getChild() instanceof ExtensionHandler) {
0526: ExtensionHandler ext = (ExtensionHandler) cch
0527: .getChild();
0528:
0529: ComplexType ct = parent.lookUpComplexType(ext
0530: .getBase());
0531: dct.parent = ct;
0532:
0533: // attributes
0534: if (ct != null && ct.getAttributes() != null) {
0535: Attribute[] it = ct.getAttributes();
0536:
0537: for (int i = 0; i < it.length; i++) {
0538: attr.add(it[i]);
0539: }
0540: }
0541:
0542: if (ext.getAttributeDeclarations() != null) {
0543: Iterator it = ext.getAttributeDeclarations()
0544: .iterator();
0545:
0546: while (it.hasNext()) {
0547: Object o = it.next();
0548:
0549: if (o instanceof AttributeHandler) {
0550: AttributeHandler ah = (AttributeHandler) o;
0551: attr.add(ah.compress(parent));
0552: } else {
0553: AttributeGroupHandler agh = (AttributeGroupHandler) o;
0554: AttributeGroup ag = agh
0555: .compress(parent);
0556: attr.addAll(Arrays.asList(ag
0557: .getAttributes()));
0558: }
0559: }
0560: }
0561:
0562: if (ct != null && ext.getChild() != null) {
0563: logger.finest("Looked up "
0564: + ext.getBase()
0565: + " and found "
0566: + ((ct == null) ? null : (ct.getName()
0567: + ":::" + ct.getNamespace()))
0568: + " for " + name);
0569:
0570: ElementGrouping extensionBaseType = ct
0571: .getChild();
0572: ElementGrouping extensionChild = ((ElementGroupingHandler) ext
0573: .getChild()).compress(parent);
0574: dct.child = loadNewEG(extensionBaseType,
0575: extensionChild, parent); // note should override element def only ... not spot
0576: } else {
0577: if (ct != null)
0578: dct.child = ct.getChild();
0579: }
0580: } else {
0581: //restriction
0582: RestrictionHandler ext = (RestrictionHandler) cch
0583: .getChild();
0584:
0585: // attributes
0586: if (ext.getAttributeDeclarations() != null) {
0587: Iterator it = ext.getAttributeDeclarations()
0588: .iterator();
0589:
0590: while (it.hasNext()) {
0591: Object o = it.next();
0592:
0593: if (o instanceof AttributeHandler) {
0594: AttributeHandler ah = (AttributeHandler) o;
0595: attr.add(ah.compress(parent));
0596: } else {
0597: AttributeGroupHandler agh = (AttributeGroupHandler) o;
0598: AttributeGroup ag = agh
0599: .compress(parent);
0600: attr.addAll(Arrays.asList(ag
0601: .getAttributes()));
0602: }
0603: }
0604: }
0605:
0606: if (ext.getChild() == null) {
0607: dct.child = null; // empty child
0608: } else {
0609: dct.child = ((ElementGroupingHandler) ext
0610: .getChild()).compress(parent);
0611: }
0612:
0613: dct.parent = parent
0614: .lookUpComplexType(ext.getBase());
0615: }
0616:
0617: if (dct.child == null) {
0618: dct.child = new DefaultSequence();
0619: }
0620:
0621: dct.isDerived = true;
0622: }
0623: } else {
0624: // one of Choice, Group, Sequence, All
0625: // attributes
0626: if (attrDecs != null) {
0627: Iterator it = attrDecs.iterator();
0628:
0629: while (it.hasNext()) {
0630: Object o = it.next();
0631:
0632: if (o instanceof AttributeHandler) {
0633: AttributeHandler ah = (AttributeHandler) o;
0634: attr.add(ah.compress(parent));
0635: } else {
0636: AttributeGroupHandler agh = (AttributeGroupHandler) o;
0637: AttributeGroup ag = agh.compress(parent);
0638: attr.addAll(Arrays.asList(ag.getAttributes()));
0639: }
0640: }
0641: }
0642:
0643: if (child != null) {
0644: dct.child = ((ElementGroupingHandler) child)
0645: .compress(parent);
0646: } else {
0647: dct.child = new DefaultSequence();
0648: }
0649: }
0650:
0651: dct.attributes = (Attribute[]) attr.toArray(new Attribute[attr
0652: .size()]);
0653: dct.namespace = parent.getTargetNamespace();
0654: dct.block = block;
0655: dct.finaL = finaL;
0656: dct.id = id;
0657:
0658: if (!dct.mixed) { // simpleContent flag ...
0659: dct.mixed = mixed;
0660: }
0661:
0662: dct.name = name;
0663: cache = dct;
0664:
0665: if (((cache.getChild() == null) && !abstracT) && !dct.simple) {
0666: logger.warning(getName() + " :: "
0667: + parent.getTargetNamespace()
0668: + " should have a real child: ");
0669: throw new NullPointerException();
0670: }
0671:
0672: if ((dct.parent == null) && dct.simple) {
0673: logger.warning(getName() + " :: "
0674: + parent.getTargetNamespace()
0675: + " should have a real parent: ");
0676: throw new NullPointerException();
0677: }
0678:
0679: logger.fine("End compressing ComplexType " + getName());
0680:
0681: attrDecs = null;
0682: anyAttribute = null;
0683: child = null;
0684:
0685: return cache;
0686: }
0687:
0688: /*
0689: * Helper method that removes a level of indirection through combining
0690: * the levels into more compact representations
0691: */
0692: private ElementGrouping loadNewEG(
0693: ElementGrouping extensionBaseType,
0694: ElementGrouping extensionChild, SchemaHandler parent)
0695: throws SAXException {
0696: if (extensionChild == null) {
0697:
0698: if (extensionBaseType.getGrouping() == ElementGrouping.GROUP) {
0699: return ((Group) extensionBaseType).getChild();
0700: }
0701:
0702: return extensionBaseType;
0703: }
0704:
0705: switch (extensionBaseType.getGrouping()) {
0706:
0707: case ElementGrouping.CHOICE:
0708: logger.finest("ElementGrouping eg is CHOICE in loadNewEG");
0709:
0710: return new DefaultSequence((Choice) extensionBaseType,
0711: extensionChild);
0712:
0713: case ElementGrouping.GROUP:
0714: logger.finest("ElementGrouping eg is GROUP in loadNewEG");
0715:
0716: Group baseGroup = (Group) extensionBaseType;
0717:
0718: if (baseGroup.getChild() == null) {
0719: return extensionChild;
0720: }
0721: return loadNewEG(baseGroup.getChild(), extensionChild,
0722: parent);
0723:
0724: case ElementGrouping.SEQUENCE:
0725: logger.finest("ElementGrouping eg is SEQUENCE");
0726: return new DefaultSequence((Sequence) extensionBaseType,
0727: extensionChild);
0728:
0729: default:
0730: return extensionBaseType;
0731: }
0732: }
0733:
0734: /**
0735: * @see org.geotools.xml.XSIElementHandler#getHandlerType()
0736: */
0737: public int getHandlerType() {
0738: return DEFAULT;
0739: }
0740:
0741: /**
0742: * @see org.geotools.xml.XSIElementHandler#endElement(java.lang.String,
0743: * java.lang.String)
0744: */
0745: public void endElement(String namespaceURI, String localName) {
0746: // do nothing
0747: }
0748:
0749: /**
0750: * <p>
0751: * implementation of a default sequence with some extra logic in the
0752: * constructors.
0753: * </p>
0754: *
0755: * @author dzwiers
0756: *
0757: * @see Sequence
0758: */
0759: private static class DefaultSequence implements Sequence {
0760: ElementGrouping[] children;
0761: String id;
0762: int maxOccurs;
0763: int minOccurs;
0764:
0765: /*
0766: * Should not be called
0767: */
0768: private DefaultSequence() {
0769: // do nothing
0770: }
0771:
0772: /**
0773: * <p>
0774: * Combines the specified Sequence with the element grouping into a
0775: * new Sequence
0776: * </p>
0777: *
0778: * @param sequence
0779: * @param eg
0780: */
0781: public DefaultSequence(Sequence sequence, ElementGrouping eg) {
0782: logger.finest("merging sequence with an ElementGrouping");
0783: id = sequence.getId();
0784: maxOccurs = sequence.getMaxOccurs();
0785: minOccurs = sequence.getMinOccurs();
0786:
0787: if (sequence.getChildren() == null) {
0788: logger.finest("Sequence children are null");
0789: children = new ElementGrouping[1];
0790: children[0] = eg;
0791:
0792: return;
0793: }
0794:
0795: if (eg.getGrouping() == ElementGrouping.SEQUENCE) {
0796: logger.finest("Two sequences being merged");
0797:
0798: Sequence sq2 = (Sequence) eg;
0799: children = new ElementGrouping[sequence.getChildren().length
0800: + sq2.getChildren().length];
0801: logger.finest("There are a total of " + children.length
0802: + " Children");
0803:
0804: for (int i = 0; i < sequence.getChildren().length; i++) {
0805: children[i] = sequence.getChildren()[i];
0806: }
0807:
0808: for (int i = 0; i < sq2.getChildren().length; i++) {
0809: children[sequence.getChildren().length + i] = sq2
0810: .getChildren()[i];
0811: }
0812: } else {
0813: children = new ElementGrouping[sequence.getChildren().length + 1];
0814: logger.finest("There are a total of " + children.length
0815: + " Children");
0816:
0817: for (int i = 0; i < sequence.getChildren().length; i++)
0818: children[i] = sequence.getChildren()[i];
0819:
0820: children[sequence.getChildren().length] = eg;
0821: }
0822: }
0823:
0824: /**
0825: * <p>
0826: * Combines the Choice with the ElementGrouping to form a new Sequence
0827: * </p>
0828: *
0829: * @param sequence
0830: * @param eg
0831: */
0832: public DefaultSequence(Choice sequence, ElementGrouping eg) {
0833: id = sequence.getId();
0834: maxOccurs = sequence.getMaxOccurs();
0835: minOccurs = sequence.getMinOccurs();
0836:
0837: if (sequence.getChildren() == null) {
0838: children = new ElementGrouping[1];
0839: children[0] = eg;
0840:
0841: return;
0842: }
0843:
0844: children = new ElementGrouping[2];
0845: children[0] = sequence;
0846: children[1] = eg;
0847: }
0848:
0849: /**
0850: * @see org.geotools.xml.xsi.Sequence#getChildren()
0851: */
0852: public ElementGrouping[] getChildren() {
0853: return children;
0854: }
0855:
0856: /**
0857: * @see org.geotools.xml.xsi.Sequence#getId()
0858: */
0859: public String getId() {
0860: return id;
0861: }
0862:
0863: /**
0864: * @see org.geotools.xml.xsi.ElementGrouping#getMaxOccurs()
0865: */
0866: public int getMaxOccurs() {
0867: return maxOccurs;
0868: }
0869:
0870: /**
0871: * @see org.geotools.xml.xsi.ElementGrouping#getMinOccurs()
0872: */
0873: public int getMinOccurs() {
0874: return minOccurs;
0875: }
0876:
0877: /**
0878: * @see org.geotools.xml.xsi.ElementGrouping#getGrouping()
0879: */
0880: public int getGrouping() {
0881: return SEQUENCE;
0882: }
0883:
0884: /**
0885: * @see org.geotools.xml.xsi.ElementGrouping#findChildElement(java.lang.String)
0886: */
0887: public Element findChildElement(String name) {
0888: if (children == null) {
0889: return null;
0890: }
0891: for (int i = 0; i < children.length; i++) {
0892: Element t = children[i].findChildElement(name);
0893: if (t != null) { // found it
0894:
0895: return t;
0896: }
0897: }
0898:
0899: return null;
0900: }
0901:
0902: public Element findChildElement(String localName,
0903: URI namespaceURI) {
0904: if (children == null) {
0905: return null;
0906: }
0907: for (int i = 0; i < children.length; i++) {
0908: Element t = children[i].findChildElement(localName,
0909: namespaceURI);
0910: if (t != null) { // found it
0911:
0912: return t;
0913: }
0914: }
0915:
0916: return null;
0917: }
0918: }
0919:
0920: /**
0921: * <p>
0922: * Default implementation of a ComplexType
0923: * </p>
0924: *
0925: * @author dzwiers
0926: *
0927: * @see ComplexType
0928: */
0929: private static class DefaultComplexType implements ComplexType {
0930: boolean isDerived = false;
0931: Type parent;
0932: String anyAttributeNameSpace;
0933: URI namespace;
0934: String id;
0935: String name;
0936: int block;
0937: int finaL;
0938: ElementGrouping child;
0939: boolean simple = false;
0940: Attribute[] attributes;
0941: boolean abstracT;
0942: boolean mixed;
0943:
0944: public Element[] getChildElements() {
0945: if (child == null) {
0946: return null;
0947: }
0948:
0949: return getChildElements(child);
0950: }
0951:
0952: public Element[] getChildElements(ElementGrouping child11) {
0953: if (child11 == null)
0954: return new Element[0];
0955: switch (child11.getGrouping()) {
0956: case ElementGrouping.ALL:
0957: return ((All) child11).getElements();
0958:
0959: case ElementGrouping.ANY:
0960: return null;
0961:
0962: case ElementGrouping.CHOICE:
0963:
0964: ElementGrouping[] children = ((Choice) child11)
0965: .getChildren();
0966: List l = new LinkedList();
0967:
0968: for (int i = 0; i < children.length; i++) {
0969: Element[] t = getChildElements(children[i]);
0970:
0971: if (t != null) {
0972: l.addAll(Arrays.asList(t));
0973: }
0974: }
0975:
0976: return (l.size() > 0) ? (Element[]) l
0977: .toArray(new Element[l.size()]) : null;
0978:
0979: case ElementGrouping.ELEMENT:
0980: return new Element[] { (Element) child11, };
0981:
0982: case ElementGrouping.GROUP:
0983:
0984: ElementGrouping c = ((Group) child11).getChild();
0985: if (c == null)
0986: return new Element[0];
0987: return getChildElements(c);
0988:
0989: case ElementGrouping.SEQUENCE:
0990: children = ((Sequence) child11).getChildren();
0991: l = new LinkedList();
0992: if (children != null) {
0993: for (int i = 0; i < children.length; i++) {
0994: Element[] t = getChildElements(children[i]);
0995:
0996: if (t != null) {
0997: l.addAll(Arrays.asList(t));
0998: }
0999: }
1000: }
1001:
1002: return (l.size() > 0) ? (Element[]) l
1003: .toArray(new Element[l.size()]) : null;
1004: }
1005:
1006: return null;
1007: }
1008:
1009: /**
1010: * @see org.geotools.xml.schema.ComplexType#cache()
1011: */
1012: public boolean cache(Element e, Map m) {
1013: return true;
1014: }
1015:
1016: /**
1017: * @see org.geotools.xml.xsi.Type#getNamespace()
1018: */
1019: public URI getNamespace() {
1020: return namespace;
1021: }
1022:
1023: /**
1024: * @see org.geotools.xml.xsi.Type#getParent()
1025: */
1026: public Type getParent() {
1027: return parent;
1028: }
1029:
1030: /**
1031: * @see org.geotools.xml.xsi.ComplexType#isDerived()
1032: */
1033: public boolean isDerived() {
1034: return isDerived;
1035: }
1036:
1037: /**
1038: * @see org.geotools.xml.xsi.ComplexType#getAttributes()
1039: */
1040: public Attribute[] getAttributes() {
1041: return attributes;
1042: }
1043:
1044: /**
1045: * @see org.geotools.xml.xsi.ComplexType#isAbstract()
1046: */
1047: public boolean isAbstract() {
1048: return abstracT;
1049: }
1050:
1051: /**
1052: * @see org.geotools.xml.xsi.ComplexType#getBlock()
1053: */
1054: public int getBlock() {
1055: return block;
1056: }
1057:
1058: /**
1059: * @see org.geotools.xml.xsi.ComplexType#getChild()
1060: */
1061: public ElementGrouping getChild() {
1062: return child;
1063: }
1064:
1065: /**
1066: * @see org.geotools.xml.xsi.ComplexType#getFinal()
1067: */
1068: public int getFinal() {
1069: return finaL;
1070: }
1071:
1072: /**
1073: * @see org.geotools.xml.xsi.ComplexType#isMixed()
1074: */
1075: public boolean isMixed() {
1076: return mixed;
1077: }
1078:
1079: /**
1080: * @see org.geotools.xml.xsi.Type#getName()
1081: */
1082: public String getName() {
1083: return name;
1084: }
1085:
1086: /**
1087: * @see org.geotools.xml.xsi.ComplexType#getAnyAttributeNameSpace()
1088: */
1089: public String getAnyAttributeNameSpace() {
1090: return anyAttributeNameSpace;
1091: }
1092:
1093: /**
1094: * @see org.geotools.xml.xsi.ComplexType#getId()
1095: */
1096: public String getId() {
1097: return id;
1098: }
1099:
1100: /**
1101: * @throws SAXException
1102: * @throws OperationNotSupportedException
1103: * @see org.geotools.xml.xsi.Type#getValue(org.geotools.xml.xsi.Element,
1104: * org.geotools.xml.xsi.ElementValue[], org.xml.sax.Attributes)
1105: */
1106: public Object getValue(Element element, ElementValue[] value,
1107: final Attributes attrs, Map hints)
1108: throws OperationNotSupportedException, SAXException {
1109: Object[] values = null;
1110:
1111: logger.finest("Getting value for " + name);
1112:
1113: if (isDerived || simple) {
1114: try {
1115: Object v = parent.getValue(element, value, attrs,
1116: hints);
1117:
1118: return v; // this means it's meant to be extended ... and so should already include the extensions.
1119: } catch (SAXNotSupportedException snse) {
1120: logger.finest(snse.toString());
1121:
1122: // do nothing ... except pretend it is not derived
1123: }
1124: }
1125:
1126: if (simple) {
1127: return null;
1128: }
1129:
1130: if (element.getType() instanceof ComplexType
1131: && ((ComplexType) element.getType()).getChild() instanceof Choice) {
1132: if (value.length > 0)
1133: return value[0].getValue();
1134: } else {
1135: values = new Object[value.length + 1];
1136: logger.finest("Getting value for " + element.getName()
1137: + ":" + name);
1138:
1139: // This seems to some how be for mixed content? Don't really understand what
1140: // is going on here.
1141: values[0] = new ElementValue() {
1142: public Element getElement() {
1143: return null;
1144: }
1145:
1146: public Object getValue() {
1147: return attrs;
1148: }
1149:
1150: };
1151:
1152: for (int i = 1; i < value.length + 1; i++) {
1153: values[i] = value[i - (isMixed() ? 0 : 1)]
1154: .getValue();
1155: logger.finest("*"
1156: + ((values[i] != null) ? values[i]
1157: .getClass().getName() : "null"));
1158: }
1159:
1160: if (isMixed())
1161: values[values.length - 1] = value[0];
1162:
1163: }
1164: return values;
1165: }
1166:
1167: /**
1168: * @see org.geotools.xml.xsi.Type#getInstanceType()
1169: */
1170: public Class getInstanceType() {
1171: return Object[].class;
1172: }
1173:
1174: /**
1175: * @see org.geotools.xml.xsi.ComplexType#findChildElement(java.lang.String)
1176: */
1177: public Element findChildElement(String name1) {
1178: Element e = (child == null) ? null : child
1179: .findChildElement(name1);
1180: e = e == null ? (parent == null ? null : parent
1181: .findChildElement(name1)) : e;
1182: return e;
1183: }
1184:
1185: /**
1186: * @see org.geotools.xml.schema.Type#canEncode(org.geotools.xml.schema.Element,
1187: * java.lang.Object, java.util.Map)
1188: */
1189: public boolean canEncode(Element element, Object value,
1190: Map hints) {
1191: if ((parent != null)
1192: && parent.canEncode(element, value, hints)) {
1193: return true;
1194: }
1195:
1196: return false;
1197: }
1198:
1199: /**
1200: * @see org.geotools.xml.schema.Type#encode(org.geotools.xml.schema.Element,
1201: * java.lang.Object, org.geotools.xml.PrintHandler,
1202: * java.util.Map)
1203: */
1204: public void encode(Element element, Object value,
1205: PrintHandler output, Map hints) throws IOException,
1206: OperationNotSupportedException {
1207: if ((parent != null)
1208: && parent.canEncode(element, value, hints)) {
1209: parent.encode(element, value, output, hints);
1210: } else {
1211: output.startElement(element.getNamespace(), element
1212: .getName(), null);
1213: Type type = element.getType();
1214: if (type instanceof SimpleType) {
1215: SimpleType simple = (SimpleType) type;
1216: simple.encode(element, value, output, hints);
1217: } else if (type instanceof ComplexType) {
1218: ComplexType complex = (ComplexType) type;
1219: Element[] children = complex.getChildElements();
1220: boolean found = false;
1221: for (int i = 0; i < children.length; i++) {
1222: Element child = children[i];
1223: if (child.getType().canEncode(child, value,
1224: hints)) {
1225: child.getType().encode(child, value,
1226: output, hints);
1227: found = true;
1228: }
1229: }
1230: if (!found)
1231: throw new RuntimeException(
1232: "It is not known how to print this element");
1233: } else {
1234: throw new OperationNotSupportedException(
1235: "It is not known how to print this element");
1236: }
1237: output.endElement(element.getNamespace(), element
1238: .getName());
1239: }
1240: }
1241: }
1242: }
|