001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.persistence.impl;
016    
017    import com.liferay.portal.NoSuchModelException;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.orm.Dialect;
021    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
022    import com.liferay.portal.kernel.dao.orm.ORMException;
023    import com.liferay.portal.kernel.dao.orm.OrderFactoryUtil;
024    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
025    import com.liferay.portal.kernel.dao.orm.Session;
026    import com.liferay.portal.kernel.dao.orm.SessionFactory;
027    import com.liferay.portal.kernel.exception.SystemException;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.util.ListUtil;
031    import com.liferay.portal.kernel.util.OrderByComparator;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.model.BaseModel;
034    import com.liferay.portal.model.ModelListener;
035    import com.liferay.portal.model.ModelWrapper;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.service.ServiceContextThreadLocal;
038    import com.liferay.portal.service.persistence.BasePersistence;
039    
040    import java.io.Serializable;
041    
042    import java.sql.Connection;
043    
044    import java.util.List;
045    
046    import javax.sql.DataSource;
047    
048    /**
049     * The base implementation for all persistence classes. This class should never
050     * need to be used directly.
051     *
052     * <p>
053     * Caching information and settings can be found in
054     * <code>portal.properties</code>
055     * </p>
056     *
057     * @author Brian Wing Shun Chan
058     * @author Shuyang Zhou
059     */
060    public class BasePersistenceImpl<T extends BaseModel<T>>
061            implements BasePersistence<T>, SessionFactory {
062    
063            public static final String COUNT_COLUMN_NAME = "COUNT_VALUE";
064    
065            public void clearCache() {
066            }
067    
068            public void clearCache(List<T> model) {
069            }
070    
071            public void clearCache(T model) {
072            }
073    
074            public void closeSession(Session session) {
075                    _sessionFactory.closeSession(session);
076            }
077    
078            public long countWithDynamicQuery(DynamicQuery dynamicQuery)
079                    throws SystemException {
080    
081                    dynamicQuery.setProjection(ProjectionFactoryUtil.rowCount());
082    
083                    List<Long> results = findWithDynamicQuery(dynamicQuery);
084    
085                    if (results.isEmpty()) {
086                            return 0;
087                    }
088                    else {
089                            return (results.get(0)).longValue();
090                    }
091            }
092    
093            @SuppressWarnings("unused")
094            public T fetchByPrimaryKey(Serializable primaryKey) throws SystemException {
095                    throw new UnsupportedOperationException();
096            }
097    
098            @SuppressWarnings("unused")
099            public T findByPrimaryKey(Serializable primaryKey)
100                    throws NoSuchModelException, SystemException {
101    
102                    throw new UnsupportedOperationException();
103            }
104    
105            @SuppressWarnings("rawtypes")
106            public List findWithDynamicQuery(DynamicQuery dynamicQuery)
107                    throws SystemException {
108    
109                    Session session = null;
110    
111                    try {
112                            session = openSession();
113    
114                            dynamicQuery.compile(session);
115    
116                            return dynamicQuery.list();
117                    }
118                    catch (Exception e) {
119                            throw processException(e);
120                    }
121                    finally {
122                            closeSession(session);
123                    }
124            }
125    
126            @SuppressWarnings("rawtypes")
127            public List findWithDynamicQuery(
128                            DynamicQuery dynamicQuery, int start, int end)
129                    throws SystemException {
130    
131                    Session session = null;
132    
133                    try {
134                            session = openSession();
135    
136                            dynamicQuery.setLimit(start, end);
137    
138                            dynamicQuery.compile(session);
139    
140                            return dynamicQuery.list();
141                    }
142                    catch (Exception e) {
143                            throw processException(e);
144                    }
145                    finally {
146                            closeSession(session);
147                    }
148            }
149    
150            @SuppressWarnings("rawtypes")
151            public List findWithDynamicQuery(
152                            DynamicQuery dynamicQuery, int start, int end,
153                            OrderByComparator orderByComparator)
154                    throws SystemException {
155    
156                    OrderFactoryUtil.addOrderByComparator(dynamicQuery, orderByComparator);
157    
158                    return findWithDynamicQuery(dynamicQuery, start, end);
159            }
160    
161            public void flush() throws SystemException {
162                    try {
163                            Session session = _sessionFactory.getCurrentSession();
164    
165                            if (session != null) {
166                                    session.flush();
167                            }
168                    }
169                    catch (Exception e) {
170                            throw processException(e);
171                    }
172            }
173    
174            public Session getCurrentSession() throws ORMException {
175                    return _sessionFactory.getCurrentSession();
176            }
177    
178            public DataSource getDataSource() {
179                    return _dataSource;
180            }
181    
182            public DB getDB() {
183                    return _db;
184            }
185    
186            public Dialect getDialect() {
187                    return _dialect;
188            }
189    
190            public ModelListener<T>[] getListeners() {
191                    return listeners;
192            }
193    
194            public Session openNewSession(Connection connection) throws ORMException {
195                    return _sessionFactory.openNewSession(connection);
196            }
197    
198            public Session openSession() throws ORMException {
199                    return _sessionFactory.openSession();
200            }
201    
202            public SystemException processException(Exception e) {
203                    if (!(e instanceof ORMException)) {
204                            _log.error("Caught unexpected exception " + e.getClass().getName());
205                    }
206    
207                    if (_log.isDebugEnabled()) {
208                            _log.debug(e, e);
209                    }
210    
211                    return new SystemException(e);
212            }
213    
214            public void registerListener(ModelListener<T> listener) {
215                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
216    
217                    listenersList.add(listener);
218    
219                    listeners = listenersList.toArray(
220                            new ModelListener[listenersList.size()]);
221            }
222    
223            @SuppressWarnings("unused")
224            public T remove(Serializable primaryKey)
225                    throws NoSuchModelException, SystemException {
226    
227                    throw new UnsupportedOperationException();
228            }
229    
230            public T remove(T model) throws SystemException {
231                    if (model instanceof ModelWrapper) {
232                            ModelWrapper<T> modelWrapper = (ModelWrapper<T>)model;
233    
234                            model = modelWrapper.getWrappedModel();
235                    }
236    
237                    for (ModelListener<T> listener : listeners) {
238                            listener.onBeforeRemove(model);
239                    }
240    
241                    model = removeImpl(model);
242    
243                    for (ModelListener<T> listener : listeners) {
244                            listener.onAfterRemove(model);
245                    }
246    
247                    return model;
248            }
249    
250            public void setDataSource(DataSource dataSource) {
251                    _dataSource = dataSource;
252            }
253    
254            public void setSessionFactory(SessionFactory sessionFactory) {
255                    _sessionFactory = sessionFactory;
256                    _dialect = _sessionFactory.getDialect();
257                    _db = DBFactoryUtil.getDB(_dialect);
258            }
259    
260            public void unregisterListener(ModelListener<T> listener) {
261                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
262    
263                    listenersList.remove(listener);
264    
265                    listeners = listenersList.toArray(
266                            new ModelListener[listenersList.size()]);
267            }
268    
269            public T update(T model) throws SystemException {
270                    if (model instanceof ModelWrapper) {
271                            ModelWrapper<T> modelWrapper = (ModelWrapper<T>)model;
272    
273                            model = modelWrapper.getWrappedModel();
274                    }
275    
276                    boolean isNew = model.isNew();
277    
278                    for (ModelListener<T> listener : listeners) {
279                            if (isNew) {
280                                    listener.onBeforeCreate(model);
281                            }
282                            else {
283                                    listener.onBeforeUpdate(model);
284                            }
285                    }
286    
287                    model = updateImpl(model);
288    
289                    for (ModelListener<T> listener : listeners) {
290                            if (isNew) {
291                                    listener.onAfterCreate(model);
292                            }
293                            else {
294                                    listener.onAfterUpdate(model);
295                            }
296                    }
297    
298                    return model;
299            }
300    
301            /**
302             * @deprecated {@link #update(BaseModel)}}
303             */
304            public T update(T model, boolean merge) throws SystemException {
305                    if (model instanceof ModelWrapper) {
306                            ModelWrapper<T> modelWrapper = (ModelWrapper<T>)model;
307    
308                            model = modelWrapper.getWrappedModel();
309                    }
310    
311                    boolean isNew = model.isNew();
312    
313                    for (ModelListener<T> listener : listeners) {
314                            if (isNew) {
315                                    listener.onBeforeCreate(model);
316                            }
317                            else {
318                                    listener.onBeforeUpdate(model);
319                            }
320                    }
321    
322                    model = updateImpl(model, merge);
323    
324                    for (ModelListener<T> listener : listeners) {
325                            if (isNew) {
326                                    listener.onAfterCreate(model);
327                            }
328                            else {
329                                    listener.onAfterUpdate(model);
330                            }
331                    }
332    
333                    return model;
334            }
335    
336            /**
337             * @deprecated {@link #update(BaseModel, ServiceContext)}}
338             */
339            public T update(T model, boolean merge, ServiceContext serviceContext)
340                    throws SystemException {
341    
342                    return update(model, serviceContext);
343            }
344    
345            public T update(T model, ServiceContext serviceContext)
346                    throws SystemException {
347    
348                    try {
349                            ServiceContextThreadLocal.pushServiceContext(serviceContext);
350    
351                            update(model);
352    
353                            return model;
354                    }
355                    finally {
356                            ServiceContextThreadLocal.popServiceContext();
357                    }
358            }
359    
360            protected void appendOrderByComparator(
361                    StringBundler query, String entityAlias,
362                    OrderByComparator orderByComparator) {
363    
364                    query.append(ORDER_BY_CLAUSE);
365    
366                    String[] orderByFields = orderByComparator.getOrderByFields();
367    
368                    for (int i = 0; i < orderByFields.length; i++) {
369                            query.append(entityAlias);
370                            query.append(orderByFields[i]);
371    
372                            if ((i + 1) < orderByFields.length) {
373                                    if (orderByComparator.isAscending(orderByFields[i])) {
374                                            query.append(ORDER_BY_ASC_HAS_NEXT);
375                                    }
376                                    else {
377                                            query.append(ORDER_BY_DESC_HAS_NEXT);
378                                    }
379                            }
380                            else {
381                                    if (orderByComparator.isAscending(orderByFields[i])) {
382                                            query.append(ORDER_BY_ASC);
383                                    }
384                                    else {
385                                            query.append(ORDER_BY_DESC);
386                                    }
387                            }
388                    }
389            }
390    
391            /**
392             * Removes the model instance from the database. {@link #update(BaseModel,
393             * boolean)} depends on this method to implement the remove operation; it
394             * only notifies the model listeners.
395             *
396             * @param  model the model instance to remove
397             * @return the model instance that was removed
398             * @throws SystemException if a system exception occurred
399             */
400            protected T removeImpl(T model) throws SystemException {
401                    throw new UnsupportedOperationException();
402            }
403    
404            /**
405             * Updates the model instance in the database or adds it if it does not yet
406             * exist. {@link #remove(BaseModel)} depends on this method to implement the
407             * update operation; it only notifies the model listeners.
408             *
409             * @param  model the model instance to update
410             * @return the model instance that was updated
411             * @throws SystemException if a system exception occurred
412             */
413            protected T updateImpl(T model) throws SystemException {
414                    throw new UnsupportedOperationException();
415            }
416    
417            /**
418             * @deprecated {@link #updateImpl(BaseModel)}
419             */
420            protected T updateImpl(T model, boolean merge) throws SystemException {
421                    return updateImpl(model);
422            }
423    
424            protected static final Object[] FINDER_ARGS_EMPTY = new Object[0];
425    
426            protected static final String ORDER_BY_ASC = " ASC";
427    
428            protected static final String ORDER_BY_ASC_HAS_NEXT = " ASC, ";
429    
430            protected static final String ORDER_BY_CLAUSE = " ORDER BY ";
431    
432            protected static final String ORDER_BY_DESC = " DESC";
433    
434            protected static final String ORDER_BY_DESC_HAS_NEXT = " DESC, ";
435    
436            protected static final String WHERE_AND = " AND ";
437    
438            protected static final String WHERE_GREATER_THAN = " >= ? ";
439    
440            protected static final String WHERE_GREATER_THAN_HAS_NEXT = " >= ? AND ";
441    
442            protected static final String WHERE_LESSER_THAN = " <= ? ";
443    
444            protected static final String WHERE_LESSER_THAN_HAS_NEXT = " <= ? AND ";
445    
446            protected static final String WHERE_OR = " OR ";
447    
448            protected ModelListener<T>[] listeners = new ModelListener[0];
449    
450            private static Log _log = LogFactoryUtil.getLog(BasePersistenceImpl.class);
451    
452            private DataSource _dataSource;
453            private DB _db;
454            private Dialect _dialect;
455            private SessionFactory _sessionFactory;
456    
457    }