1 19 20 package org.apache.cayenne.map; 21 22 import java.io.Serializable ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.SortedMap ; 27 import java.util.StringTokenizer ; 28 import java.util.TreeMap ; 29 30 import org.apache.cayenne.CayenneRuntimeException; 31 import org.apache.cayenne.exp.Expression; 32 import org.apache.cayenne.exp.ExpressionException; 33 import org.apache.cayenne.util.CayenneMapEntry; 34 import org.apache.cayenne.util.XMLSerializable; 35 36 42 public abstract class Entity implements CayenneMapEntry, XMLSerializable, Serializable { 43 44 public static final String PATH_SEPARATOR = "."; 45 46 protected String name; 47 protected DataMap dataMap; 48 49 protected SortedMap attributes; 50 protected SortedMap relationships; 51 52 55 public Entity() { 56 this(null); 57 } 58 59 62 public Entity(String name) { 63 this.attributes = new TreeMap (); 64 this.relationships = new TreeMap (); 65 66 setName(name); 67 } 68 69 72 public String getName() { 73 return name; 74 } 75 76 public void setName(String name) { 77 this.name = name; 78 } 79 80 public Object getParent() { 81 return getDataMap(); 82 } 83 84 public void setParent(Object parent) { 85 if (parent != null && !(parent instanceof DataMap)) { 86 throw new IllegalArgumentException ("Expected null or DataMap, got: " + parent); 87 } 88 89 setDataMap((DataMap) parent); 90 } 91 92 95 public DataMap getDataMap() { 96 return dataMap; 97 } 98 99 102 public void setDataMap(DataMap dataMap) { 103 this.dataMap = dataMap; 104 } 105 106 110 public Attribute getAttribute(String attributeName) { 111 return (Attribute) attributes.get(attributeName); 112 } 113 114 118 public void addAttribute(Attribute attribute) { 119 if (attribute.getName() == null) { 120 throw new IllegalArgumentException ("Attempt to insert unnamed attribute."); 121 } 122 123 125 Object existingAttribute = attributes.get(attribute.getName()); 128 if (existingAttribute != null) { 129 if (existingAttribute == attribute) { 130 return; 131 } 132 else { 133 throw new IllegalArgumentException ("An attempt to override attribute '" 134 + attribute.getName() 135 + "'"); 136 } 137 } 138 139 Object existingRelationship = relationships.get(attribute.getName()); 141 if (existingRelationship != null) { 142 throw new IllegalArgumentException ( 143 "Attribute name conflict with existing relationship '" 144 + attribute.getName() 145 + "'"); 146 } 147 148 attributes.put(attribute.getName(), attribute); 149 attribute.setEntity(this); 150 } 151 152 153 public void removeAttribute(String attrName) { 154 attributes.remove(attrName); 155 } 156 157 public void clearAttributes() { 158 attributes.clear(); 159 } 160 161 165 public Relationship getRelationship(String relName) { 166 return (Relationship) relationships.get(relName); 167 } 168 169 170 public void addRelationship(Relationship relationship) { 171 if (relationship.getName() == null) { 172 throw new IllegalArgumentException ("Attempt to insert unnamed relationship."); 173 } 174 175 177 Object existingRelationship = relationships.get(relationship.getName()); 180 if (existingRelationship != null) { 181 if (existingRelationship == relationship) { 182 return; 183 } 184 else { 185 throw new IllegalArgumentException ( 186 "An attempt to override relationship '" 187 + relationship.getName() 188 + "'"); 189 } 190 } 191 192 Object existingAttribute = attributes.get(relationship.getName()); 194 if (existingAttribute != null) { 195 throw new IllegalArgumentException ( 196 "Relationship name conflict with existing attribute '" 197 + relationship.getName() 198 + "'"); 199 } 200 201 relationships.put(relationship.getName(), relationship); 202 relationship.setSourceEntity(this); 203 } 204 205 206 public void removeRelationship(String relName) { 207 relationships.remove(relName); 208 } 209 210 public void clearRelationships() { 211 relationships.clear(); 212 } 213 214 217 public SortedMap getRelationshipMap() { 218 return Collections.unmodifiableSortedMap(relationships); 221 } 222 223 230 public Relationship getAnyRelationship(Entity targetEntity) { 231 if (getRelationships().isEmpty()) { 232 return null; 233 } 234 235 Iterator it = getRelationships().iterator(); 236 while (it.hasNext()) { 237 Relationship r = (Relationship) it.next(); 238 if (r.getTargetEntity() == targetEntity) { 239 return r; 240 } 241 } 242 return null; 243 } 244 245 248 public Collection getRelationships() { 249 return Collections.unmodifiableCollection(relationships.values()); 252 } 253 254 257 public SortedMap getAttributeMap() { 258 return Collections.unmodifiableSortedMap(attributes); 261 } 262 263 266 public Collection getAttributes() { 267 return Collections.unmodifiableCollection(attributes.values()); 270 } 271 272 278 public abstract Expression translateToRelatedEntity( 279 Expression expression, 280 String relationshipPath); 281 282 288 public Object lastPathComponent(Expression pathExp) { 289 Object last = null; 290 Iterator it = resolvePathComponents(pathExp); 291 while (it.hasNext()) { 292 last = it.next(); 293 } 294 295 return last; 296 } 297 298 305 public abstract Iterator resolvePathComponents(Expression pathExp) 306 throws ExpressionException; 307 308 314 public Iterator resolvePathComponents(String path) throws ExpressionException { 315 return new PathIterator(path); 316 } 317 318 final class PathIterator implements Iterator { 321 322 private StringTokenizer toks; 323 private Entity currentEnt; 324 private String path; 325 326 PathIterator(String path) { 327 super(); 328 this.currentEnt = Entity.this; 329 this.toks = new StringTokenizer (path, PATH_SEPARATOR); 330 this.path = path; 331 } 332 333 public boolean hasNext() { 334 return toks.hasMoreTokens(); 335 } 336 337 public Object next() { 338 String pathComp = toks.nextToken(); 339 340 Attribute attr = currentEnt.getAttribute(pathComp); 342 if (attr != null) { 343 if (toks.hasMoreTokens()) { 345 throw new ExpressionException( 346 "Attribute must be the last component of the path: '" 347 + pathComp 348 + "'.", 349 path, 350 null); 351 } 352 353 return attr; 354 } 355 356 Relationship rel = currentEnt.getRelationship(pathComp); 357 if (rel != null) { 358 currentEnt = rel.getTargetEntity(); 359 return rel; 360 } 361 362 StringBuffer buf = new StringBuffer (); 364 buf 365 .append("Can't resolve path component: [") 366 .append(currentEnt.getName()) 367 .append('.') 368 .append(pathComp) 369 .append("]."); 370 throw new ExpressionException(buf.toString(), path, null); 371 } 372 373 public void remove() { 374 throw new UnsupportedOperationException ( 375 "'remove' operation is not supported."); 376 } 377 } 378 379 final MappingNamespace getNonNullNamespace() { 380 MappingNamespace parent = getDataMap(); 381 if (parent == null) { 382 throw new CayenneRuntimeException("Entity '" 383 + getName() 384 + "' has no parent MappingNamespace (such as DataMap)"); 385 } 386 387 return parent; 388 } 389 } 390 | Popular Tags |