LinearDefinition.java
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 (-!= 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 (-!= 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 (-!= 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 = ; 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 = ; 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 = ; 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 (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 (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 == 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 (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 (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 (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 = (LinearNodeinodes.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 instanceof LinearDefinition ) {
521       LinearDefinition def = (LinearDefinitiono;
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