001 /*
002 * LinearDefinition.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 * borislav popov 02/2002
013 *
014 * $Id: LinearDefinition.java 12919 2010-08-03 10:31:37Z valyt $
015 */
016 package gate.creole.gazetteer;
017
018 import java.io.*;
019 import java.net.MalformedURLException;
020 import java.net.URL;
021 import java.util.*;
022
023 import gate.creole.ResourceInstantiationException;
024 import gate.util.BomStrippingInputStreamReader;
025 import gate.util.Files;
026
027
028 /** Represents a Linear Definition [lists.def] file <br>
029 * The normal usage of the class will be
030 * * construct it
031 * * setURL
032 * * load
033 * * change
034 * * store
035 */
036 public class LinearDefinition extends gate.creole.AbstractLanguageResource
037 implements List {
038
039 private static final long serialVersionUID = 4050479036709221175L;
040
041 /** the default encoding of the definition */
042 private final static String ENCODING = "UTF-8";
043
044 /** the list of nodes */
045 private List nodes = new ArrayList();
046
047 /** the URL of the definition */
048 private URL url;
049
050 /** set of lists as strings*/
051 private List lists = new ArrayList();
052
053 /**the encoding of the list */
054 private String encoding = "UTF-8";
055
056 /** a mapping between a list and a node */
057 private Map nodesByList = new HashMap();
058
059 /** a map of gazetteer lists by nodes. this is loaded on loadLists*/
060 private Map gazListsByNode = new HashMap();
061
062 /** flag whether the definition has been modified after loading */
063 private boolean isModified = false;
064
065 /** the separator used to delimit feature name-value pairs in gazetteer lists */
066 private String separator;
067
068 public LinearDefinition() {
069 }
070
071 /** Sets the encoding of the linear def
072 * @param encod the encoding to be set */
073 public void setEncoding(String encod) {
074 encoding = encod;
075 }
076
077 /** Gets the encoding of the linear def
078 * @return the encoding of the list*/
079 public String getEncoding() {
080 return encoding;
081 }
082
083 /**
084 * Loads the gazetteer lists and maps them to the nodes
085 * @return a map of nodes vs GazetteerLists
086 * @throws ResourceInstantiationException when the resource cannot be created
087 */
088 public Map loadLists()
089 throws ResourceInstantiationException {
090 return loadLists(false);
091 }
092
093 /**
094 * Loads the gazetteer lists and maps them to the nodes
095 * @return a map of nodes vs GazetteerLists
096 * @param isOrdered true if the feature maps used should be ordered
097 * @throws ResourceInstantiationException when the resource cannot be created
098 */
099 public Map loadLists(boolean isOrdered)
100 throws ResourceInstantiationException {
101 try {
102 gazListsByNode = new HashMap();
103 Iterator inodes = nodes.iterator();
104 while (inodes.hasNext()) {
105 LinearNode node = (LinearNode)inodes.next();
106
107 GazetteerList list = new GazetteerList();
108 list.setSeparator(separator);
109 URL lurl = new URL(url,node.getList());
110 list.setURL(lurl);
111 list.setEncoding(encoding);
112 list.load(isOrdered);
113
114 gazListsByNode.put(node,list);
115 } // while inodes
116 } catch (Exception ex) {
117 throw new ResourceInstantiationException(ex);
118 }
119 return gazListsByNode;
120 } // loadLists()
121
122 /** Loads a single gazetteer list given a name
123 * @param listName the name of the list to be loaded
124 * @return the loaded gazetteer list
125 * @throws ResourceInstantiationException*/
126 public GazetteerList loadSingleList(String listName)
127 throws ResourceInstantiationException {
128 GazetteerList list = new GazetteerList();
129 list.setSeparator(separator);
130 try {
131 URL turl = url;
132 if (-1 != url.getProtocol().indexOf("gate")) {
133 turl = gate.util.protocols.gate.Handler.class.getResource(
134 gate.util.Files.getResourcePath() + url.getPath()
135 );
136 } // if gate:path url
137
138
139 try {
140 URL lurl = new URL(url,listName);
141 list.setURL(lurl);
142 list.load();
143 } catch (Exception x) {
144 String path = turl.getPath();
145 int slash = path.lastIndexOf("/");
146 if (-1 != slash ) {
147 path = path.substring(0,slash+1);
148 }
149
150 File f = new File(path+listName);
151
152 if (!f.exists())
153 f.createNewFile();
154
155 URL lurl = new URL(url,listName);
156 list.setURL(lurl);
157 list.load();
158
159 }
160
161
162
163 } catch (MalformedURLException murle ) {
164 throw new ResourceInstantiationException(murle);
165 } catch (IOException ioex) {
166 throw new ResourceInstantiationException(ioex);
167 }
168 return list;
169 } // loadSingleList
170
171 /**Gets the lists by node map
172 * @return a map of nodes vs lists*/
173 public Map getListsByNode(){
174 return gazListsByNode;
175 }
176
177 /** Gets a map of lists names vs nodes
178 * @return a map of lists names vs nodes*/
179 public Map getNodesByListNames() {
180 return nodesByList;
181 }
182
183 /**Gets the value of the isModified flag.
184 * @return true if the definition has been modified */
185 public boolean isModified() {
186 return isModified;
187 }
188
189 public void setModified(boolean modified) {
190 isModified = modified;
191 }
192
193 /**Gets the url of this linear definition
194 * @return the url of this linear definition */
195 public URL getURL() {
196 return url;
197 }
198
199
200 /**Sets the url of this linear definition
201 * @param aUrl the url of this linear definition */
202 public void setURL(URL aUrl) {
203 url = aUrl;
204 }
205
206 /**
207 * Loads linear definition if url is set
208 */
209 public void load() throws ResourceInstantiationException {
210 if (null == url) {
211 throw new ResourceInstantiationException("URL not set (null).");
212 }
213 try {
214 BufferedReader defReader =
215 new BomStrippingInputStreamReader((url).openStream(), ENCODING);
216
217 String line;
218 LinearNode node;
219 while (null != (line = defReader.readLine())) {
220 node = new LinearNode(line);
221 this.add(node);
222 } //while
223
224 defReader.close();
225 isModified = false;
226 } catch (Exception x){
227 throw new ResourceInstantiationException(x);
228 }
229 } // load();
230
231 /**
232 * Stores this to a definition file.
233 */
234 public void store() throws ResourceInstantiationException{
235 if (null == url) {
236 throw new ResourceInstantiationException("URL not set.(null)");
237 }
238 try {
239 URL tempUrl = url;
240 if (-1 != url.getProtocol().indexOf("gate")) {
241 tempUrl = gate.util.protocols.gate.Handler.class.getResource(
242 gate.util.Files.getResourcePath() + url.getPath()
243 );
244 } // if gate:path url
245
246 File fileo = Files.fileFromURL(tempUrl);
247 fileo.delete();
248 BufferedWriter defWriter = new BufferedWriter(new FileWriter(fileo));
249 Iterator inodes = nodes.iterator();
250 while (inodes.hasNext()) {
251 defWriter.write(inodes.next().toString());
252 defWriter.newLine();
253 }
254 defWriter.close();
255 isModified = false;
256 } catch(Exception x) {
257 throw new ResourceInstantiationException(x);
258 }
259
260 } // store();
261
262 /**
263 * Gets gazetteer lists of this definition.
264 * note that a new list is created so the adding and removing of lists will
265 * not affect the internal members. Also there is no setLists method since the leading
266 * member of the class is nodes, and lists cannot be added individually without being
267 * associated with a node.
268 * @return a list of the gazetteer lists names
269 */
270 public List getLists() {
271 return new ArrayList(lists);
272 }
273
274 /** get the nodes of the definition as a list
275 * @return the list of nodes */
276 public List getNodes() {
277 return new ArrayList(nodes);
278 }
279
280
281 /** Gets the set of all major types in this definition
282 * @return the set of all major types present in this definition*/
283 public Set getMajors() {
284 Set result = new HashSet();
285 for ( int i = 0 ; i < nodes.size() ; i++ )
286 {
287 String maj = ((LinearNode)nodes.get(i)).getMajorType();
288 if (null!= maj)
289 result.add(maj);
290 }
291 return result;
292 } // getMajors
293
294 /** Gets the set of all minor types in this definition
295 * @return the set of all minor types present in this definition*/
296 public Set getMinors() {
297 Set result = new HashSet();
298 for ( int i = 0 ; i < nodes.size() ; i++ ) {
299 String min = ((LinearNode)nodes.get(i)).getMinorType();
300 if (null!=min)
301 result.add(min);
302 }
303 result.add("");
304 return result;
305 } // getMinors()
306
307 /** Gets the set of all languages in this definition
308 * @return the set of all languages present in this definition*/
309 public Set getLanguages() {
310 Set result = new HashSet();
311 for ( int i = 0 ; i < nodes.size() ; i++ ) {
312 String lang = ((LinearNode)nodes.get(i)).getLanguage();
313 if (null!=lang)
314 result.add(lang);
315 }
316 result.add("");
317 return result;
318 } // getMinors()
319
320
321 /*---implementation of interface java.util.List---*/
322 public boolean addAll(int index, Collection c) {
323 int size = nodes.size();
324 Iterator iter = c.iterator();
325 Object o;
326 while (iter.hasNext()) {
327 o = iter.next();
328 if (o instanceof LinearNode) {
329 add(index,o);
330 } // instance of linearnode
331 } // while
332
333 boolean result = (size != nodes.size());
334 isModified |= result;
335 return result;
336 }
337
338 public Object get(int index) {
339 return nodes.get(index);
340 }
341
342 public Object set(int index, Object element) {
343 throw new UnsupportedOperationException("this method has not been implemented");
344 }
345
346 public void add(int index, Object o) {
347 if (o instanceof LinearNode) {
348 String list = ((LinearNode)o).getList();
349 if (!nodesByList.containsKey(list)) {
350 try {
351 GazetteerList gl = loadSingleList(list);
352 gazListsByNode.put(o,gl);
353 nodes.add(index,o);
354 nodesByList.put(list,o);
355 lists.add(list);
356 isModified = true;
357 } catch (ResourceInstantiationException x) {
358 // do nothing since the list ain't real
359 }
360 } // if unique
361 } // if a linear node
362 }
363
364 public Object remove(int index) {
365 Object result = null;
366 int size = nodes.size();
367 result = nodes.remove(index);
368 if (null!=result) {
369 String list = ((LinearNode)result).getList();
370 lists.remove(list);
371 nodesByList.remove(list);
372 gazListsByNode.remove(result);
373 isModified |= (size != nodes.size());
374 }
375 return result;
376 }
377
378 public int indexOf(Object o) {
379 return nodes.indexOf(o);
380 }
381
382 public int lastIndexOf(Object o) {
383 return nodes.lastIndexOf(o);
384 }
385
386 public ListIterator listIterator() {
387 throw new UnsupportedOperationException("this method is not implemented");
388 }
389
390 public ListIterator listIterator(int index) {
391 throw new UnsupportedOperationException("this method is not implemented");
392 }
393
394 public List subList(int fromIndex, int toIndex) {
395 return nodes.subList(fromIndex,toIndex);
396 } // class SafeIterator
397
398 public int size() {
399 return nodes.size();
400 }
401
402 public boolean isEmpty() {
403 return 0 == nodes.size();
404 }
405
406 public boolean contains(Object o) {
407 return nodes.contains(o);
408 }
409
410 public Iterator iterator() {
411 return new SafeIterator();
412 }
413
414 public Object[] toArray() {
415 return nodes.toArray();
416 }
417
418 public Object[] toArray(Object[] a) {
419 return nodes.toArray(a);
420 }
421
422 /**
423 * adds a new node, only if its list is new and uniquely mapped to this node.
424 * @param o a node
425 * @return true if the list of node is not already mapped with another node.
426 */
427 public boolean add(Object o) {
428 boolean result = false;
429 if (o instanceof LinearNode) {
430 String list = ((LinearNode)o).getList();
431 if (!nodesByList.containsKey(list)) {
432 try {
433 GazetteerList gl = loadSingleList(list);
434 gazListsByNode.put(o,gl);
435 result = nodes.add(o);
436 nodesByList.put(list,o);
437 lists.add(list);
438 isModified=true;
439 } catch (ResourceInstantiationException x) {
440 result = false;
441 }
442 } // if unique
443 } // if a linear node
444 return result;
445 } // add()
446
447 public boolean remove(Object o) {
448 boolean result = false;
449 int size = nodes.size();
450 if (o instanceof LinearNode) {
451 result = nodes.remove(o);
452 String list = ((LinearNode)o).getList();
453 lists.remove(list);
454 nodesByList.remove(list);
455 gazListsByNode.remove(o);
456 isModified |= (size != nodes.size());
457 } // if linear node
458 return result;
459 }// remove
460
461 public boolean containsAll(Collection c) {
462 return nodes.containsAll(c);
463 }
464
465 public boolean addAll(Collection c) {
466 boolean result = false;
467 Iterator iter = c.iterator();
468 Object o;
469 while (iter.hasNext()) {
470 o = iter.next();
471 if (o instanceof LinearNode) {
472 result |= add(o);
473 } // instance of linearnode
474 } // while
475 return result;
476 } // addAll()
477
478
479 public boolean removeAll(Collection c) {
480 boolean result = false;
481 Iterator iter = c.iterator();
482 Object o;
483 while (iter.hasNext()) {
484 o = iter.next();
485 result |= remove(o);
486 }
487 return result;
488 }// removeAll()
489
490
491 public boolean retainAll(Collection c) {
492 int aprioriSize = nodes.size();
493 List scrap = new ArrayList();
494
495 LinearNode node;
496 Iterator inodes = nodes.iterator();
497 while(inodes.hasNext()) {
498 node = (LinearNode) inodes.next();
499 if (c.contains(node)) {
500 scrap.add(node);
501 }
502 } //for
503
504 removeAll(scrap);
505 isModified |= (aprioriSize != nodes.size());
506 return (aprioriSize != nodes.size());
507 }
508
509
510 public void clear() {
511 nodes.clear();
512 lists.clear();
513 nodesByList.clear();
514 gazListsByNode.clear();
515 isModified = true;
516 }
517
518 public boolean equals(Object o) {
519 boolean result = false;
520 if ( o instanceof LinearDefinition ) {
521 LinearDefinition def = (LinearDefinition) o;
522 result &= nodes.equals(def.nodes);
523 result &= lists.equals(def.lists);
524 result &= nodesByList.equals(def.lists);
525 }// if
526 return result;
527 } // equals()
528
529 /*---end of implementation of interface java.util.List---*/
530
531
532
533
534
535 /*-----------internal classes -------------*/
536
537 /**SafeIterator class provides an iterator which is safe to be iterated and objects removed from it*/
538 private class SafeIterator implements Iterator {
539 private Iterator iter = LinearDefinition.this.nodes.iterator();
540 private boolean removeCalled = false;
541 private Object last = null;
542
543 public boolean hasNext() {
544 return iter.hasNext();
545 }
546
547 public Object next() {
548 removeCalled = false;
549 last = iter.next();
550 return last;
551 }
552
553 public void remove() {
554 if (!removeCalled && null!=last ) {
555 LinearDefinition.this.remove(last);
556 }// if possible remove
557 removeCalled = true;
558 } // remove
559
560 } // class SafeIterator
561
562 /**
563 * @return the separator
564 */
565 public String getSeparator() {
566 return separator;
567 }
568
569 /**
570 * @param separator the separator to set
571 */
572 public void setSeparator(String separator) {
573 this.separator = separator;
574 }
575
576
577 } // class LinearDefinition
|