View Javadoc

1   package org.starobjects.jpa.runtime.persistence.maps;
2   
3   import org.hibernate.proxy.HibernateProxy;
4   import org.hibernate.proxy.LazyInitializer;
5   import org.nakedobjects.metamodel.adapter.NakedObject;
6   import org.nakedobjects.metamodel.adapter.oid.Oid;
7   import org.nakedobjects.metamodel.spec.NakedObjectSpecification;
8   import org.nakedobjects.metamodel.spec.feature.OneToOneAssociation;
9   import org.nakedobjects.runtime.persistence.adaptermanager.AdapterManagerDefault;
10  import org.nakedobjects.runtime.persistence.adaptermanager.AggregateAdapters;
11  import org.starobjects.jpa.metamodel.facets.object.entity.JpaEntityFacet;
12  import org.starobjects.jpa.metamodel.util.JpaPropertyUtils;
13  import org.starobjects.jpa.runtime.persistence.objectstore.hibspi.ResolveStateUtil;
14  import org.starobjects.jpa.runtime.persistence.oid.JpaOid;
15  import org.starobjects.jpa.runtime.persistence.oid.JpaOidGenerator;
16  import org.starobjects.jpa.runtime.util.JpaOidPropertyUtils;
17  
18  public class JpaAdapterManager extends AdapterManagerDefault {
19  
20      /**
21       * see {@link #createOrRecreateRootAdapter(Object)}.
22       */
23      private long serviceId;
24  
25      public JpaAdapterManager() {
26      // just discovered this commented out. Not sure why.
27      // the tests still pass, so leaving as commented out.
28      // setPojoAdapterMap(new JpaPojoAdapterMap());
29      }
30  
31      /**
32       * Downcast.
33       */
34      @Override
35      public JpaOidGenerator getOidGenerator() {
36          return (JpaOidGenerator) super.getOidGenerator();
37      }
38  
39      @Override
40      protected AggregateAdapters createOrRecreateRootAdapter(final Object pojo) {
41          // will create a transient adapter or a ghost (if persistent) adapter
42          final AggregateAdapters aggregateAdapters = super
43                  .createOrRecreateRootAdapter(pojo);
44  
45          final NakedObject rootAdapter = aggregateAdapters.getRootAdapter();
46  
47          // special handling for services
48          if (rootAdapter.getSpecification().isService()) {
49              final Long id = ++serviceId;
50              syncOidAndConvertToPersistent(rootAdapter, id);
51              ResolveStateUtil.markAsResolved(rootAdapter);
52              return aggregateAdapters;
53          }
54  
55          // otherwise, regular object.
56          updateResolveStateIfPersistent(rootAdapter);
57          return aggregateAdapters;
58      }
59  
60      @Override
61      protected Oid createOid(final Object pojo) {
62          final JpaOid oid = getOidGenerator().createTransientOid(pojo);
63  
64          // we create a throw-away adapter, just to extract the Id of the pojo
65          final NakedObject adapter = getAdapterFactory()
66                  .createAdapter(pojo, oid);
67          initializeOidIfEntity(adapter);
68  
69          return oid;
70      }
71  
72      private void initializeOidIfEntity(final NakedObject adapter) {
73          final NakedObjectSpecification noSpec = adapter.getSpecification();
74  
75          if (!noSpec.containsFacet(JpaEntityFacet.class)) {
76              return;
77          }
78  
79          // Entities always have an Id
80          final OneToOneAssociation idProperty = JpaPropertyUtils
81                  .getIdPropertyFor(noSpec);
82          final NakedObject idAdapter = idProperty.get(adapter);
83  
84          // if the Id is set we infer that the pojo is persistent.
85          if (idAdapter != null) {
86              final Number id = (Number) idAdapter.getObject();
87              final JpaOid oid = (JpaOid) adapter.getOid();
88              convertToPersistentOid(oid, id);
89          }
90      }
91  
92      private void convertToPersistentOid(final JpaOid oid, final Number id) {
93          // ensure Oid is setup correctly.
94          oid.setNewId(id);
95          getOidGenerator().convertTransientToPersistentOid(oid);
96      }
97  
98  
99      private void updateResolveStateIfPersistent(final NakedObject adapter) {
100         if (adapter.getOid().isTransient()) {
101             return;
102         }
103 
104         final Object pojo = adapter.getObject();
105         final LazyInitializer hibernateLazyInitializer = getHibernateLazyInitializer(pojo);
106 
107 
108         // this was a previous approach to try to guess whether the object was
109         // transient or not. But I think it is flawed; we might have eagerly
110         // loaded in the referenced object so there would be no proxy.
111         // instead, see #createOid (called earlier on) which aims to setup the
112         // correct Oid (transient or persistent) from the outset.
113 
114         // // see if we have a proxy
115         // if (hibernateLazyInitializer == null) {
116         // // no, so must be transient
117         // return;
118         // }
119 
120         // yes, so presume is persistent
121 
122         final Long id = JpaOidPropertyUtils.getIdFor(adapter);
123         if (id == null) {
124             // TODO: can't do much here; should we throw an exception instead?
125             return;
126         }
127 
128         // the following isn't needed any more because it is in effect
129         // done in #createOid()
130 
131         // // sync the Oid & make persistent
132         // // it shouldn't be in any maps yet, so can do this safely)
133         // syncOidAndConvertToPersistent(adapter, id);
134 
135         // update the resolve state
136         if (hibernateLazyInitializer != null &&
137                 hibernateLazyInitializer.isUninitialized()) {
138             ResolveStateUtil.markAsGhost(adapter);
139         } else {
140             ResolveStateUtil.markAsResolved(adapter);
141         }
142 
143         return;
144     }
145 
146     private void syncOidAndConvertToPersistent(final NakedObject adapter,
147             final Number id) {
148         final JpaOid oid = (JpaOid) adapter.getOid();
149         convertToPersistentOid(oid, id);
150     }
151 
152     private LazyInitializer getHibernateLazyInitializer(final Object pojo) {
153         if (!(pojo instanceof HibernateProxy)) {
154             return null;
155         }
156         final HibernateProxy hibernateProxy = (HibernateProxy) pojo;
157         return hibernateProxy.getHibernateLazyInitializer();
158     }
159 }
160 
161 
162 // Copyright (c) Naked Objects Group Ltd.