1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wadl.inference.schema;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import org.apache.xmlbeans.XmlCursor;
21 import org.apache.xmlbeans.XmlException;
22
23 import com.eviware.soapui.impl.wadl.inference.ConflictHandler;
24 import com.eviware.soapui.impl.wadl.inference.ConflictHandler.Event;
25 import com.eviware.soapui.impl.wadl.inference.schema.types.ComplexType;
26 import com.eviware.soapui.impl.wadl.inference.schema.types.EmptyType;
27 import com.eviware.soapui.inferredSchema.ComplexTypeConfig;
28 import com.eviware.soapui.inferredSchema.MapEntryConfig;
29 import com.eviware.soapui.inferredSchema.ParticleConfig;
30 import com.eviware.soapui.inferredSchema.SchemaConfig;
31 import com.eviware.soapui.support.StringUtils;
32
33 /***
34 * Represents an inferred schema for a single namespace.
35 *
36 * @author Dain Nilsson
37 */
38 public class Schema
39 {
40 private SchemaSystem schemaSystem;
41 private String namespace;
42 private Map<String, String> prefixes;
43 private Map<String, ComplexType> types;
44 private List<Particle> particles;
45 private EmptyType empty = new EmptyType( this );
46
47 /***
48 * Constructs a blank new Schema for the given namespace in the given
49 * SchemaSystem.
50 *
51 * @param namespace
52 * The namespace for the new schema.
53 * @param schemaSystem
54 * The SchemaSystem in which to place the newly created Schema.
55 */
56 public Schema( String namespace, SchemaSystem schemaSystem )
57 {
58 this.schemaSystem = schemaSystem;
59 this.namespace = namespace;
60 prefixes = new HashMap<String, String>();
61 particles = new ArrayList<Particle>();
62 types = new HashMap<String, ComplexType>();
63 putPrefixForNamespace( "xs", Settings.xsdns );
64 }
65
66 /***
67 * Constructs a Schema object using previously saved data.
68 *
69 * @param xml
70 * The XmlObject to which data has previously been saved.
71 * @param schemaSystem
72 * The SchemaSystem in which to place the newly created Schema.
73 */
74 public Schema( SchemaConfig xml, SchemaSystem schemaSystem )
75 {
76 this.schemaSystem = schemaSystem;
77 namespace = xml.getNamespace();
78 prefixes = new HashMap<String, String>();
79 particles = new ArrayList<Particle>();
80 types = new HashMap<String, ComplexType>();
81 for( MapEntryConfig entry : xml.getPrefixList() )
82 prefixes.put( entry.getKey(), entry.getValue() );
83 for( ParticleConfig item : xml.getParticleList() )
84 {
85 particles.add( Particle.Factory.parse( item, this ) );
86 }
87 for( ComplexTypeConfig item : xml.getComplexTypeList() )
88 {
89 types.put( item.getName(), new ComplexType( item, this ) );
90 }
91 }
92
93 /***
94 * Save the Schema to an XmlObject.
95 *
96 * @param xml
97 * A blank XmlObject to save to.
98 */
99 public void save( SchemaConfig xml )
100 {
101 xml.setNamespace( namespace );
102 for( Map.Entry<String, String> entry : prefixes.entrySet() )
103 {
104 MapEntryConfig mapEntry = xml.addNewPrefix();
105 mapEntry.setKey( entry.getKey() );
106 mapEntry.setValue( entry.getValue() );
107 }
108 List<ParticleConfig> particleList = new ArrayList<ParticleConfig>();
109 for( Particle item : particles )
110 particleList.add( item.save() );
111 xml.setParticleArray( particleList.toArray( new ParticleConfig[0] ) );
112 for( ComplexType item : types.values() )
113 item.save( xml.addNewComplexType() );
114 }
115
116 /***
117 * Add a ComplexType to this Schema.
118 *
119 * @param type
120 * The ComplexType to be added.
121 */
122 public void addType( ComplexType type )
123 {
124 types.put( type.getName(), type );
125 type.setSchema( this );
126 }
127
128 /***
129 * Getter for the namespace of this Schema.
130 *
131 * @return The namespace of this Schema.
132 */
133 public String getNamespace()
134 {
135 return namespace;
136 }
137
138 /***
139 * Gets the prefix used in this schema for a different namespace, if one
140 * exists.
141 *
142 * @param namespace
143 * Another namespace to get the prefix for.
144 * @return The prefix used for the given namespace.
145 */
146 public String getPrefixForNamespace( String namespace )
147 {
148 return prefixes.get( namespace );
149 }
150
151 /***
152 * Set the prefix used in this schema for a different namespace.
153 *
154 * @param prefix
155 * The prefix to be used.
156 * @param namespace
157 * The namespace to use the prefix for.
158 */
159 public void putPrefixForNamespace( String prefix, String namespace )
160 {
161 prefixes.put( namespace, prefix );
162 }
163
164 /***
165 * Get a Type contained in this schema by name.
166 *
167 * @param name
168 * The name of a contained Type.
169 * @return Returns the Type, if one is found. Otherwise returns null.
170 */
171 public Type getType( String name )
172 {
173 return types.get( name );
174 }
175
176 /***
177 * Create and add a new root element for this schema.
178 *
179 * @param name
180 * The name to give the newly created element.
181 * @return Returns the newly created element.
182 */
183 public Particle newElement( String name )
184 {
185 Particle p = Particle.Factory.newElementInstance( this, name );
186 particles.add( p );
187 return p;
188 }
189
190 /***
191 * Create and add a new global attribute for this schema.
192 *
193 * @param name
194 * The name to give the newly created attribute.
195 * @return Returns the newly created attribute.
196 */
197 public Particle newAttribute( String name )
198 {
199 Particle p = Particle.Factory.newAttributeInstance( this, name );
200 particles.add( p );
201 return p;
202 }
203
204 public String toString()
205 {
206 StringBuilder s = new StringBuilder( "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + "<"
207 + getPrefixForNamespace( Settings.xsdns ) + ":schema " );
208
209 if( StringUtils.hasContent( namespace ))
210 s.append( "targetNamespace=\"" + namespace + "\" " + "xmlns=\"" + namespace + "\" " );
211
212
213 for( Map.Entry<String, String> entry : prefixes.entrySet() )
214 s.append( "xmlns:" + entry.getValue() + "=\"" + entry.getKey() + "\" " );
215 s.append( "elementFormDefault=\"qualified\">" );
216 for( Particle item : particles )
217 {
218 s.append( item );
219 }
220 for( Type item : types.values() )
221 {
222 s.append( item );
223 }
224 if( s.toString().contains( "type=\"" + empty.getName() + "\"" ) )
225 s.append( empty );
226 s.append( "</" + getPrefixForNamespace( Settings.xsdns ) + ":schema>" );
227 return s.toString();
228 }
229
230 /***
231 * Validates an XML document contained in a given Context object.
232 *
233 * @param context
234 * A Context object containing the XML data to be validated, and
235 * other needed contextual variables.
236 * @throws XmlException
237 * On unresolvable validation error.
238 */
239 public void validate( Context context ) throws XmlException
240 {
241 XmlCursor cursor = context.getCursor();
242 Particle root = getParticle( cursor.getName().getLocalPart() );
243 if( root == null )
244 {
245 if( context.getHandler().callback( Event.CREATION, ConflictHandler.Type.ELEMENT, cursor.getName(),
246 "/" + cursor.getName().getLocalPart(), "Undeclared root element." ) )
247 {
248 root = newElement( cursor.getName().getLocalPart() );
249 }
250 else
251 throw new XmlException( "Illegal root element" );
252 }
253
254 root.validate( context );
255 }
256
257 /***
258 * Getter for the SchemaSystem that contains this Schema.
259 *
260 * @return Returns the parent SchemaSystem.
261 */
262 public SchemaSystem getSystem()
263 {
264 return schemaSystem;
265 }
266
267 /***
268 * Get a global particle by its name.
269 *
270 * @param name
271 * The name of the particle to get.
272 * @return Returns the Particle if one is found. Otherwise returns null.
273 */
274 public Particle getParticle( String name )
275 {
276 for( Particle item : particles )
277 {
278 if( item.getName().getLocalPart().equals( name ) )
279 return item;
280 }
281 return null;
282 }
283 }