OrthoMatcherHelper.java
001 package gate.creole.orthomatcher;
002 
003 import gate.Annotation;
004 import gate.AnnotationSet;
005 import gate.creole.ExecutionException;
006 import gate.util.InvalidOffsetException;
007 
008 import java.util.Arrays;
009 import java.util.HashSet;
010 import java.util.Iterator;
011 import java.util.Map;
012 import java.util.Set;
013 
014 import org.apache.log4j.Logger;
015 
016 public class OrthoMatcherHelper {
017   
018     protected static final Logger log = Logger.getLogger(OrthoMatcherHelper.class);
019   
020     public static boolean straightCompare(String s1,
021             String s2,
022             boolean matchCase) {
023 
024       boolean matched = false;
025       if (!matchCase)
026         matched = s1.equalsIgnoreCase(s2);
027       else matched =  s1.equals(s2;
028   //  kalina: do not remove, nice for debug
029   //  if (matched && (s2.startsWith("Kenneth") || s1.startsWith("Kenneth")))
030   //  Out.prln("Rule1: Matched " + s1 + "and " + s2);
031       return matched;
032     }
033     
034     /**
035      * Returns true if only one of s1 and s2 is a single character and the two strings match on that
036      * initial
037      */
038     public static boolean initialMatch(String s1, String s2) {
039       return (((s1.length() == 1(s2.length() == 1) ) && (s1.charAt(0== s2.charAt(0)));
040     }
041 
042     /**
043      * Gets the content of an annotation
044      */
045     public static String getStringForSpan(Long start, Long end,gate.Document dthrows ExecutionException {
046         try {
047           return d.getContent().getContent(start, end).toString();
048         }
049         catch (InvalidOffsetException e) {
050           //log.error("Weird offset exception in getStringForSpan", e);
051           throw new ExecutionException(e);
052         }
053     }
054      
055     public static boolean executeDisjunction(Map<Integer,OrthoMatcherRule> allrules, int[] executeRules,String longName,String shortName, boolean mr[]) {
056       
057       boolean result=false;
058       
059       for (int i = 0; i < executeRules.length; i = i + 1) {
060         
061         boolean current=allrules.get(executeRules[i]).value(longName, shortName);
062         mr[executeRules[i]]=current;
063         result=result || current;
064       }
065       
066       return result;
067     }
068     
069     public static Double round2Places(Double input) {
070       return Math.round(input*100.0)/100.0;
071     }
072     
073     /**
074      * It is used for test purposes.
075      * This table shows which rules have fired over a corpus.
076      */
077     public static boolean[] rulesUsedTable=null;
078     
079     static {
080       rulesUsedTable = new boolean[18];
081       for(int i=0;i<rulesUsedTable.length;i++rulesUsedTable[i]=false;
082     }
083     
084     /**
085      * It is used for test purposes.
086      * It sets that a specific rule has returned 'true'. 
087      */
088     public static void usedRule(int rule) {    
089       rulesUsedTable[rule]=true;
090     }
091     
092     /**
093      *  It is used for test purposes.
094      *  It saves which rules have fired(have returned 'true') while processing a corpus
095      *  Must be enabled - uncommented
096      */
097     public static void saveUsedTable() {
098        
099       //Iterator<Map.Entry<Integer, Boolean>> iter = rulesUsedTable.entrySet().iterator();
100       if (rulesUsedTable!=null) {   
101       log.debug("Saving table of used orthomatcher rules:");
102       
103       String table="";
104       
105       for(int i=0;i<rulesUsedTable.length;i++table+="Rule: "+i+" fired: "+rulesUsedTable[i]+"\r\n";
106       
107       log.debug(table);
108       log.debug("End of table of used Orthomatcher rules")
109       }
110       else log.debug("Could not save the table of used orthomatcher rules. This also results when no Orthomatcher rule has returned 'true'.")
111     }
112     
113     /*
114      * Converts a string array to an integer one.
115      */
116     public static int[] convertArrayToInteger(String[] input) {
117     
118          int[] result=new int[input.length];
119          
120          for(int i=0;i<input.length;i++) {
121             result[i= Integer.parseInt(input[i].trim());
122          }
123          
124          return result;
125     }
126     /*
127      * It sorts a list of pairs by the first number which is the start point of an annotation.
128      * It encodes the pair in a single number, sorts by this number and then decodes to the original pair.
129      */
130     public static String SortByStartPosition(String input) {
131       
132       int ceil=100000;//a and b both must be less than ceil
133       
134       String[] pairs = input.trim().split(",");
135       
136       int[] temp=new int[pairs.length];
137       
138       if (pairs.length>1) {
139       
140       int i=0;
141       //encode in temp
142       for(String pair: pairs){
143 
144         String[] s = pair.split(":");
145         int x=Integer.parseInt(s[0].trim())* ceil + Integer.parseInt(s[1].trim());
146         temp[i]=x;
147         i++;
148       }
149 
150       Arrays.sort(temp);
151       
152       //decode from temp
153       String result="";
154       for(int n: temp) {
155         int a = n / ceil;
156         int b = n % ceil;
157         result=result+a+":"+b+", ";
158       }
159       
160       return result;
161       }
162       else return input;//we do not need to sort a single pair
163     }
164     
165     /*
166      * The feature "matches" contains annotation IDs.
167      * This method adds a new feature called "matches_positions" that tells the exact position of each match annotation from "matches".
168      * "matches" contains annotations IDs which are in general different and can not be used for comparison in tools like the Corpus Quality Assurance tool
169      * "matches_positions" can be used to check if the matches really match in for example the Corpus Quality Assurance tool
170      */
171     protected static void setMatchesPositions(AnnotationSet nameAllAnnots) {
172       
173       //get all annotations that have a matches feature
174       Set<String> fNames = new HashSet<String>();
175       fNames.add(gate.creole.ANNIEConstants.ANNOTATION_COREF_FEATURE_NAME);
176       AnnotationSet allMatchesAnnots =
177         nameAllAnnots.get(null, fNames);
178 
179       if (allMatchesAnnots == null || allMatchesAnnots.isEmpty())
180         return;
181 
182       for (Annotation currentMatchAnnot : allMatchesAnnots) {
183           
184           String matchValue=currentMatchAnnot.getFeatures().get(gate.creole.ANNIEConstants.ANNOTATION_COREF_FEATURE_NAME).toString();
185           
186           matchValue = matchValue.substring(1);
187           matchValue = matchValue.substring(0,matchValue.length()-1);
188           
189           String[] annotationsIDs = matchValue.split(",");
190 
191           String matchPositionsValue="";//with the annotations positions
192           String sentinel = ", ";
193           
194           int[] integerIDs = OrthoMatcherHelper.convertArrayToInteger(annotationsIDs);
195           for (int i=0; i<integerIDs.length ; i++) {
196             
197           int id=integerIDs[i];
198           Annotation ann=null;
199           
200           Iterator<Annotation> iter = nameAllAnnots.iterator();
201           
202           //find the current annotation with ID from the match list - in order to get its start and end point
203           if (currentMatchAnnot.getId()==id)
204              ann=currentMatchAnnot; else {
205                 while (iter.hasNext()) {
206                    Annotation a=iter.next();
207                    if (a.getId()==id)
208                    {
209                      ann = a;
210                      break;
211                    }
212                 }
213              }
214           
215           //do the actual job of retrieving the start and end points
216           if (ann!=null) {
217             matchPositionsValue = matchPositionsValue + ann.getStartNode().getOffset()+":"+ann.getEndNode().getOffset()+sentinel;
218           }
219           
220           }//end going through the match ids
221           
222           //sort so that every time we have the "match_positions" generated the same way so that we can compare it
223           matchPositionsValue = OrthoMatcherHelper.SortByStartPosition(matchPositionsValue);
224           
225           //formating 
226           if (matchPositionsValue.endsWith(sentinel)) {
227           matchPositionsValue = matchPositionsValue.substring(0,matchPositionsValue.length()-sentinel.length());
228           }
229           matchPositionsValue = "["+matchPositionsValue+"]";
230           //finally insert the annotation
231           currentMatchAnnot.getFeatures().put("matches_positions", matchPositionsValue);
232           
233         //}
234       //while - going through all the matches annotations(that have a feature "match") and adding the new feature
235     }//matchesPositions
236 
237 
238 }