001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.betwixt.schema;
019
020 import java.beans.IntrospectionException;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.Iterator;
024 import java.util.List;
025
026 import org.apache.commons.betwixt.ElementDescriptor;
027 import org.apache.commons.betwixt.XMLBeanInfo;
028 import org.apache.commons.betwixt.XMLIntrospector;
029
030 /**
031 * Model for top level element in an XML Schema
032 *
033 * @author <a href='http://commons.apache.org/'>Apache Commons Team</a>
034 * @version $Revision: 561314 $
035 */
036 public class Schema {
037
038 private List elements = new ArrayList();
039 private List complexTypes = new ArrayList();
040 private List simpleTypes = new ArrayList();
041
042 private XMLIntrospector introspector;
043
044 public Schema() {
045 this(new XMLIntrospector());
046 }
047
048 public Schema(XMLIntrospector introspector) {
049 this.introspector = introspector;
050 }
051
052 /**
053 * Introspects the given type giving an <code>XMLBeanInfo</code>.
054 * @param type Class to introspect, not null
055 * @return <code>XMLBeanInfo</code>, not null
056 * @throws IntrospectionException
057 */
058 public XMLBeanInfo introspect(Class type) throws IntrospectionException {
059 return introspector.introspect(type);
060 }
061
062 /**
063 * Gets the complex types defined
064 * @return list of <code>ComplexType</code>'s not null
065 */
066 public List getComplexTypes() {
067 return complexTypes;
068 }
069
070
071 /**
072 * Adds a new complex type to those defined
073 * @param complexType not null
074 */
075 public void addComplexType(GlobalComplexType complexType) {
076 complexTypes.add(complexType);
077 }
078
079
080 /**
081 * Gets the elements definied
082 * @return list of <code>Element</code>s not null
083 */
084 public List getElements() {
085 return elements;
086 }
087
088 /**
089 * Adds a new element to those defined.
090 * @param element not null
091 */
092 public void addElement(GlobalElement element) {
093 elements.add(element);
094 }
095
096 /**
097 * Gets the simple types defined.
098 * @return list of <code>SimpleType</code>s not null
099 */
100 public List getSimpleTypes() {
101 return simpleTypes;
102 }
103
104 /**
105 * Adds a new simple type to those defined.
106 * @param simpleType
107 */
108 public void addSimpleType(SimpleType simpleType) {
109 simpleTypes.add(simpleType);
110 }
111
112
113 /**
114 * Adds global (top level) element and type declarations matching the given descriptor.
115 * @param elementDescriptor ElementDescriptor not null
116 */
117 public void addGlobalElementType(TranscriptionConfiguration configuration, ElementDescriptor elementDescriptor) throws IntrospectionException {
118 // need to create a global element declaration and a complex type
119 // use the fully qualified class name as the type name
120 GlobalElement element = new GlobalElement(
121 elementDescriptor.getLocalName(),
122 configuration.getSchemaTypeNamingStrategy().nameSchemaType(elementDescriptor));
123 addElement(element);
124 addGlobalComplexType(configuration, elementDescriptor);
125 }
126
127 /**
128 * Adds a new global complex type definition matching the given element descriptor.
129 * If this element descriptor has already been mapped to a global type then
130 * that is returned.
131 * @since 0.7
132 * @param configuration <code>TranscriptionConfiguration</code>, not null
133 * @param elementDescriptor <code>ElementDescriptor</code>, not null
134 * @return <code>GlobalComplexType</code>
135 * @throws IntrospectionException
136 */
137 public GlobalComplexType addGlobalComplexType(TranscriptionConfiguration configuration, ElementDescriptor elementDescriptor) throws IntrospectionException {
138 GlobalComplexType type = null;
139 for (Iterator it = complexTypes.iterator(); it.hasNext();) {
140 GlobalComplexType complexType = (GlobalComplexType) it.next();
141 if (complexType.matches( elementDescriptor )) {
142 type = complexType;
143 break;
144 }
145 }
146 if (type == null) {
147 type = new GlobalComplexType(configuration, elementDescriptor, this);
148 addComplexType(type);
149 type.fill(configuration, elementDescriptor, this);
150 }
151 return type;
152 }
153
154 public boolean equals(Object obj) {
155 boolean result = false;
156 if (obj instanceof Schema) {
157 Schema schema = (Schema) obj;
158 result =
159 equalContents(elements, schema.elements) &&
160 equalContents(complexTypes, schema.complexTypes) &&
161 equalContents(simpleTypes, schema.simpleTypes);
162 }
163 return result;
164 }
165
166 private boolean equalContents(Collection one, Collection two)
167 {
168 // doesn't check cardinality but should be ok
169 if (one.size() != two.size()) {
170 return false;
171 }
172 for (Iterator it=one.iterator();it.hasNext();) {
173 Object object = it.next();
174 if (!two.contains(object)) {
175 return false;
176 }
177 }
178 return true;
179 }
180
181 public int hashCode() {
182 return 0;
183 }
184
185
186
187 public String toString() {
188 StringBuffer buffer = new StringBuffer();
189 buffer.append("<?xml version='1.0'?>");
190 buffer.append("<xsd:schema xmlns:xsd='http://www.w3c.org/2001/XMLSchema'>");
191
192 for (Iterator it=simpleTypes.iterator(); it.hasNext();) {
193 buffer.append(it.next());
194 }
195
196 for (Iterator it=complexTypes.iterator(); it.hasNext();) {
197 buffer.append(it.next());
198 }
199
200
201 for (Iterator it=elements.iterator(); it.hasNext();) {
202 buffer.append(it.next());
203 }
204 buffer.append("</xsd:schema>");
205 return buffer.toString();
206 }
207 }