KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > node > db > hibernate > HibernateNodeDaoServiceImpl


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.node.db.hibernate;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.List JavaDoc;
22
23 import org.alfresco.model.ContentModel;
24 import org.alfresco.repo.domain.ChildAssoc;
25 import org.alfresco.repo.domain.Node;
26 import org.alfresco.repo.domain.NodeAssoc;
27 import org.alfresco.repo.domain.NodeKey;
28 import org.alfresco.repo.domain.NodeStatus;
29 import org.alfresco.repo.domain.Store;
30 import org.alfresco.repo.domain.StoreKey;
31 import org.alfresco.repo.domain.hibernate.ChildAssocImpl;
32 import org.alfresco.repo.domain.hibernate.NodeAssocImpl;
33 import org.alfresco.repo.domain.hibernate.NodeImpl;
34 import org.alfresco.repo.domain.hibernate.NodeStatusImpl;
35 import org.alfresco.repo.domain.hibernate.StoreImpl;
36 import org.alfresco.repo.node.db.NodeDaoService;
37 import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
38 import org.alfresco.service.cmr.dictionary.InvalidTypeException;
39 import org.alfresco.service.cmr.repository.ChildAssociationRef;
40 import org.alfresco.service.namespace.QName;
41 import org.alfresco.util.GUID;
42 import org.hibernate.ObjectDeletedException;
43 import org.hibernate.Query;
44 import org.hibernate.Session;
45 import org.springframework.dao.DataAccessException;
46 import org.springframework.dao.DataIntegrityViolationException;
47 import org.springframework.orm.hibernate3.HibernateCallback;
48 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
49
50 /**
51  * Hibernate-specific implementation of the persistence-independent <b>node</b> DAO interface
52  *
53  * @author Derek Hulley
54  */

55 public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements NodeDaoService
56 {
57     private static final String JavaDoc QUERY_GET_ALL_STORES = "store.GetAllStores";
58     private static final String JavaDoc QUERY_GET_NODE_ASSOC = "node.GetNodeAssoc";
59     private static final String JavaDoc QUERY_GET_NODE_ASSOC_TARGETS = "node.GetNodeAssocTargets";
60     private static final String JavaDoc QUERY_GET_NODE_ASSOC_SOURCES = "node.GetNodeAssocSources";
61     private static final String JavaDoc QUERY_GET_CONTENT_DATA_STRINGS = "node.GetContentDataStrings";
62     
63     /** a uuid identifying this unique instance */
64     private String JavaDoc uuid;
65
66     /**
67      *
68      */

69     public HibernateNodeDaoServiceImpl()
70     {
71         this.uuid = GUID.generate();
72     }
73
74     /**
75      * Checks equality by type and uuid
76      */

77     public boolean equals(Object JavaDoc obj)
78     {
79         if (obj == null)
80         {
81             return false;
82         }
83         else if (!(obj instanceof HibernateNodeDaoServiceImpl))
84         {
85             return false;
86         }
87         HibernateNodeDaoServiceImpl that = (HibernateNodeDaoServiceImpl) obj;
88         return this.uuid.equals(that.uuid);
89     }
90     
91     /**
92      * @see #uuid
93      */

94     public int hashCode()
95     {
96         return uuid.hashCode();
97     }
98
99     /**
100      * Does this <tt>Session</tt> contain any changes which must be
101      * synchronized with the store?
102      *
103      * @return true => changes are pending
104      */

105     public boolean isDirty()
106     {
107         // create a callback for the task
108
HibernateCallback callback = new HibernateCallback()
109         {
110             public Object JavaDoc doInHibernate(Session session)
111             {
112                 return session.isDirty();
113             }
114         };
115         // execute the callback
116
return ((Boolean JavaDoc)getHibernateTemplate().execute(callback)).booleanValue();
117     }
118
119     /**
120      * @see #QUERY_GET_ALL_STORES
121      */

122     @SuppressWarnings JavaDoc("unchecked")
123     public List JavaDoc<Store> getStores()
124     {
125         HibernateCallback callback = new HibernateCallback()
126         {
127             public Object JavaDoc doInHibernate(Session session)
128             {
129                 Query query = session.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_ALL_STORES);
130                 return query.list();
131             }
132         };
133         List JavaDoc<Store> queryResults = (List JavaDoc) getHibernateTemplate().execute(callback);
134         // done
135
return queryResults;
136     }
137     
138     /**
139      * Ensures that the store protocol/identifier combination is unique
140      */

