AnnotationSchema.java
001 /*
002  *  AnnotationSchema.java
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Cristian URSU, 27/Sept/2000
013  *
014  *  $Id: AnnotationSchema.java 13142 2010-10-14 08:49:36Z markagreenwood $
015  */
016 package gate.creole;
017 
018 import java.io.InputStream;
019 import java.net.URL;
020 import java.util.*;
021 
022 import org.jdom.JDOMException;
023 import org.jdom.Namespace;
024 import org.jdom.input.SAXBuilder;
025 
026 import gate.Resource;
027 
028 /** This class handles annotation schemas.An annotation schema is a
029   * representation of an annotation, together with its types and their
030   * attributes, values and types.
031   */
032 public class AnnotationSchema extends AbstractLanguageResource{
033   public static final String FILE_URL_PARAM_NAME = "xmlFileUrl";
034 
035   /** Debug flag */
036   private static final boolean DEBUG = false;
037 
038   /** A map between XSchema types and Java Types */
039   private static Map<String, Class<?>> xSchema2JavaMap;
040 
041   /** A map between Java types and XSchema */
042   private static Map<Class<?>, String> java2xSchemaMap;
043 
044   /** This sets up two Maps between XSchema types and their coresponding
045     * Java types + a DOM xml parser
046     */
047   private static void setUpStaticData()
048   throws ResourceInstantiationException
049   {
050     xSchema2JavaMap = new HashMap<String, Class<?>>();
051     java2xSchemaMap = new HashMap<Class<?>, String>();
052 
053     xSchema2JavaMap.put("string",   String.class);
054     xSchema2JavaMap.put("integer",  Integer.class);
055     xSchema2JavaMap.put("int",      Integer.class);
056     xSchema2JavaMap.put("boolean",  Boolean.class);
057     xSchema2JavaMap.put("float",    Float.class);
058     xSchema2JavaMap.put("double",   Double.class);
059     xSchema2JavaMap.put("short",    Short.class);
060     xSchema2JavaMap.put("byte",     Byte.class);
061 
062     java2xSchemaMap.put(String.class,   "string");
063     java2xSchemaMap.put(Integer.class,  "integer");
064     java2xSchemaMap.put(Boolean.class,  "boolean");
065     java2xSchemaMap.put(Float.class,    "float");
066     java2xSchemaMap.put(Double.class,   "double");
067     java2xSchemaMap.put(Short.class,    "short");
068     java2xSchemaMap.put(Byte.class,     "byte");
069   //setUpStaticData
070 
071   /** The name of the annotation */
072   protected String annotationName = null;
073 
074   /** Returns the value of annotation name */
075   public String getAnnotationName(){
076     return annotationName;
077   // getAnnotationName
078 
079   /** Sets the annotation name */
080   public void setAnnotationName(String annotationName) {
081     this.annotationName = annotationName;
082   // setAnnotationName
083 
084   /** Schemas for the attributes */
085   protected Set<FeatureSchema> featureSchemaSet = null;
086 
087   /** Constructs an annotation schema. */
088   public AnnotationSchema(){
089   // AnnotationSchema
090 
091   /** Returns the feature schema set */
092   public Set<FeatureSchema> getFeatureSchemaSet(){
093     return featureSchemaSet;
094   // getAttributeSchemas
095 
096   /** Sets the feature schema set */
097   public void setFeatureSchemaSet(Set<FeatureSchema> featureSchemaSet) {
098     this.featureSchemaSet = featureSchemaSet;
099   // setFeatureSchemaSet
100 
101   /** @return a FeatureSchema object from featureSchemaSet, given a
102     * feature name.It will return null if the feature name is not found.
103     */
104   public FeatureSchema getFeatureSchema(String featureName) {
105     if(featureSchemaSet == nullreturn null;
106     for(FeatureSchema fs : featureSchemaSet){
107       if (fs.getFeatureName().equals(featureName)) return fs;      
108     }
109     return null;
110   // getFeatureSchema
111 
112   /** Initialise this resource, and return it. If the schema XML source file
113     * URL has been set, it will construct itself from that file.
114     */
115   public Resource init() throws ResourceInstantiationException {
116     // set up the static data if it's not there already
117     if(xSchema2JavaMap == null || java2xSchemaMap == null)
118       setUpStaticData();
119 
120     // parse the XML file if we have its URL
121     if(xmlFileUrl != nullfromXSchema(xmlFileUrl);
122 
123     return this;
124   // init()
125 
126   /** The xml file URL of the resource */
127   protected URL xmlFileUrl;
128 
129   /**
130    * The namepsace used in the xml file
131    */
132   protected Namespace namespace;
133 
134   /** Set method for the resource xml file URL */
135   public void setXmlFileUrl(URL xmlFileUrl) { this.xmlFileUrl = xmlFileUrl; }
136 
137   /** Get method for the resource xml file URL */
138   public URL getXmlFileUrl() { return xmlFileUrl; }
139 
140   /** Creates an AnnotationSchema object from an XSchema file
141     @param anXSchemaURL the URL where to find the XSchema file
142     */
143   public void fromXSchema(URL anXSchemaURL)
144               throws ResourceInstantiationException {
145     org.jdom.Document jDom = null;
146     SAXBuilder saxBuilder = new SAXBuilder(false);
147     try {
148     try{
149       jDom = saxBuilder.build(anXSchemaURL);
150     }catch(JDOMException je){
151       throw new ResourceInstantiationException(je);
152     }
153     catch (java.io.IOException ex) {
154       throw new ResourceInstantiationException(ex);
155     }
156     workWithJDom(jDom);
157   // fromXSchema
158 
159   /** Creates an AnnotationSchema object from an XSchema file
160     @param anXSchemaInputStream the Input Stream containing the XSchema file
161     */
162   public void fromXSchema(InputStream anXSchemaInputStream)
163               throws ResourceInstantiationException {
164     org.jdom.Document jDom = null;
165     SAXBuilder saxBuilder = new SAXBuilder(false);
166     try {
167     try{
168       jDom = saxBuilder.build(anXSchemaInputStream);
169     }catch(JDOMException je){
170       throw new ResourceInstantiationException(je);
171     }
172     catch (java.io.IOException ex) {
173       throw new ResourceInstantiationException(ex);
174     }
175     workWithJDom(jDom);
176   // end fromXSchema
177 
178   /** This method uses the JDom structure for our XSchema needs. What it does is
179     * to add semantics to the XML elements defined in XSchema. In the end we need
180     * to construct an AnnotationSchema object form an XSchema file.
181     *
182     @param jDom the JDOM structure containing the XSchema document. It must not
183     * be <b>null<b>
184     */
185   private void workWithJDom(org.jdom.Document jDom){
186     // Use the jDom structure the way we want
187     org.jdom.Element rootElement = jDom.getRootElement();
188     namespace = rootElement.getNamespace();
189     // get all children elements from the rootElement
190     List rootElementChildrenList = rootElement.getChildren("element", namespace);
191     Iterator rootElementChildrenIterator = rootElementChildrenList.iterator();
192     while (rootElementChildrenIterator.hasNext()){
193       org.jdom.Element childElement =
194                         (org.jdom.ElementrootElementChildrenIterator.next();
195       createAnnotationSchemaObject(childElement);
196     }//end while
197   // workWithJdom
198 
199   /** This method creates an AnnotationSchema object fom an org.jdom.Element
200     @param anElement is an XSchema element element
201     */
202   private void createAnnotationSchemaObject(org.jdom.Element anElement){
203     // Get the value of the name attribute. If this attribute doesn't exists
204     // then it will receive a default one.
205     annotationName = anElement.getAttributeValue("name");
206     if (annotationName == null)
207         annotationName = "UnknownElement";
208     // See if this element has a complexType element inside it
209     org.jdom.Element complexTypeElement = anElement.getChild("complexType",
210                                                              namespace);
211     if (complexTypeElement != null){
212       List complexTypeCildrenList = complexTypeElement.getChildren("attribute",
213                                                                    namespace);
214       Iterator complexTypeCildrenIterator = complexTypeCildrenList.iterator();
215       if (complexTypeCildrenIterator.hasNext())
216         featureSchemaSet = new LinkedHashSet<FeatureSchema>();
217       while (complexTypeCildrenIterator.hasNext()) {
218         org.jdom.Element childElement =
219                     (org.jdom.ElementcomplexTypeCildrenIterator.next();
220         createAndAddFeatureSchemaObject(childElement);
221       }// end while
222     }// end if
223   // createAnnoatationSchemaObject
224 
225   /** This method creates and adds a FeatureSchema object to the current
226     * AnnotationSchema one.
227     @param anAttributeElement is an XSchema attribute element
228     */
229   public void createAndAddFeatureSchemaObject(org.jdom.Element
230                                                           anAttributeElement) {
231     String featureName = null;
232     Class<?> featureType = null;
233     String featureUse  = null;
234     String featureValue = null;
235     Set    featurePermittedValuesSet = null;
236 
237     // Get the value of the name attribute. If this attribute doesn't exists
238     // then it will receive a default one.
239     featureName = anAttributeElement.getAttributeValue("name");
240     if (featureName == null)
241       featureName = "UnknownFeature";
242 
243     // See if it has a type attribute associated
244     String featureTypeName = anAttributeElement.getAttributeValue("type");
245     if (featureTypeName != null)
246       // Set it to the corresponding Java type
247       featureType = xSchema2JavaMap.get(featureTypeName);
248 
249     // Get the value of use attribute
250     featureUse = anAttributeElement.getAttributeValue("use");
251     if (featureUse == null)
252       // Set it to the default value
253       featureUse = "optional";
254 
255     // Get the value of value attribute
256     featureValue = anAttributeElement.getAttributeValue("value");
257     if (featureValue == null)
258       featureValue = "";
259 
260     // Let's check if it has a simpleType element inside
261     org.jdom.Element simpleTypeElement  =
262                                   anAttributeElement.getChild("simpleType",
263                                                               namespace);
264 
265     // If it has (!= null) then check to see if it has a restrictionElement
266     if (simpleTypeElement != null) {
267       org.jdom.Element restrictionElement =
268                               simpleTypeElement.getChild("restriction",
269                                                          namespace);
270       if (restrictionElement != null) {
271         // Get the type attribute for restriction element
272         featureTypeName = restrictionElement.getAttributeValue("base");
273         if (featureTypeName == nullfeatureTypeName = "string";
274         // Set it to the corresponding Java type
275         featureType =  xSchema2JavaMap.get(featureTypeName);
276 
277         // Check to see if there are any enumeration elements inside
278         List enumerationElementChildrenList =
279                                  restrictionElement.getChildren("enumeration",
280                                                                 namespace);
281         Iterator enumerationChildrenIterator =
282                                 enumerationElementChildrenList.iterator();
283 
284         // Check if there is any enumeration element in the list
285         if (enumerationChildrenIterator.hasNext())
286             featurePermittedValuesSet = new HashSet();
287         while (enumerationChildrenIterator.hasNext()) {
288           org.jdom.Element enumerationElement =
289                         (org.jdom.ElementenumerationChildrenIterator.next();
290           String permissibleValue =
291                             enumerationElement.getAttributeValue("value");
292           // Add that value to the featureSchema possible values set.
293           featurePermittedValuesSet.add(permissibleValue);
294         }// end while
295       }// end if( restrictionElement != null)
296     }// end if (simpleTypeElement != null)
297 
298     // If it doesn't have a simpleTypeElement inside and featureType is null or
299     // it wasn't recognised, then we set the default type to string.
300     if (simpleTypeElement == null && featureType == null )
301       featureType = xSchema2JavaMap.get("string");
302 
303     // Create an add a featureSchema object
304     FeatureSchema featureSchema = new FeatureSchema(
305                                                    featureName,
306                                                    featureType,
307                                                    featureValue,
308                                                    featureUse,
309                                                    featurePermittedValuesSet);
310     featureSchemaSet.add(featureSchema);
311   // createAndAddFeatureSchemaObject
312 
313   /** @return a String containing the XSchema document representing
314     *  an AnnotationSchema object.
315     */
316   public String toXSchema(){
317     StringBuffer schemaString = new StringBuffer();
318     schemaString.append("<?xml version=\"1.0\"?>\n" +
319                    "<schema xmlns=\"http://www.w3.org/2000/10/XMLSchema\">\n"+
320                    " <element name=\"" + annotationName + "\"");
321 
322     if (featureSchemaSet == null)
323       schemaString.append("/>\n");
324     else {
325       schemaString.append(">\n  <complexType>\n");
326       for(FeatureSchema fs : featureSchemaSet){
327         schemaString.append(fs.toXSchema(java2xSchemaMap));
328       }
329       schemaString.append("  </complexType>\n");
330       schemaString.append(" </element>\n");
331     }// end if else
332     schemaString.append("</schema>\n");
333     return schemaString.toString();
334   }// toXSchema
335 // AnnotationSchema
336