001: /*
002: * Created on 05-Jan-2006
003: */
004: package uk.org.ponder.rsf.hibernate3;
005:
006: import java.io.Serializable;
007: import java.util.HashMap;
008: import java.util.Iterator;
009: import java.util.Map;
010:
011: import org.hibernate.EntityMode;
012: import org.hibernate.SessionFactory;
013: import org.hibernate.metadata.ClassMetadata;
014: import org.springframework.beans.factory.NoSuchBeanDefinitionException;
015:
016: import uk.org.ponder.beanutil.BeanUtil;
017: import uk.org.ponder.beanutil.entity.NewEntityEntry;
018: import uk.org.ponder.beanutil.entity.NewEntityReceiver;
019: import uk.org.ponder.conversion.StaticLeafParser;
020: import uk.org.ponder.reflect.ReflectiveCache;
021: import uk.org.ponder.rsf.state.entity.EntityNameInferrer;
022: import uk.org.ponder.rsf.state.entity.ObstinateEntityBeanLocator;
023: import uk.org.ponder.saxalizer.SAXalizerMappingContext;
024: import uk.org.ponder.util.UniversalRuntimeException;
025:
026: /**
027: * A form of "DAO" managing a section of the request container namespace
028: * corresponding to all entities of a Hibernate-mapped type. See documentation
029: * on {@link uk.org.ponder.rsf.state.entity.ObstinateEntityBeanLocator} for
030: * details on semantics.
031: *
032: * <p>
033: * Set either "entityClass" or "entityName" to determine the mapped entity and
034: * hence Java class for this locator. Note that the Hibernate entity name
035: * defaults to the unqualified class name
036: * {@link http://docs.jboss.org/ejb3/app-server/HibernateEntityManager/reference/en/html_single/}
037: * (this functionality not supported until re-upgrade to Hibernate 3.x)
038: *
039: * <p>
040: * These are request-scope beans, but not created by RSAC for reasons of
041: * efficiency. These are auto-populated by the StaticHibernateEBM for each
042: * request.
043: *
044: * @author Antranig Basman (amb26@ponder.org.uk)
045: *
046: */
047:
048: public class HibernateEntityBeanLocator implements
049: ObstinateEntityBeanLocator {
050: private Map delivered = new HashMap();
051: private Class clazz;
052: private Class idclazz;
053:
054: private HibernateAlterationWrapper haw;
055: private ReflectiveCache reflectivecache;
056: private SessionFactory sessionfactory;
057: private ClassMetadata classmetadata;
058: private StaticLeafParser parser;
059: private NewEntityReceiver entityreceiver;
060: private EntityNameInferrer entitynameinferrer;
061:
062: private String entityname;
063:
064: // One request-scope dependency. Basically we must have some, or could not
065: // resolve the Session.
066: public void setHibernateAlterationWrapper(
067: HibernateAlterationWrapper haw) {
068: this .haw = haw;
069: }
070:
071: // Two application-scope dependencies
072: public void setSessionFactory(SessionFactory sessionfactory) {
073: this .sessionfactory = sessionfactory;
074: }
075:
076: public void setMappingContext(SAXalizerMappingContext mappingcontext) {
077: this .reflectivecache = mappingcontext.getReflectiveCache();
078: this .parser = mappingcontext.saxleafparser;
079: }
080:
081: public void setEntityNameInferrer(
082: EntityNameInferrer entitynameinferrer) {
083: this .entitynameinferrer = entitynameinferrer;
084: }
085:
086: private void setClassMetadata(ClassMetadata classmetadata) {
087: this .classmetadata = classmetadata;
088: this .idclazz = classmetadata.getIdentifierType()
089: .getReturnedClass();
090: }
091:
092: public void setEntityClass(Class clazz) {
093: this .clazz = clazz;
094: entityname = entitynameinferrer.getEntityName(clazz);
095: ClassMetadata classmeta = sessionfactory
096: .getClassMetadata(entityname);
097: if (classmeta == null) {
098: classmeta = sessionfactory.getClassMetadata(clazz);
099: entityname = clazz.getName();
100: }
101: if (classmeta == null) {
102: throw new IllegalArgumentException(
103: "Unknown class metadata in SessionFactory for entity "
104: + entityname);
105: }
106: setClassMetadata(classmeta);
107: }
108:
109: public void setNewEntityReceiver(NewEntityReceiver entityreceiver) {
110: this .entityreceiver = entityreceiver;
111: }
112:
113: public Class getIDClass() {
114: return idclazz;
115: }
116:
117: /*
118: * Not supported under Hibernate 2.x public void setEntityName(String
119: * entityname) { try {
120: * setClassMetadata(sessionfactory.getClassMetadata(entityname)); } catch
121: * (HibernateException he) { throw UniversalRuntimeException.accumulate(he,
122: * "Error locating class metadata for entity" + entityname); } this.clazz =
123: * classmetadata.getMappedClass(// EntityMode.POJO ); }
124: */
125: public Serializable getID(Object idfor) {
126: return classmetadata.getIdentifier(idfor, EntityMode.POJO);
127: }
128:
129: public String getIDString(Object idfor) {
130: Serializable sez = getID(idfor);
131: // the point of this rendering is that it be the inverse of the parsing
132: // performed in locateBean. I note that Hibernate is not terribly careful
133: // about such things, but given that all IDs in practice are either Int,
134: // Long, or String, it is not terribly important.
135: return parser.render(sez);
136: }
137:
138: private void registerNewEntity(String id, Object newent) {
139: entityreceiver.receiveNewEntity(new NewEntityEntry(newent, id,
140: this ));
141: delivered.put(id, newent);
142: }
143:
144: public Object locateBean(String path) {
145: Object togo = null;
146: // Assume this is even FASTER than Hibernate 1st-level cache :P
147: togo = delivered.get(path);
148: if (togo == null) {
149: if (path.startsWith(BeanUtil.NEW_ENTITY_PREFIX)) {
150: togo = reflectivecache.construct(clazz);
151: registerNewEntity(path, togo);
152: } else {
153: try {
154: Serializable beanid = (Serializable) parser.parse(
155: idclazz, path);
156: togo = haw.getSession().get(entityname, beanid);
157: } catch (Exception e) {
158: throw UniversalRuntimeException.accumulate(e,
159: "Error getting bean with ID " + path
160: + " of " + clazz);
161: }
162: if (togo == null) {
163: throw new NoSuchBeanDefinitionException(path,
164: "No entity of " + clazz + " with ID "
165: + path + " could be found");
166: }
167: }
168: delivered.put(path, togo);
169:
170: }
171: return togo;
172: }
173:
174: public boolean remove(String beanname) {
175: try {
176: Object bean = locateBean(beanname);
177: haw.getSession().delete(entityname, bean);
178: delivered.remove(beanname);
179: } catch (Exception e) {
180: throw UniversalRuntimeException.accumulate(e,
181: "Error removing bean with name " + beanname
182: + " of " + clazz);
183: }
184: return true; // if the bean did not exist, there will be an exception in
185: // any case
186: }
187:
188: public void set(String beanname, Object toset) {
189: if (beanname.startsWith(BeanUtil.NEW_ENTITY_PREFIX)) {
190: registerNewEntity(beanname, toset);
191: } else {
192: try {
193: haw.getSession().update(entityname, toset);
194: } catch (Exception e) {
195: throw UniversalRuntimeException.accumulate(e,
196: "Error updating bean with id " + beanname
197: + " of " + clazz);
198: }
199: delivered.put(beanname, toset);
200: }
201:
202: }
203:
204: /** Returns an iterator of PREVIOUSLY DELIVERED beans */
205: public Iterator iterator() {
206: return delivered.keySet().iterator();
207: }
208:
209: /** Package-protected access to "dead" list of delivered beans */
210: Map getDeliveredBeans() {
211: return delivered;
212: }
213: }
|