4da147f52142da2a1a1c8f612ec62f61c7aa1317
[working/Evergreen.git] / Open-ILS / src / java / org / open_ils / idl / IDLParser.java
1 package org.open_ils.idl;
2
3 import org.opensrf.util.*;
4
5 import java.util.HashMap;
6 import java.util.Set;
7 import java.util.Iterator;
8
9 import java.io.InputStream;
10 import java.io.FileInputStream;
11 import java.io.IOException;
12
13 import javax.xml.stream.*;
14 import javax.xml.stream.events.* ;
15 import javax.xml.namespace.QName;
16
17
18 public class IDLParser {
19
20     public static final String OILS_NS_BASE="http://opensrf.org/spec/IDL/base/v1";
21     public static final String OILS_NS_OBJ="http://open-ils.org/spec/opensrf/IDL/objects/v1";
22     public static final String OILS_NS_OBJ_PREFIX="oils_obj";
23     public static final String OILS_NS_PERSIST="http://open-ils.org/spec/opensrf/IDL/persistence/v1";
24     public static final String OILS_NS_PERSIST_PREFIX="oils_persist";
25     public static final String OILS_NS_REPORTER="http://open-ils.org/spec/opensrf/IDL/reporter/v1";
26     public static final String OILS_NS_REPORTER_PREFIX="reporter";
27
28     /** The source for the IDL XML */
29     InputStream inStream;
30     HashMap<String, IDLObject> IDLObjects;
31     IDLObject current;
32     private int fieldIndex;
33
34     /** If true, we retain the full set of IDL objects in memory.  This is true by default. */
35     private boolean keepIDLObjects;
36
37     private int parsedObjectCount;
38
39     public IDLParser() {
40         IDLObjects = new HashMap<String, IDLObject>();
41         keepIDLObjects = true;
42         parsedObjectCount = 0;
43         fieldIndex = 0;
44     }
45
46     public IDLParser(String fileName) throws IOException {
47         this(new FileInputStream(fileName));
48     }
49
50     public IDLParser(InputStream inStream) {
51         this();
52         this.inStream = inStream;
53     }
54
55
56     /**
57     * Parses the IDL XML
58     */
59     public void parse() throws IOException, IDLException {
60     
61         try {
62             XMLInputFactory factory = XMLInputFactory.newInstance();
63     
64             /** disable as many unused features as possible to speed up the parsing */
65             factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
66             factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
67             factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);
68             factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
69             factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
70     
71     
72         /** create the stream reader */
73             XMLStreamReader reader = factory.createXMLStreamReader(this.inStream);
74             int eventType;
75     
76             while(reader.hasNext()) {
77                 /** cycle through the XML events */
78     
79                 eventType = reader.next();
80     
81                 switch(eventType) {
82     
83                     case XMLEvent.START_ELEMENT:
84                         handleStartElement(reader);
85                         break;
86     
87                     case XMLEvent.END_ELEMENT: 
88                         handleEndElement(reader);
89                         break;
90                 }
91             }
92
93         } catch(javax.xml.stream.XMLStreamException se) {
94             throw new IDLException("Error parsing IDL XML", se);
95         }
96    }
97
98     /**
99     * Returns the IDLObject with the given IDLClass 
100     */
101     public IDLObject getObject(String IDLClass) {
102       return (IDLObject) IDLObjects.get(IDLClass);
103     }
104
105     /**
106      * Returns the full set of IDL objects as a hash from classname to object.
107      * If keepIDLObjects is false, the map will be empty.
108      */
109     public HashMap<String, IDLObject> getIDLObjects() {
110         return IDLObjects;
111     }
112
113     /**
114      * Returns the number of parsed objects, regardless of the keepIDLObjects setting.
115      */
116     public int getObjectCount() {
117         return parsedObjectCount;
118     }
119
120
121     public void handleStartElement(XMLStreamReader reader) {
122
123         if(!OILS_NS_BASE.equals(reader.getNamespaceURI())) return;
124         String localpart = reader.getLocalName();
125     
126         if( "class".equals(localpart) ) {
127             fieldIndex = 0;
128             current = new IDLObject();
129             current.setIDLClass(reader.getAttributeValue(null, "id"));
130             current.setController(reader.getAttributeValue(null, "controller"));
131             String persist = reader.getAttributeValue(OILS_NS_PERSIST, "virtual");
132             current.setIsVirtual("persist".equals(reader.getAttributeValue(OILS_NS_PERSIST, "virtual")));
133             return;
134         }
135     
136         if( "field".equals(localpart) ) {
137             IDLField field = new IDLField();
138             field.setName(reader.getAttributeValue(null, "name"));
139             field.setArrayPos(fieldIndex++);
140             field.setIsVirtual("true".equals(reader.getAttributeValue(OILS_NS_PERSIST, "virtual")));
141             current.addField(field);
142         }
143
144         if( "link".equals(localpart) ) {
145             IDLLink link = new IDLLink();
146             link.setField(reader.getAttributeValue(null, "field"));
147             link.setReltype(reader.getAttributeValue(null, "reltype"));
148             link.setKey(reader.getAttributeValue(null, "key"));
149             link.setMap(reader.getAttributeValue(null, "map"));
150             link.setIDLClass(reader.getAttributeValue(null, "class"));
151             current.addLink(link);
152         }
153     }
154
155     public void handleEndElement(XMLStreamReader reader) throws IDLException {
156
157         if(!OILS_NS_BASE.equals(reader.getNamespaceURI())) return;
158         String localpart = reader.getLocalName();
159
160         if("class".equals(localpart)) {
161
162             if(keepIDLObjects)
163                 IDLObjects.put(current.getIDLClass(), current);
164
165             HashMap fields = current.getFields();
166             String fieldNames[] = new String[fields.size()];
167
168             for(Iterator itr = fields.keySet().iterator(); itr.hasNext(); ) {
169                 String key = (String) itr.next();
170                 IDLField field = (IDLField) fields.get(key);
171                 try {
172                     fieldNames[ field.getArrayPos() ] = field.getName();
173                 } catch(ArrayIndexOutOfBoundsException E) {
174                     String msg = "class="+current.getIDLClass()+";field="+key+
175                         ";fieldcount="+fields.size()+";currentpos="+field.getArrayPos();
176                     throw new IDLException(msg, E);
177                 }
178             }
179
180             OSRFRegistry.registerObject(
181                 current.getIDLClass(), OSRFRegistry.WireProtocol.ARRAY, fieldNames);
182
183             parsedObjectCount++;
184
185             current = null;
186         }
187     }
188
189
190     public String toXML() {
191         StringBuffer sb = new StringBuffer();
192         Set keys = IDLObjects.keySet();
193         Iterator itr = IDLObjects.keySet().iterator();
194         String IDLClass;
195         IDLObject obj;
196         while(itr.hasNext()) {
197             IDLClass = (String) itr.next();
198             obj = IDLObjects.get(IDLClass);
199             obj.toXML(sb);
200         }
201         return sb.toString();
202     }
203 }
204
205
206
207
208
209