1
15
16 package gate.creole;
17
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.util.*;
21
22 import org.xml.sax.*;
23 import org.xml.sax.helpers.DefaultHandler;
24
25 import gate.*;
26 import gate.util.*;
27 import gate.xml.SimpleErrorHandler;
28
29
34 public class CreoleXmlHandler extends DefaultHandler {
35
36
41 private Stack contentStack = new Stack();
42
43
44 private ResourceData resourceData;
45
46
47 private ParameterList currentParamList = new ParameterList();
48
49
50 private List currentParamDisjunction = new ArrayList();
51
52
53 private Parameter currentParam;
54
55
56 private Attributes currentAttributes;
57
58
59 private static final boolean DEBUG = false;
60
61
62 private URL sourceUrl;
63
64
67 private URL creoleFileUrl;
68
69
70 private SimpleErrorHandler _seh = new SimpleErrorHandler();
71
72
75 private FeatureMap currentAutoinstanceParams = null;
76
77
80 private List currentAutoinstances = null;
81
82
83
84 private StringBuffer contentBuffer = new StringBuffer("");
85
86
87 private boolean readCharacterStatus = false;
88
89
90 public CreoleXmlHandler(CreoleRegister register, URL directoryUrl,
91 URL creoleFileUrl) {
92 this.register = register;
93 this.sourceUrl = directoryUrl;
94 this.creoleFileUrl = creoleFileUrl;
95 currentParam = new Parameter(this.creoleFileUrl);
96 }
98
100 private CreoleRegister register;
101
102
103 public void startDocument() throws GateSaxException {
104 if(DEBUG) Out.prln("start document");
105 }
107
108 public void endDocument() throws GateSaxException {
109 if(DEBUG) Out.prln("end document");
110 if(! contentStack.isEmpty()) {
111 StringBuffer errorMessage =
112 new StringBuffer("document ended but element stack not empty:");
113 while(! contentStack.isEmpty())
114 errorMessage.append(Strings.getNl()+" "+(String) contentStack.pop());
115 throw new GateSaxException(errorMessage.toString());
116 }
117 }
119
120 private String attributes2String(Attributes atts){
121 StringBuffer strBuf = new StringBuffer("");
122 if (atts == null) return strBuf.toString();
123 for (int i = 0; i < atts.getLength(); i++) {
124 String attName = atts.getQName(i);
125 String attValue = atts.getValue(i);
126 strBuf.append(" ");
127 strBuf.append(attName);
128 strBuf.append("=");
129 strBuf.append(attValue);
130 } return strBuf.toString();
132 }
134
135 public void startElement (String uri, String qName, String elementName,
136 Attributes atts) throws SAXException {
137
138 if(readCharacterStatus) {
140 readCharacterStatus = false;
141 charactersAction(new String(contentBuffer).toCharArray(),0,contentBuffer.length());
142 }
143
144 if(DEBUG) {
145 Out.pr("startElement: ");
146 Out.println(
147 elementName + " " +
148 attributes2String(atts)
149 );
150 }
151
152 if(elementName.toUpperCase().equals("RESOURCE")) {
154 resourceData = new ResourceData();
155 resourceData.setFeatures(Factory.newFeatureMap());
156 currentAutoinstances = new ArrayList();
157 }
159 currentAttributes = atts;
161
162 if (elementName.toUpperCase().equals("AUTOINSTANCE")){
165 currentAutoinstanceParams = Factory.newFeatureMap();
166 }
168 if (elementName.toUpperCase().equals("PARAM")){
171 if (currentAutoinstanceParams == null)
176 currentAutoinstanceParams = Factory.newFeatureMap();
177 String paramName = currentAttributes.getValue("NAME");
179 String paramStrValue = currentAttributes.getValue("VALUE");
180 if (paramName == null)
181 throw new GateRuntimeException ("Found in creole.xml a PARAM element" +
182 " for resource "+ resourceData.getClassName()+ " without a NAME"+
183 " attribute. Check the file and try again.");
184 if (paramStrValue == null)
185 throw new GateRuntimeException("Found in creole.xml a PARAM element"+
186 " for resource "+ resourceData.getClassName()+ " without a VALUE"+
187 " attribute. Check the file and try again.");
188 currentAutoinstanceParams.put(paramName,paramStrValue);
190 }
192 if(elementName.toUpperCase().equals("PARAMETER")) {
194 if(DEBUG) {
195 for(int i=0, len=currentAttributes.getLength(); i<len; i++) {
196 Out.prln(currentAttributes.getLocalName(i));
197 Out.prln(currentAttributes.getValue(i));
198 } } currentParam.comment = currentAttributes.getValue("COMMENT");
201 currentParam.defaultValueString = currentAttributes.getValue("DEFAULT");
202 currentParam.optional =
203 Boolean.valueOf(currentAttributes.getValue("OPTIONAL")).booleanValue();
204 currentParam.name = currentAttributes.getValue("NAME");
205 currentParam.runtime =
206 Boolean.valueOf(currentAttributes.getValue("RUNTIME")).booleanValue();
207 currentParam.itemClassName =
208 currentAttributes.getValue("ITEM_CLASS_NAME");
209 String suffixes = currentAttributes.getValue("SUFFIXES");
211 Set suffiexesSet = null;
212 if (suffixes != null){
213 suffiexesSet = new HashSet();
214 StringTokenizer strTokenizer = new StringTokenizer(suffixes,";");
215 while(strTokenizer.hasMoreTokens()){
216 suffiexesSet.add(strTokenizer.nextToken());
217 } } currentParam.suffixes = suffiexesSet;
220 }else if(elementName.toUpperCase().equals("GUI")){
221 String typeValue = currentAttributes.getValue("TYPE");
222 if (typeValue != null){
223 if (typeValue.toUpperCase().equals("LARGE"))
224 resourceData.setGuiType(ResourceData.LARGE_GUI);
225 if (typeValue.toUpperCase().equals("SMALL"))
226 resourceData.setGuiType(ResourceData.SMALL_GUI);
227 } }
230 if(elementName.toUpperCase().equals("OR")) {
233 if(! currentParamDisjunction.isEmpty()) {
234 currentParamList.addAll(currentParamDisjunction);
235 currentParamDisjunction = new ArrayList();
236 } } }
240
241 private void checkStack(String methodName, String elementName)
242 throws GateSaxException {
243 if(contentStack.isEmpty())
244 throw new GateSaxException(
245 methodName + " called for element " + elementName + " with empty stack"
246 );
247 }
249
254 public void endElement (String uri, String qName, String elementName)
255 throws GateSaxException, SAXException {
256 if(readCharacterStatus) {
258 readCharacterStatus = false;
259 charactersAction(new String(contentBuffer).toCharArray(),0,contentBuffer.length());
260 }
261
262 if(DEBUG) Out.prln("endElement: " + elementName);
263
264 if(elementName.toUpperCase().equals("RESOURCE")) {
266 if(! resourceData.isValid())
268 throw new GateSaxException(
269 "Invalid resource data: " + resourceData.getValidityMessage()
270 );
271
272 resourceData.setXmlFileUrl(creoleFileUrl);
274 register.put(resourceData.getClassName(), resourceData);
276 if(resourceData.isAutoLoading())
278 try {
279 Class resClass = resourceData.getResourceClass();
280 } catch(ClassNotFoundException e) {
285 throw new GateSaxException(
286 "Couldn't load autoloading resource: " +
287 resourceData.getName() + "; problem was: " + e
288 );
289 }
291 if(! currentParamDisjunction.isEmpty()) {
294 currentParamList.addAll(currentParamDisjunction);
295 currentParamDisjunction = new ArrayList();
296 }
298 resourceData.setParameterList(currentParamList);
300 currentParamList = new ParameterList();
301
302 if(DEBUG) Out.println("added: " + resourceData);
303 if ( currentAutoinstances != null && !currentAutoinstances.isEmpty()){
305 Iterator iter = currentAutoinstances.iterator();
306 while (iter.hasNext()){
307 FeatureMap autoinstanceParams = (FeatureMap) iter.next();
308 iter.remove();
309 try {
311 Resource res = Factory.createResource(
312 resourceData.getClassName(), autoinstanceParams);
313 resourceData.makeInstantiationPersistant(res);
314 } catch(ResourceInstantiationException e) {
315 throw new GateSaxException(
316 "Couldn't auto-instantiate resource: " +
317 resourceData.getName() + "; problem was: " + e
318 );
319 } } } currentAutoinstances = null;
323 } else if(elementName.toUpperCase().equals("AUTOINSTANCE")) {
326 if (currentAutoinstanceParams != null)
329 currentAutoinstances.add(currentAutoinstanceParams);
330 } else if(elementName.toUpperCase().equals("PARAM")) {
333 } else if(elementName.toUpperCase().equals("NAME")) {
336 checkStack("endElement", "NAME");
337 resourceData.setName((String) contentStack.pop());
338 } else if(elementName.toUpperCase().equals("JAR")) {
341 checkStack("endElement", "JAR");
342
343 String jarFileName = (String) contentStack.pop();
345 if(resourceData != null) {
346 resourceData.setJarFileName(jarFileName);
347 }
348
349 if(sourceUrl != null) {
351 String sourceUrlName = sourceUrl.toExternalForm();
352 String separator = "/";
353
354 if(sourceUrlName.endsWith(separator))
355 separator = "";
356 URL jarFileUrl = null;
357
358 try {
359 jarFileUrl = new URL(sourceUrlName + separator + jarFileName);
360 if(resourceData != null) {
361 resourceData.setJarFileUrl(jarFileUrl);
362 }
363
364 if(DEBUG) Out.prln("adding URL to classloader: " + jarFileUrl);
366 Gate.getClassLoader().addURL(jarFileUrl);
367 } catch(MalformedURLException e) {
368 throw new GateSaxException("bad URL " + jarFileUrl + e);
369 } } } else if(elementName.toUpperCase().equals("CLASS")) {
374 checkStack("endElement", "CLASS");
375 resourceData.setClassName((String) contentStack.pop());
376 } else if(elementName.toUpperCase().equals("COMMENT")) {
379 checkStack("endElement", "COMMENT");
380 resourceData.setComment((String) contentStack.pop());
381 } else if(elementName.toUpperCase().equals("INTERFACE")) {
384 checkStack("endElement", "INTERFACE");
385 resourceData.setInterfaceName((String) contentStack.pop());
386 } else if(elementName.toUpperCase().equals("ICON")) {
389 checkStack("endElement", "ICON");
390 resourceData.setIcon((String) contentStack.pop());
391 } else if(elementName.toUpperCase().equals("OR")) {
394 currentParamList.add(currentParamDisjunction);
395 currentParamDisjunction = new ArrayList();
396 } else if(elementName.toUpperCase().equals("PARAMETER")) {
399 checkStack("endElement", "PARAMETER");
400 currentParam.typeName = (String) contentStack.pop();
401 currentParamDisjunction.add(currentParam);
402 if(DEBUG)
403 Out.prln("added param: " + currentParam);
404 currentParam = new Parameter(creoleFileUrl);
405 } else if(elementName.toUpperCase().equals("AUTOLOAD")) {
408 resourceData.setAutoLoading(true);
409 } else if(elementName.toUpperCase().equals("PRIVATE")) {
412 resourceData.setPrivate(true);
413 } else if(elementName.toUpperCase().equals("TOOL")) {
416 resourceData.setTool(true);
417 } else if(elementName.toUpperCase().equals("MAIN_VIEWER")) {
420 resourceData.setIsMainView(true);
421 } else if(elementName.toUpperCase().equals("RESOURCE_DISPLAYED")){
424 checkStack("endElement", "RESOURCE_DISPLAYED");
425 String resourceDisplayed = (String) contentStack.pop();
426 resourceData.setResourceDisplayed(resourceDisplayed);
427 Class resourceDisplayedClass = null;
428 try{
429 resourceDisplayedClass = Gate.getClassLoader().
430 loadClass(resourceDisplayed);
431 } catch (ClassNotFoundException ex){
432 throw new GateRuntimeException(
433 "Couldn't get resource class from the resource name :" +
434 resourceDisplayed + " " +ex );
435 } } else if(elementName.toUpperCase().equals("ANNOTATION_TYPE_DISPLAYED")){
439 checkStack("endElement", "ANNOTATION_TYPE_DISPLAYED");
440 resourceData.setAnnotationTypeDisplayed((String) contentStack.pop());
441 } else if(elementName.toUpperCase().equals("GUI")) {
444
445 } else if(elementName.toUpperCase().equals("CREOLE")) {
448 } else if(elementName.toUpperCase().equals("CREOLE-DIRECTORY")) {
451 } else { if(resourceData != null)
455 resourceData.getFeatures().put(
456 elementName.toUpperCase(),
457 ((contentStack.isEmpty()) ? null : (String) contentStack.pop())
458 );
459 }
460
462 }
464
465 public void characters(char [] text,int start,int length) throws SAXException {
466 if(!readCharacterStatus) {
467 contentBuffer = new StringBuffer(new String(text,start,length));
468 } else {
469 contentBuffer.append(new String(text,start,length));
470 }
471 readCharacterStatus = true;
472 }
473
474
477 public void charactersAction(char[] text, int start, int length)
478 throws SAXException {
479 String content = new String(text, start, length).trim();
481 if (content.length() == 0) return;
484 contentStack.push(content);
485 if(DEBUG) Out.println(content);
486 }
488
489 public void ignorableWhitespace(char ch[], int start, int length)
490 throws SAXException {
491 }
493
494 public void error(SAXParseException ex) throws SAXException {
495 _seh.error(ex);
496 }
498
499 public void fatalError(SAXParseException ex) throws SAXException {
500 _seh.fatalError(ex);
501 }
503
504 public void warning(SAXParseException ex) throws SAXException {
505 _seh.warning(ex);
506 }
508 }