GazetteerListsCollector.java
001 package gate.creole;
002 
003 import gate.Annotation;
004 import gate.AnnotationSet;
005 import gate.creole.gazetteer.Gazetteer;
006 import gate.creole.gazetteer.GazetteerList;
007 import gate.creole.gazetteer.GazetteerNode;
008 import gate.creole.gazetteer.LinearNode;
009 import gate.creole.gazetteer.Lookup;
010 import gate.util.GateRuntimeException;
011 import gate.util.InvalidOffsetException;
012 import gate.util.Out;
013 
014 import java.io.BufferedWriter;
015 import java.io.FileOutputStream;
016 import java.io.IOException;
017 import java.io.OutputStreamWriter;
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Map;
023 import java.util.Set;
024 import java.util.StringTokenizer;
025 
026 public class GazetteerListsCollector extends AbstractLanguageAnalyser {
027 
028   private static final long serialVersionUID = -4124586772112530437L;
029 
030   private static String PERSON_ANNOT_NAME = "PER";
031 
032   @Override
033   public void execute() throws gate.creole.ExecutionException {
034     // reinitialise the stats
035     statsPerType = new HashMap<String, Map<String, Integer>>();
036 
037     // check the input
038     if(document == null) {
039       throw new ExecutionException("No document to process!");
040     }
041 
042     if(gazetteer == null) {
043       throw new ExecutionException("No gazetteer set!");
044     }
045 
046     // if no annotation types given, then exit
047     if((this.annotationTypes == null|| annotationTypes.isEmpty()) {
048       Out.prln("Gazetteer Lists Collector Warning: No annotation types given for processing");
049       return;
050     }
051 
052     // get the annotations from document
053     if((markupSetName == null|| (markupSetName.equals("")))
054       allAnnots = document.getAnnotations();
055     else allAnnots = document.getAnnotations(markupSetName);
056 
057     // if none found, print warning and exit
058     if((allAnnots == null|| allAnnots.isEmpty()) {
059       Out.prln("Gazetteer Lists Collector Warning: No annotations found for processing");
060       return;
061     }
062 
063     // collect the stats for each annotation type
064     for(int i = 0; i < annotationTypes.size(); i++) {
065       AnnotationSet annots = allAnnots.get(annotationTypes.get(i));
066       if(annots == null || annots.isEmpty()) continue;
067       statsPerType.put(annotationTypes.get(i)new HashMap<String, Integer>());
068       collectLists(annots, annotationTypes.get(i));
069     }
070 
071     // print out the stats in log files
072     printStats();
073 
074     // save the updated gazetteer lists now
075     Map<LinearNode, GazetteerList> theLists =
076             gazetteer.getLinearDefinition().getListsByNode();
077     Iterator<LinearNode> iter1 = theLists.keySet().iterator();
078     while(iter1.hasNext()) {
079       GazetteerList theList = theLists.get(iter1.next());
080       try {
081         if(theList.isModified()) theList.store();
082       catch(ResourceInstantiationException ex) {
083         throw new GateRuntimeException(ex.getMessage());
084       }
085     }
086 
087   }
088 
089   public void setMarkupASName(String newMarkupASName) {
090     markupSetName = newMarkupASName;
091   }
092 
093   public String getMarkupASName() {
094     return markupSetName;
095   }
096 
097   /**
098    * get the types of the annotation
099    
100    @return type of the annotation
101    */
102   public List<String> getAnnotationTypes() {
103     return annotationTypes;
104   }// getAnnotationTypes
105 
106   /**
107    * set the types of the annotations
108    
109    @param newType
110    */
111   public void setAnnotationTypes(List<String> newType) {
112     annotationTypes = newType;
113   }// setAnnotationTypes
114 
115   public Gazetteer getGazetteer() {
116     return gazetteer;
117   }
118 
119   public void setGazetteer(Gazetteer theGaz) {
120     gazetteer = theGaz;
121   }
122 
123   public void setTheLanguage(String language) {
124     theLanguage = language;
125   }
126 
127   public String getTheLanguage() {
128     return theLanguage;
129   }
130 
131   protected void collectLists(AnnotationSet annots, String annotType) {
132     Iterator<Annotation> iter = annots.iterator();
133     String listName = "";
134     GazetteerList theList = null;
135     Iterator<GazetteerList> theListsIter =
136             gazetteer.getLinearDefinition().getListsByNode().values()
137                     .iterator();
138     while(theListsIter.hasNext() && listName.equals("")) {
139       theList = theListsIter.next();
140       if(theList.getURL().toExternalForm().endsWith(annotType + ".lst"))
141         listName = theList.getURL().toExternalForm();
142     }
143     while(iter.hasNext()) {
144       Annotation annot = iter.next();
145       String text = "";
146       List<String> strings = new ArrayList<String>();
147       try {
148         text =
149                 document.getContent()
150                         .getContent(annot.getStartNode().getOffset(),
151                                 annot.getEndNode().getOffset()).toString();
152         // tokenise the text and save for the future if we need it
153         StringTokenizer tok =
154                 new StringTokenizer(text, "\n\r.|();-?!\t"false);
155         while(tok.hasMoreTokens())
156           strings.add(tok.nextToken());
157         // then replace the line breaks with spaces for the gazetteer
158         text = text.replace('\r'' ');
159         text = text.replace('\n'' ');
160         text = text.replace('\t'' ');
161 
162       catch(InvalidOffsetException ex) {
163         throw new GateRuntimeException(ex.getMessage());
164       }
165 
166       // collect stats for the string
167       if(statsPerType.get(annotType).containsKey(text))
168         statsPerType.get(annotType).put(
169                 text,
170                 new Integer(
171                         statsPerType.get(annotType).get(text).intValue() 1));
172       else statsPerType.get(annotType).put(text, new Integer(1));
173 
174       // also collect stats for the individual tokens in the name to
175       // identify the most
176       // frequent tokens across names
177       if(strings.size() 1) {
178         for(int i = 0; i < strings.size(); i++) {
179           String theString = strings.get(i);
180           // collect stats for the string
181           if(statsPerType.get(annotType).containsKey(theString))
182             statsPerType.get(annotType).put(
183                     theString,
184                     new Integer(statsPerType.get(annotType).get(theString)
185                             .intValue() 1));
186           else statsPerType.get(annotType).put(theString, new Integer(1));
187         }
188       }
189 
190       // first we check whether the text is already in the gazetteer
191       Set<Lookup> lookupResult = gazetteer.lookup(text);
192       if(lookupResult != null && lookupResult.size() 0continue;
193       // if not, then we add it
194       gazetteer.add(text, new Lookup(listName, annotType, "inferred",
195               theLanguage));
196       // theList.add(text + document.getSourceUrl().toString());
197       theList.add(new GazetteerNode(text));
198 
199       // for persons we want also to add their individual names to the
200       // list
201       if(annotType.equals(PERSON_ANNOT_NAME&& strings.size() 1) {
202         for(int i = 0; i < strings.size(); i++) {
203           String theString = strings.get(i);
204           Set<Lookup> lookupResult1 = gazetteer.lookup(theString);
205           if(lookupResult1 != null && lookupResult1.size() 0continue;
206           if(theString.length() 3continue;
207           gazetteer.add(theString, new Lookup(listName, annotType, "inferred",
208                   theLanguage));
209           theList.add(new GazetteerNode(theString));
210         }
211       }
212     }
213   }
214 
215   protected void printStats() {
216     try {
217       for(int i = 0; i < annotationTypes.size(); i++) {
218         if(!statsPerType.containsKey(annotationTypes.get(i))) continue;
219         BufferedWriter writer =
220                 new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
221                         annotationTypes.get(i".stats.lst")"UTF-8"));
222         Map<String,Integer> stats = statsPerType.get(annotationTypes.get(i));
223         Iterator<String> stringsIter = stats.keySet().iterator();
224         while(stringsIter.hasNext()) {
225           String string = stringsIter.next();
226           writer.write(string);
227           writer.write("$");
228           writer.write(stats.get(string).toString());
229           writer.newLine();
230         }
231         writer.close();
232       }
233     catch(IOException ioe) {
234       throw new RuntimeException(ioe.getMessage());
235     }// try
236 
237   }
238 
239   /**
240    * The idea is to have this method check if an item is already present
241    * in the gazetteer under this type, and if so, not to add it. It is
242    * not implemented for now.
243    */
244   protected boolean alreadyPresentInGazetteer(String token) {
245     return false;
246   }
247 
248   private String markupSetName = "";
249 
250   private AnnotationSet allAnnots;
251 
252   private List<String> annotationTypes;
253 
254   private Gazetteer gazetteer;
255 
256   private String theLanguage = "";
257 
258   private Map<String, Map<String, Integer>> statsPerType =
259           new HashMap<String, Map<String, Integer>>();
260 }