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