|
SimpleFeatureMapImpl |
|
1 /* 2 * SimpleFeatureMapImpl.java 3 * 4 * Copyright (c) 1998-2001, The University of Sheffield. 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Hamish Cunningham, 7/Feb/2000 12 * borislav popov, 1/May/2002 13 * 14 * $Id: SimpleFeatureMapImpl.java,v 1.26 2002/05/01 09:32:04 nasso Exp $ 15 */ 16 17 package gate.util; 18 19 import java.util.*; 20 import java.net.*; 21 22 import gate.*; 23 import gate.event.*; 24 //import gate.creole.*; 25 import gate.creole.ontology.*; 26 27 import com.ontotext.gate.ontology.*; 28 29 /** Simple case of features. */ 30 //>>> DAM: was (derived from HashMap) 31 /* 32 public class SimpleFeatureMapImpl extends HashMap implements FeatureMap 33 */ 34 //=== DAM: FeatArray optimization, now derived from SimpleMapImpl 35 public class SimpleFeatureMapImpl 36 extends SimpleMapImpl 37 // extends HashMap 38 implements FeatureMap, java.io.Serializable, java.lang.Cloneable, 39 gate.creole.ANNIEConstants 40 //>>> DAM: end 41 { 42 /** Debug flag */ 43 private static final boolean DEBUG = false; 44 45 46 /** Freeze the serialization UID. */ 47 static final long serialVersionUID = -2747241616127229116L; 48 49 /** Test if <b>this</b> featureMap includes all features from aFeatureMap 50 * @param aFeatureMap object which will be included or not in 51 * <b>this</b> FeatureMap obj.If this param is null then it will return true. 52 * @return <code>true</code> if aFeatureMap is incuded in <b>this</b> obj. 53 * and <code>false</code> if not. 54 */ 55 public boolean subsumes(FeatureMap aFeatureMap){ 56 // null is included in everything 57 if (aFeatureMap == null) return true; 58 59 if (this.size() < aFeatureMap.size()) return false; 60 61 SimpleFeatureMapImpl sfm = (SimpleFeatureMapImpl)aFeatureMap; 62 63 Object key; 64 Object keyValueFromAFeatureMap; 65 Object keyValueFromThis; 66 67 for (int i = 0; i < sfm.count; i++) { 68 key = sfm.theKeys[i]; 69 keyValueFromAFeatureMap = sfm.theValues[i]; 70 int v = super.getSubsumeKey(key); 71 if (v < 0) return false; 72 keyValueFromThis = theValues[v];//was: get(key); 73 74 if ( (keyValueFromThis == null && keyValueFromAFeatureMap != null) || 75 (keyValueFromThis != null && keyValueFromAFeatureMap == null) 76 ) return false; 77 78 /*ontology aware subsume implementation 79 ontotext.bp*/ 80 if ((keyValueFromThis != null) && (keyValueFromAFeatureMap != null)) { 81 82 if ( key.equals(LOOKUP_CLASS_FEATURE_NAME) ) { 83 /* ontology aware processing */ 84 Object sfmOntoObj = sfm.get(LOOKUP_ONTOLOGY_FEATURE_NAME); 85 Object thisOntoObj = this.get(LOOKUP_ONTOLOGY_FEATURE_NAME); 86 if (null!=sfmOntoObj && null!= thisOntoObj) { 87 if (sfmOntoObj.equals(thisOntoObj)) { 88 boolean doSubsume = ontologySubsume( 89 sfmOntoObj.toString(), 90 keyValueFromAFeatureMap.toString(), 91 keyValueFromThis.toString()); 92 if (!doSubsume ) { 93 return false; 94 } 95 } // if ontologies are with the same url 96 } //if not null objects 97 } else { 98 /* processing without ontology awareness */ 99 if (!keyValueFromThis.equals(keyValueFromAFeatureMap)) return false; 100 } // else 101 102 } // if 103 } // for 104 105 return true; 106 }//subsumes() 107 108 /** Tests if <b>this</b> featureMap object includes aFeatureMap but only 109 * for the those features present in the aFeatureNamesSet. 110 * @param aFeatureMap which will be included or not in <b>this</b> 111 * FeatureMap obj.If this param is null then it will return true. 112 * @param aFeatureNamesSet is a set of strings representing the names of the 113 * features that would be considered for subsumes. If aFeatureNamesSet is 114 * <b>null</b> then subsumes(FeatureMap) will be called. 115 * @return <code>true</code> if all features present in the aFeaturesNameSet 116 * from aFeatureMap are included in <b>this</b> obj, or <code>false</code> 117 * otherwise. 118 */ 119 public boolean subsumes(FeatureMap aFeatureMap, Set aFeatureNamesSet){ 120 // This means that all features are taken into consideration. 121 if (aFeatureNamesSet == null) return this.subsumes(aFeatureMap); 122 // null is included in everything 123 if (aFeatureMap == null) return true; 124 // This means that subsumes is supressed. 125 if (aFeatureNamesSet.isEmpty()) return true; 126 127 SimpleFeatureMapImpl sfm = (SimpleFeatureMapImpl)aFeatureMap; 128 129 Object key; 130 Object keyValueFromAFeatureMap; 131 Object keyValueFromThis; 132 133 for (int i = 0; i < sfm.count; i++) { 134 key = sfm.theKeys[i]; 135 136 if (!aFeatureNamesSet.contains(key)) 137 continue; 138 139 keyValueFromAFeatureMap = sfm.theValues[i]; 140 keyValueFromThis = get(key); 141 142 if ( (keyValueFromThis == null && keyValueFromAFeatureMap != null) || 143 (keyValueFromThis != null && keyValueFromAFeatureMap == null) 144 ) return false; 145 146 if ((keyValueFromThis != null) && (keyValueFromAFeatureMap != null)) { 147 if ( key.equals(LOOKUP_CLASS_FEATURE_NAME) ) { 148 /* ontology aware processing */ 149 if (!aFeatureNamesSet.contains(LOOKUP_ONTOLOGY_FEATURE_NAME)) 150 continue; 151 152 Object sfmOntoObj = sfm.get(LOOKUP_ONTOLOGY_FEATURE_NAME); 153 Object thisOntoObj = this.get(LOOKUP_ONTOLOGY_FEATURE_NAME); 154 if (null!=sfmOntoObj && null!= thisOntoObj) { 155 if (sfmOntoObj.equals(thisOntoObj)) { 156 if (! ontologySubsume( 157 sfmOntoObj.toString(), 158 keyValueFromAFeatureMap.toString(), 159 keyValueFromThis.toString())) 160 return false; 161 } // if ontologies are with the same url 162 } //if not null objects 163 } else { 164 /*processing without ontology awareness*/ 165 if (!keyValueFromThis.equals(keyValueFromAFeatureMap)) return false; 166 } //else 167 } // if values not null 168 } // for 169 170 return true; 171 }// subsumes() 172 173 174 /** 175 * Overriden to fire events, so that the persistent objects 176 * can keep track of what's updated 177 */ 178 public Object put(Object key, Object value) { 179 Object result = super.put(key, value); 180 this.fireMapUpdatedEvent(); 181 return result; 182 } // put 183 184 /** 185 * Overriden to fire events, so that the persistent objects 186 * can keep track of what's updated 187 */ 188 public Object remove(Object key) { 189 Object result = super.remove(key); 190 this.fireMapUpdatedEvent(); 191 return result; 192 } // remove 193 194 public void clear() { 195 super.clear(); 196 //tell the world if they're listening 197 this.fireMapUpdatedEvent(); 198 } // clear 199 200 // Views 201 public Object clone() { 202 return super.clone(); 203 } //clone 204 205 public boolean equals(Object o) { 206 return super.equals(o); 207 } // equals 208 209 //////////////////THE EVENT HANDLING CODE////////////// 210 //Needed so an annotation can listen to its features// 211 //and update correctly the database////////////////// 212 private transient Vector mapListeners; 213 /** 214 * Removes a gate listener 215 */ 216 public synchronized void removeFeatureMapListener(FeatureMapListener l) { 217 if (mapListeners != null && mapListeners.contains(l)) { 218 Vector v = (Vector) mapListeners.clone(); 219 v.removeElement(l); 220 mapListeners = v; 221 } 222 } //removeFeatureMapListener 223 /** 224 * Adds a gate listener 225 */ 226 public synchronized void addFeatureMapListener(FeatureMapListener l) { 227 Vector v = mapListeners == null ? new Vector(2) : (Vector)mapListeners.clone(); 228 if (!v.contains(l)) { 229 v.addElement(l); 230 mapListeners = v; 231 } 232 } //addFeatureMapListener 233 /** 234 * 235 * @param e 236 */ 237 protected void fireMapUpdatedEvent () { 238 if (mapListeners != null) { 239 Vector listeners = mapListeners; 240 int count = listeners.size(); 241 if (count == 0) return; 242 for (int i = 0; i < count; i++) 243 ((FeatureMapListener) listeners.elementAt(i)).featureMapUpdated(); 244 } 245 }//fireMapUpdatedEvent 246 247 248 /**ontology enhanced subsume 249 * @param ontoUrl the url of the ontology to be used 250 * @return true if value1 subsumes value2 in the specified ontology */ 251 protected boolean ontologySubsume(String ontoUrl,String value1,String value2) { 252 boolean result = false; 253 try { 254 URL url; 255 try { 256 url = new URL(ontoUrl); 257 } catch (MalformedURLException e){ 258 throw new RuntimeException( 259 "\nin SimpleFeatureMapImpl on ontologySubsume()\n" 260 +e.getMessage()+"\n"); 261 } 262 263 /* GET ONTOLOGY BY URL : a bit tricky reference 264 since the behaviour behind the getOntology method is 265 certainly static. 266 : should be temporary */ 267 Ontology o = new OntologyImpl().getOntology(url); 268 269 OClass c1 = o.getClassByName(value1); 270 OClass c2 = o.getClassByName(value2); 271 272 if (null!= c1 && null!= c2) { 273 if (c1.equals(c2)) { 274 result = true; 275 } else { 276 Set subs1; 277 try { 278 subs1 = c1.getSubClasses(OClass.TRANSITIVE_CLOSURE); 279 } catch (gate.creole.ontology.NoSuchClosureTypeException x) { 280 throw new gate.creole.ResourceInstantiationException(x); 281 } 282 if (subs1.contains(c2)) 283 result = true; 284 } // else 285 } // if not null classes 286 } catch (gate.creole.ResourceInstantiationException x) { 287 x.printStackTrace(Err.getPrintWriter()); 288 } 289 return result; 290 } // ontologySubsume 291 292 } // class SimpleFeatureMapImpl 293 294
|
SimpleFeatureMapImpl |
|