141     public Store createStore(String JavaDoc protocol, String JavaDoc identifier)
142     {
143         // ensure that the name isn't in use
144
Store store = getStore(protocol, identifier);
145         if (store != null)
146         {
147             throw new RuntimeException JavaDoc("A store already exists: \n" +
148                     " protocol: " + protocol + "\n" +
149                     " identifier: " + identifier + "\n" +
150                     " store: " + store);
151         }
152         
153         store = new StoreImpl();
154         // set key
155
store.setKey(new StoreKey(protocol, identifier));
156         // persist so that it is present in the hibernate cache
157
getHibernateTemplate().save(store);
158         // create and assign a root node
159
Node rootNode = newNode(
160                 store,
161                 GUID.generate(),
162                 ContentModel.TYPE_STOREROOT);
163         store.setRootNode(rootNode);
164         // done
165
return store;
166     }
167
168     public Store getStore(String JavaDoc protocol, String JavaDoc identifier)
169     {
170         StoreKey storeKey = new StoreKey(protocol, identifier);
171         Store store = (Store) getHibernateTemplate().get(StoreImpl.class, storeKey);
172         // done
173
return store;
174     }
175
176     public Node newNode(Store store, String JavaDoc id, QName nodeTypeQName) throws InvalidTypeException
177     {
178         NodeKey key = new NodeKey(store.getKey(), id);
179
180         // create (or reuse) the mandatory node status
181
NodeStatus nodeStatus = (NodeStatus) getHibernateTemplate().get(NodeStatusImpl.class, key);
182         if (nodeStatus == null)
183         {
184             nodeStatus = new NodeStatusImpl();
185         }
186         // set required status properties
187
nodeStatus.setKey(key);
188         nodeStatus.setDeleted(false);
189         nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
190         // persist the nodestatus
191
getHibernateTemplate().save(nodeStatus);
192         
193         // build a concrete node based on a bootstrap type
194
Node node = new NodeImpl();
195         // set other required properties
196
node.setKey(key);
197         node.setTypeQName(nodeTypeQName);
198         node.setStore(store);
199         node.setStatus(nodeStatus);
200         // persist the node
201
getHibernateTemplate().save(node);
202         // done
203
return node;
204     }
205
206     public Node getNode(String JavaDoc protocol, String JavaDoc identifier, String JavaDoc id)
207     {
208         try
209         {
210             NodeKey nodeKey = new NodeKey(protocol, identifier, id);
211             Object JavaDoc obj = getHibernateTemplate().get(NodeImpl.class, nodeKey);
212             // done
213
return (Node) obj;
214         }
215         catch (ObjectDeletedException e)
216         {
217             return null;
218         }
219         catch (DataAccessException e)
220         {
221             if (e.contains(ObjectDeletedException.class))
222             {
223                 // the object no loner exists
224
return null;
225             }
226             throw e;
227         }
228     }
229     
230     /**
231      * Manually ensures that all cascading of associations is taken care of
232      */

233     public void deleteNode(Node node, boolean cascade)
234     {
235         // delete all parent assocs
236
Collection JavaDoc<ChildAssoc> parentAssocs = node.getParentAssocs();
237         parentAssocs = new ArrayList JavaDoc<ChildAssoc>(parentAssocs);
238         for (ChildAssoc assoc : parentAssocs)
239         {
240             deleteChildAssoc(assoc, false); // we don't cascade upwards
241
}
242         // delete all child assocs
243
Collection JavaDoc<ChildAssoc> childAssocs = node.getChildAssocs();
244         childAssocs = new ArrayList JavaDoc<ChildAssoc>(childAssocs);
245         for (ChildAssoc assoc : childAssocs)
246         {
247             deleteChildAssoc(assoc, cascade); // potentially cascade downwards
248
}
249         // delete all target assocs
250
Collection JavaDoc<NodeAssoc> targetAssocs = node.getTargetNodeAssocs();
251         targetAssocs = new ArrayList JavaDoc<NodeAssoc>(targetAssocs);
252         for (NodeAssoc assoc : targetAssocs)
253         {
254             deleteNodeAssoc(assoc);
255         }
256         // delete all source assocs
257
Collection JavaDoc<NodeAssoc> sourceAssocs = node.getSourceNodeAssocs();
258         sourceAssocs = new ArrayList JavaDoc<NodeAssoc>(sourceAssocs);
259         for (NodeAssoc assoc : sourceAssocs)
260         {
261             deleteNodeAssoc(assoc);
262         }
263         // update the node status
264
NodeStatus nodeStatus = node.getStatus();
265         nodeStatus.setDeleted(true);
266         nodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
267         // finally delete the node
268
getHibernateTemplate().delete(node);
269         // done
270
}
271
272     /**
273      * Fetch the node status, if it exists
274      */

