1 /** 2 * Redistribution and use of this software and associated documentation ("Software"), with or 3 * without modification, are permitted provided that the following conditions are met: 4 * 5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions 6 * must also contain a copy of this document. 7 * 8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 9 * conditions and the following disclaimer in the documentation and/or other materials provided with 10 * the distribution. 11 * 12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software 13 * without prior written permission of Intalio, Inc. For written permission, please contact 14 * info@exolab.org. 15 * 16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in 17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of 18 * Intalio, Inc. 19 * 20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/). 21 * 22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright 2001-2002 (C) Intalio Inc. All Rights Reserved. 32 * 33 * $Id$ 34 */ 35 36 package org.exolab.castor.xml.schema.reader; 37 38 // -- imported classes and packages 39 import java.util.StringTokenizer; 40 41 import org.exolab.castor.xml.AttributeSet; 42 import org.exolab.castor.xml.Namespaces; 43 import org.exolab.castor.xml.XMLException; 44 import org.exolab.castor.xml.schema.Annotation; 45 import org.exolab.castor.xml.schema.Schema; 46 import org.exolab.castor.xml.schema.SchemaContext; 47 import org.exolab.castor.xml.schema.SchemaNames; 48 import org.exolab.castor.xml.schema.SimpleType; 49 import org.exolab.castor.xml.schema.Union; 50 51 /** 52 * A class for Unmarshalling XML Schema Union types 53 * 54 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 55 * @version $Revision$ $Date: 2003-03-03 00:05:44 -0700 (Mon, 03 Mar 2003) $ 56 **/ 57 public class UnionUnmarshaller extends ComponentReader { 58 59 // --------------------/ 60 // - Member Variables -/ 61 // --------------------/ 62 63 /** 64 * The current ComponentReader 65 **/ 66 private ComponentReader _unmarshaller; 67 68 /** 69 * The current branch depth 70 **/ 71 private int _depth = 0; 72 73 /** 74 * The Union we are unmarshalling 75 **/ 76 private Union _union = null; 77 78 /** 79 * The parent Schema for the Union 80 **/ 81 private Schema _schema = null; 82 83 private boolean _foundAnnotation = false; 84 private boolean _foundSimpleType = false; 85 86 // ----------------/ 87 // - Constructors -/ 88 // ----------------/ 89 90 /** 91 * Creates a new IdentityConstraintUnmarshaller 92 * 93 * @param schemaContext the {@link SchemaContext} to get some configuration settings from 94 * @param atts the AttributeList 95 **/ 96 public UnionUnmarshaller(final SchemaContext schemaContext, final Schema schema, 97 final AttributeSet atts) throws XMLException { 98 super(schemaContext); 99 100 if (schema == null) { 101 String err = "'schema' must not be null."; 102 throw new IllegalStateException(err); 103 } 104 _schema = schema; 105 106 _union = new Union(_schema); 107 _union.setId(atts.getValue(SchemaNames.ID_ATTR)); 108 109 String memberTypes = atts.getValue(SchemaNames.MEMBER_TYPES_ATTR); 110 processMemberTypes(memberTypes); 111 112 } // -- UnionUnmarshaller 113 114 // -----------/ 115 // - Methods -/ 116 // -----------/ 117 118 /** 119 * Returns the name of the element that this ComponentReader handles 120 * 121 * @return the name of the element that this ComponentReader handles 122 **/ 123 public String elementName() { 124 return SchemaNames.UNION; 125 } // -- elementName 126 127 /** 128 * Returns the Object created by this ComponentReader 129 * 130 * @return the Object created by this ComponentReader 131 **/ 132 public Object getObject() { 133 return _union; 134 } // -- getObject 135 136 public void finish() throws XMLException { 137 // -- do nothing 138 } // -- finish 139 140 /** 141 * Signals the start of an element with the given name. 142 * 143 * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a 144 * prefix). 145 * @param namespace the namespace of the element. This may be null. Note: A null namespace is not 146 * the same as the default namespace unless the default namespace is also null. 147 * @param atts the AttributeSet containing the attributes associated with the element. 148 * @param nsDecls the namespace declarations being declared for this element. This may be null. 149 **/ 150 public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls) 151 throws XMLException { 152 // -- Do delagation if necessary 153 if (_unmarshaller != null) { 154 _unmarshaller.startElement(name, namespace, atts, nsDecls); 155 ++_depth; 156 return; 157 } 158 159 if (SchemaNames.ANNOTATION.equals(name)) { 160 161 if (_foundAnnotation) 162 error("Only one (1) annotation may appear as a child of '" + elementName() + "'."); 163 164 if (_foundSimpleType) 165 error("An annotation may only appear as the first child of '" + elementName() + "'."); 166 167 _foundAnnotation = true; 168 _unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts); 169 } else if (SchemaNames.SIMPLE_TYPE.equals(name)) { 170 _foundSimpleType = true; 171 _unmarshaller = new SimpleTypeUnmarshaller(getSchemaContext(), _schema, atts); 172 } else 173 illegalElement(name); 174 175 } // -- startElement 176 177 /** 178 * Signals to end of the element with the given name. 179 * 180 * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a 181 * prefix). 182 * @param namespace the namespace of the element. 183 **/ 184 public void endElement(String name, String namespace) throws XMLException { 185 186 // -- Do delagation if necessary 187 if ((_unmarshaller != null) && (_depth > 0)) { 188 _unmarshaller.endElement(name, namespace); 189 --_depth; 190 return; 191 } 192 193 // -- have unmarshaller perform any necessary clean up 194 _unmarshaller.finish(); 195 196 if (SchemaNames.ANNOTATION.equals(name)) { 197 _union.setLocalAnnotation((Annotation) _unmarshaller.getObject()); 198 } else if (SchemaNames.SIMPLE_TYPE.equals(name)) { 199 200 SimpleType simpleType = (SimpleType) _unmarshaller.getObject(); 201 202 // -- make sure type is not another Union 203 if (simpleType instanceof Union) { 204 String err = "A 'union' may only contain SimpleTypes of " + "the atomic or list variety."; 205 error(err); 206 } 207 // -- make sure type is atomic or list 208 // XXXX to be added later 209 210 _union.addMemberType(simpleType); 211 } 212 213 214 _unmarshaller = null; 215 } // -- endElement 216 217 public void characters(char[] ch, int start, int length) throws XMLException { 218 // -- Do delagation if necessary 219 if (_unmarshaller != null) { 220 _unmarshaller.characters(ch, start, length); 221 } 222 } // -- characters 223 224 225 /** 226 * Processes the given string into the referenced simpleTypes for the Union being unmarshalled. 227 * 228 * @param memberTypes the memberTypes list. 229 **/ 230 private void processMemberTypes(String memberTypes) { 231 if ((memberTypes == null) || (memberTypes.length() == 0)) 232 return; 233 234 StringTokenizer st = new StringTokenizer(memberTypes); 235 while (st.hasMoreTokens()) { 236 String typeName = st.nextToken(); 237 SimpleType simpleType = _schema.getSimpleType(typeName); 238 if (simpleType != null) { 239 _union.addMemberType(simpleType); 240 } else { 241 _union.addMemberType(typeName); 242 } 243 244 } 245 } // -- processMemberTypes 246 247 } // -- UnionUnmarshaller