001    /*
002     * $Id: KatEntryDao.java,v 1.12 2005/06/26 02:23:23 mitch Exp $
003     * 
004     * Copyright (c) 2004, FullSpan Software (www.fullspan.com)
005     *
006     * Licensed under the BSD License
007     * OSI Certified Open Source Software (www.opensource.org)
008     *
009     * You may not use this file except in compliance with the License.  You should
010     * have received a copy of the License with this distribution, or you can find
011     * it at: http://www.fullspan.com/shared/license.html.
012     *
013     * NO WARRANTY - USE AT YOUR OWN RISK.  All software and other materials
014     * distributed under the License are provided on an "AS IS" BASIS, WITHOUT
015     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     */
017    package com.fullspan.kat.db.dao;
018    
019    import java.util.*;
020    
021    import net.sf.hibernate.*;
022    import org.apache.log4j.*;
023    
024    import com.fullspan.kat.app.*;
025    import com.fullspan.kat.db.*;
026    import com.fullspan.kat.domain.*;
027    import com.fullspan.kat.domain.entity.*;
028    import com.fullspan.kat.exception.*;
029    import com.fullspan.kat.resource.*;
030    import com.fullspan.util.*;
031    
032    /**
033     * 
034     * @author Mitch Stuart
035     */
036    public class KatEntryDao
037    {
038       // Static variables
039       
040       private static final Logger            LOGGER =
041          Logger.getLogger(LangUtil.getInvokingClassName());
042       
043       private static final KatEntryDao        s_theDao;
044       
045       // Static initializer
046       
047       static
048       {
049          s_theDao = new KatEntryDao();
050       }
051       
052       // Static methods
053       
054       /**
055        * Package private method.  Clients should call
056        * KatDao.getUserDao().
057        * 
058        */
059       static KatEntryDao getDao()
060       {
061          return s_theDao;
062       }
063       
064       // Constructor
065       
066       /**
067        * Private constructor, clients should call getService.
068        */
069       private KatEntryDao()
070       {
071       }
072    
073       // Instance methods
074       
075       public KatEntry get(KatDbSessContext dbCtx, Long id)
076       {
077          return get(dbCtx, id, false, 0);
078       }
079       
080       public KatEntry getForUpdate(KatDbSessContext dbCtx, Long id,
081          long updateVersion)
082       {
083          return get(dbCtx, id, true, updateVersion);
084       }
085       
086       public KatEntry get(KatDbSessContext dbCtx, Long id, boolean forUpdate,
087          long updateVersion)
088       {
089          try
090          {
091             if (forUpdate)
092             {
093                KatEntry entry = (KatEntry)
094                   (dbCtx.getSession().load(KatEntry.class, id, LockMode.UPGRADE));
095             
096                if (updateVersion != entry.getUpdateVersion())
097                {
098                   throw new KatConcurrentModificationException();
099                }
100                
101                return entry;
102             }
103             else
104             {
105                return (KatEntry) (dbCtx.getSession().load(KatEntry.class, id));
106             }
107          }
108          catch (HibernateException e)
109          {
110             throw new KatDataAccessException(
111                ExceptionUtil.getExceptionMessage(e), e);
112          }
113       }
114       
115       public List get(KatDbSessContext dbCtx, Long[] ids, String ownerLoginid,
116          Long identityUserid, boolean isAdmin)
117       {
118          try
119          {
120             Query query =
121                dbCtx.getSession().getNamedQuery("GetEntryList");
122             query.setString("ownerLoginid", ownerLoginid);
123             query.setParameterList("idList", ids, Hibernate.LONG);
124             query.setParameter("identityUserid", identityUserid, Hibernate.LONG);
125             query.setInteger("isAdmin", isAdmin ? 1 : 0);
126             return query.list();
127          }
128          catch (HibernateException e)
129          {
130             throw new KatDataAccessException(
131                ExceptionUtil.getExceptionMessage(e), e);
132          }
133       }
134       
135       public KatCategory getRootCategoryForLoginid(KatDbSessContext dbCtx,
136          String loginid, Long identityUserid, boolean isAdmin)
137       {
138          try
139          {
140             Query query =
141                dbCtx.getSession().getNamedQuery("GetRootCategoryForLoginid");
142             query.setString("ownerLoginid", loginid);
143             query.setParameter("identityUserid", identityUserid, Hibernate.LONG);
144             query.setInteger("isAdmin", isAdmin ? 1 : 0);
145             return (KatCategory) query.uniqueResult();
146          }
147          catch (HibernateException e)
148          {
149             throw new KatDataAccessException(
150                ExceptionUtil.getExceptionMessage(e), e);
151          }
152       }
153    
154       public KatEntryShrub getEntryShrub(KatDbSessContext dbCtx,
155          String loginid, Long id, Long identityUserid, boolean isAdmin)
156       {
157          List entryList;
158          
159          Query query = null;
160          
161          try
162          {
163             if (id == null)
164             {
165                query = dbCtx.getSession().getNamedQuery(
166                   "GetRootEntryShrubForLoginid");
167             }
168             else
169             {
170                query = dbCtx.getSession().getNamedQuery("GetEntryShrub");
171                query.setParameter("entryId", id, Hibernate.LONG);
172             }
173             
174             query.setString("ownerLoginid", loginid);
175             query.setParameter("identityUserid", identityUserid, Hibernate.LONG);
176             query.setInteger("isAdmin", isAdmin ? 1 : 0);
177             entryList = query.list();
178          }
179          catch (HibernateException e)
180          {
181             throw new KatDataAccessException(
182                ExceptionUtil.getExceptionMessage(e), e);
183          }
184          
185          KatEntry entry = null;
186          List parentCats = new ArrayList();
187          List childCats = new ArrayList();
188          List childItems = new ArrayList();
189          
190          if (entryList != null)
191          {
192             for (Iterator it = entryList.iterator(); it.hasNext(); )
193             {
194                KatEntry curEntry = (KatEntry) (it.next());
195    
196                // The entryList is in order: parents first, then the entry,
197                // then the child cats and items
198    
199                if (entry == null)
200                {
201                   if (id == null)
202                   {
203                      // Getting root, first entry in list is root
204                      entry = curEntry;
205                   }
206                   else
207                   {
208                      // Getting non-root
209                      
210                      if (!curEntry.getId().equals(id))
211                      {
212                         // Parents precede requested entry in list
213                         parentCats.add(curEntry);
214                      }
215                      else
216                      {
217                         // Entry found
218                         entry = curEntry;
219                      }
220                   }
221                }
222                else if (curEntry.getIsItem())
223                {
224                   childItems.add(curEntry);
225                }
226                else
227                {
228                   childCats.add(curEntry);
229                }
230             }
231          }
232          
233          if (entry == null)
234          {
235             return null;
236          }
237          
238          return new KatEntryShrub(entry, parentCats, childCats, childItems);
239       }
240       
241       public KatEntryTree getEntryTree(KatDbSessContext dbCtx,
242          String ownerLoginid,
243          Long startFromCatid,
244          Long skipSubtreeCatid,
245          boolean catsOnly,
246          Long identityUserid,
247          boolean isAdmin)
248       {
249          List entryList;
250          
251          try
252          {
253             Query query = null;
254             
255             if (startFromCatid == null)
256             {
257                query = dbCtx.getSession().getNamedQuery(
258                   "GetRootEntryTreeForLoginid");
259             }
260             else
261             {
262                query = dbCtx.getSession().getNamedQuery("GetEntryTree");
263                query.setParameter("entryId", startFromCatid, Hibernate.LONG);
264             }
265    
266             query.setString("ownerLoginid", ownerLoginid);
267             query.setParameter("identityUserid", identityUserid, Hibernate.LONG);
268             query.setInteger("isAdmin", isAdmin ? 1 : 0);
269             query.setInteger("includeItems", catsOnly ? 0 : 1);
270             
271             if (skipSubtreeCatid == null)
272             {
273                query.setString("skipSubtreeCatid", "");
274             }
275             else
276             {
277                String catidStr = KatEntry.formatIdForPath(skipSubtreeCatid);
278                query.setString("skipSubtreeCatid", catidStr);
279             }
280             
281             entryList = query.list();
282          }
283          catch (HibernateException e)
284          {
285             throw new KatDataAccessException(
286                ExceptionUtil.getExceptionMessage(e), e);
287          }
288          
289          return new KatEntryTree(entryList, startFromCatid);
290       }
291    
292       
293       public KatEntry getChildEntryByName(KatDbSessContext dbCtx,
294          Long catid, String name)
295       {
296          KatEntry entry = null;
297          
298          try
299          {
300             Query query = dbCtx.getSession().getNamedQuery(
301                "GetChildEntryByName");
302    
303             query.setParameter("catid", catid, Hibernate.LONG);
304             query.setString("name", name);
305             
306             entry = (KatEntry) query.uniqueResult();
307          }
308          catch (HibernateException e)
309          {
310             throw new KatDataAccessException(
311                ExceptionUtil.getExceptionMessage(e), e);
312          }
313          
314          return entry;
315       }
316       
317       
318       public List getRecentlyVisitedItems(KatDbSessContext dbCtx,
319          Long ownerUserId, int maxResults)
320       {
321          try
322          {
323             Query query = dbCtx.getSession().getNamedQuery(
324                "GetRecentlyVisitedItems");
325    
326             query.setParameter("ownerUserid", ownerUserId, Hibernate.LONG);
327             
328             if (maxResults > 0)
329             {
330                query.setMaxResults(maxResults);
331             }
332             
333             return query.list();
334          }
335          catch (HibernateException e)
336          {
337             throw new KatDataAccessException(
338                ExceptionUtil.getExceptionMessage(e), e);
339          }
340    
341       }
342    
343    
344       public List getFrequentlyVisitedItems(KatDbSessContext dbCtx,
345          Long ownerUserId, int maxResults)
346       {
347          try
348          {
349             Query query = dbCtx.getSession().getNamedQuery(
350                "GetFrequentlyVisitedItems");
351    
352             query.setParameter("ownerUserid", ownerUserId, Hibernate.LONG);
353             
354             if (maxResults > 0)
355             {
356                query.setMaxResults(maxResults);
357             }
358             
359             return query.list();
360          }
361          catch (HibernateException e)
362          {
363             throw new KatDataAccessException(
364                ExceptionUtil.getExceptionMessage(e), e);
365          }
366    
367       }
368    
369    
370       public void createRootCat(KatDbSessContext dbCtx, KatUser ownerUser)
371       {
372          KatEntry rootCat = KatEntry.newInstance(KatEntry.ENTRY_TYPE_CATEGORY);
373          
374          rootCat.setName(KatApp.getApp().getMessage(
375             KatMsgKeys.APP.ROOT_CATEGORY.DEFAULT_NAME));
376          
377          rootCat.setVisibility(KatEntry.VISIBILITY_PUBLIC);
378          rootCat.setComputedVisibility(KatEntry.VISIBILITY_PUBLIC);
379          rootCat.setEntryLevel(0);
380          rootCat.setOwnerUser(ownerUser);
381          rootCat.setOwnerUserid(ownerUser.getId());
382          rootCat.setParentPath("");
383          
384          save(dbCtx, rootCat);
385       }
386    
387       
388       public KatEntry save(KatDbSessContext dbCtx, KatEntry entry)
389       {
390          try
391          {
392             if (entry.getIsNew())
393             {
394                // This is a temporary entryPath to satisfy the non-null constraint.
395                entry.setEntryPath("");
396                dbCtx.getSession().save(entry);
397                // Now the entry's id property has been set, so we can now set
398                // the real entryPath.
399                entry.computeAndSetEntryPath();
400             }
401             else
402             {
403                dbCtx.getSession().update(entry);
404                // Proactively flush instead of waiting for commit - so we can
405                // report errors on the edit page
406                dbCtx.getSession().flush();
407             }
408             
409             return entry;
410          }
411          catch (HibernateException e)
412          {
413             KatDuplicateKeyException dupEx = getPossibleDuplicateKeyException(e);
414             
415             if (dupEx != null)
416             {
417                throw dupEx;
418             }
419             else
420             {
421                throw new KatDataAccessException(
422                   ExceptionUtil.getExceptionMessage(e), e);
423             }
424          }
425       }
426       
427       protected KatDuplicateKeyException getPossibleDuplicateKeyException(
428          HibernateException hibEx)
429       {
430          String hibMsg = ExceptionUtil.getExceptionMessage(hibEx);
431          
432          if (!hibMsg.startsWith("Duplicate key"))
433          {
434             return null;
435          }
436          
437          String fieldName = null;
438          
439          if (hibMsg.endsWith("for key 2\""))
440          {
441             fieldName = "name";
442          }
443          
444          if (fieldName == null)
445          {
446             return null;
447          }
448          else
449          {
450             return new KatDuplicateKeyException(hibMsg, fieldName);
451          }
452       }
453       
454       public void delete(KatDbSessContext dbCtx, Long id)
455       {
456          try
457          {
458             dbCtx.getSession().delete("from KatEntry where id = ?",
459                id, Hibernate.LONG);
460          }
461          catch (HibernateException e)
462          {
463             throw new KatDataAccessException(
464                ExceptionUtil.getExceptionMessage(e), e);
465          }
466       }
467       
468    }