275     public NodeStatus getNodeStatus(String JavaDoc protocol, String JavaDoc identifier, String JavaDoc id)
276     {
277         try
278         {
279             NodeKey nodeKey = new NodeKey(protocol, identifier, id);
280             Object JavaDoc obj = getHibernateTemplate().get(NodeStatusImpl.class, nodeKey);
281             // done
282
return (NodeStatus) obj;
283         }
284         catch (DataAccessException e)
285         {
286             if (e.contains(ObjectDeletedException.class))
287             {
288                 // the object no loner exists
289
return null;
290             }
291             throw e;
292         }
293     }
294
295     public ChildAssoc newChildAssoc(
296             Node parentNode,
297             Node childNode,
298             boolean isPrimary,
299             QName assocTypeQName,
300             QName qname)
301     {
302         ChildAssoc assoc = new ChildAssocImpl();
303         assoc.setTypeQName(assocTypeQName);
304         assoc.setIsPrimary(isPrimary);
305         assoc.setQname(qname);
306         assoc.buildAssociation(parentNode, childNode);
307         // persist
308
getHibernateTemplate().save(assoc);
309         // done
310
return assoc;
311     }
312     
313     public ChildAssoc getChildAssoc(
314             Node parentNode,
315             Node childNode,
316             QName assocTypeQName,
317             QName qname)
318     {
319         ChildAssociationRef childAssocRef = new ChildAssociationRef(
320                 assocTypeQName,
321                 parentNode.getNodeRef(),
322                 qname,
323                 childNode.getNodeRef());
324         // get all the parent's child associations
325
Collection JavaDoc<ChildAssoc> assocs = parentNode.getChildAssocs();
326         // hunt down the desired assoc
327
for (ChildAssoc assoc : assocs)
328         {
329             // is it a match?
330
if (!assoc.getChildAssocRef().equals(childAssocRef)) // not a match
331
{
332                 continue;
333             }
334             else
335             {
336                 return assoc;
337             }
338         }
339         // not found
340
return null;
341     }
342
343     /**
344      * Manually enforces cascade deletions down primary associations
345      */

346     public void deleteChildAssoc(ChildAssoc assoc, boolean cascade)
347     {
348         Node childNode = assoc.getChild();
349         
350         // maintain inverse association sets
351
assoc.removeAssociation();
352         // remove instance
353
getHibernateTemplate().delete(assoc);
354         
355         if (cascade && assoc.getIsPrimary()) // the assoc is primary
356
{
357             // delete the child node
358
deleteNode(childNode, cascade);
359             /*
360              * The child node deletion will cascade delete all assocs to
361              * and from it, but we have safely removed this one, so no
362              * duplicate call will be received to do this
363              */

364         }
365     }
366
367     public ChildAssoc getPrimaryParentAssoc(Node node)
368     {
369         // get the assocs pointing to the node
370
Collection JavaDoc<ChildAssoc> parentAssocs = node.getParentAssocs();
371         ChildAssoc primaryAssoc = null;
372         for (ChildAssoc assoc : parentAssocs)
373         {
374             // ignore non-primary assocs
375
if (!assoc.getIsPrimary())
376             {
377                 continue;
378             }
379             else if (primaryAssoc != null)
380             {
381                 // we have more than one somehow
382
throw new DataIntegrityViolationException(
383                         "Multiple primary associations: \n" +
384                         " child: " + node + "\n" +
385                         " first primary assoc: " + primaryAssoc + "\n" +
386                         " second primary assoc: " + assoc);
387             }
388             primaryAssoc = assoc;
389             // we keep looping to hunt out data integrity issues
390
}
391         // did we find a primary assoc?
392
if (primaryAssoc == null)
393         {
394             // the only condition where this is allowed is if the given node is a root node
395
Store store = node.getStore();
396             Node rootNode = store.getRootNode();
397             if (rootNode == null)
398             {
399                 // a store without a root node - the entire store is hosed
400
throw new DataIntegrityViolationException("Store has no root node: \n" +
401                         " store: " + store);
402             }
403             if (!rootNode.equals(node))
404             {
405                 // it wasn't the root node
406
throw new DataIntegrityViolationException("Non-root node has no primary parent: \n" +
407                         " child: " + node);
408             }
409         }
410         // done
411
return primaryAssoc;
412     }
413
414     public NodeAssoc newNodeAssoc(Node sourceNode, Node targetNode, QName assocTypeQName)
415     {
416         NodeAssoc assoc = new NodeAssocImpl();
417         assoc.setTypeQName(assocTypeQName);
418         assoc.buildAssociation(sourceNode, targetNode);
419         // persist
420
getHibernateTemplate().save(assoc);
421         // done
422
return assoc;
423     }
424
425     public NodeAssoc getNodeAssoc(
426             final Node sourceNode,
427             final Node targetNode,
428             final QName assocTypeQName)
429     {
430         final NodeKey sourceKey = sourceNode.getKey();
431         final NodeKey targetKey = targetNode.getKey();
432         HibernateCallback callback = new HibernateCallback()
433         {
434             public Object JavaDoc doInHibernate(Session session)
435             {
436                 Query query = session.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODE_ASSOC);
437                 query.setString("sourceKeyProtocol", sourceKey.getProtocol())
438                      .setString("sourceKeyIdentifier", sourceKey.getIdentifier())
439                      .setString("sourceKeyGuid", sourceKey.getGuid())
440                      .setString("assocTypeQName", assocTypeQName.toString())
441                      .setString("targetKeyProtocol", targetKey.getProtocol())
442                      .setString("targetKeyIdentifier", targetKey.getIdentifier())
443                      .setString("targetKeyGuid", targetKey.getGuid());
444                 query.setMaxResults(1);
445                 return query.uniqueResult();
446             }
447         };
448         Object JavaDoc queryResult = getHibernateTemplate().execute(callback);
449         if (queryResult == null)
450         {
451             return null;
452         }
453         NodeAssoc assoc = (NodeAssoc) queryResult;
454         // done
455
return assoc;
456     }
457
458     @SuppressWarnings JavaDoc("unchecked")
459     public Collection JavaDoc<Node> getNodeAssocTargets(final Node sourceNode, final QName assocTypeQName)
460     {
461         final NodeKey sourceKey = sourceNode.getKey();
462         HibernateCallback callback = new HibernateCallback()
463         {
464             public Object JavaDoc doInHibernate(Session session)
465             {
466                 Query query = session.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODE_ASSOC_TARGETS);
467                 query.setString("sourceKeyProtocol", sourceKey.getProtocol())
468                      .setString("sourceKeyIdentifier", sourceKey.getIdentifier())
469                      .setString("sourceKeyGuid", sourceKey.getGuid())
470                      .setString("assocTypeQName", assocTypeQName.toString());
471                 return query.list();
472             }
473         };
474         List JavaDoc<Node> queryResults = (List JavaDoc) getHibernateTemplate().execute(callback);
475         // done
476
return queryResults;
477     }
478
479     @SuppressWarnings JavaDoc("unchecked")
480     public Collection JavaDoc<Node> getNodeAssocSources(final Node targetNode, final QName assocTypeQName)
481     {
482         final NodeKey targetKey = targetNode.getKey();
483         HibernateCallback callback = new HibernateCallback()
484         {
485             public Object JavaDoc doInHibernate(Session session)
486             {
487                 Query query = session.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODE_ASSOC_SOURCES);
488                 query.setString("targetKeyProtocol", targetKey.getProtocol())
489                      .setString("targetKeyIdentifier", targetKey.getIdentifier())
490                      .setString("targetKeyGuid", targetKey.getGuid())
491                      .setString("assocTypeQName", assocTypeQName.toString());
492                 return query.list();
493             }
494         };
495         List JavaDoc<Node> queryResults = (List JavaDoc) getHibernateTemplate().execute(callback);
496         // done
497
return queryResults;
498     }
499
500     public void deleteNodeAssoc(NodeAssoc assoc)
501     {
502         // maintain inverse association sets
503
assoc.removeAssociation();
504         // remove instance
505
getHibernateTemplate().delete(assoc);
506     }
507
508     @SuppressWarnings JavaDoc("unchecked")
509     public List JavaDoc<String JavaDoc> getContentDataStrings()
510     {
511         HibernateCallback callback = new HibernateCallback()
512         {
513             public Object JavaDoc doInHibernate(Session session)
514             {
515                 Query query = session.getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_CONTENT_DATA_STRINGS);
516                 return query.list();
517             }
518         };
519         List JavaDoc<String JavaDoc> queryResults = (List JavaDoc) getHibernateTemplate().execute(callback);
520         return queryResults;
521     }
522 }
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
Popular Tags