001    /**
002     * Copyright (c) 2000-2010 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.orm.Dialect;
019    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
020    import com.liferay.portal.kernel.dao.orm.ORMException;
021    import com.liferay.portal.kernel.dao.orm.OrderFactoryUtil;
022    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
023    import com.liferay.portal.kernel.dao.orm.Session;
024    import com.liferay.portal.kernel.dao.orm.SessionFactory;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.util.ListUtil;
029    import com.liferay.portal.kernel.util.OrderByComparator;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.portal.model.BaseModel;
032    import com.liferay.portal.model.ModelListener;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portal.service.ServiceContextThreadLocal;
035    import com.liferay.portal.service.persistence.BasePersistence;
036    
037    import java.io.Serializable;
038    
039    import java.sql.Connection;
040    
041    import java.util.List;
042    
043    import javax.sql.DataSource;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Shuyang Zhou
048     */
049    public class BasePersistenceImpl<T extends BaseModel<T>>
050            implements BasePersistence<T>, SessionFactory {
051    
052            public static final String COUNT_COLUMN_NAME = "COUNT_VALUE";
053    
054            public void clearCache() {
055            }
056    
057            public void clearCache(T model) {
058            }
059    
060            public void closeSession(Session session) {
061                    _sessionFactory.closeSession(session);
062            }
063    
064            public long countWithDynamicQuery(DynamicQuery dynamicQuery)
065                    throws SystemException {
066    
067                    dynamicQuery.setProjection(ProjectionFactoryUtil.rowCount());
068    
069                    List<Long> results = findWithDynamicQuery(dynamicQuery);
070    
071                    if (results.isEmpty()) {
072                            return 0;
073                    }
074                    else {
075                            return (results.get(0)).longValue();
076                    }
077            }
078    
079            @SuppressWarnings("unused")
080            public T fetchByPrimaryKey(Serializable primaryKey) throws SystemException {
081                    throw new UnsupportedOperationException();
082            }
083    
084            @SuppressWarnings("unused")
085            public T findByPrimaryKey(Serializable primaryKey)
086                    throws NoSuchModelException, SystemException {
087    
088                    throw new UnsupportedOperationException();
089            }
090    
091            @SuppressWarnings("unchecked")
092            public List findWithDynamicQuery(DynamicQuery dynamicQuery)
093                    throws SystemException {
094    
095                    Session session = null;
096    
097                    try {
098                            session = openSession();
099    
100                            dynamicQuery.compile(session);
101    
102                            return dynamicQuery.list();
103                    }
104                    catch (Exception e) {
105                            throw processException(e);
106                    }
107                    finally {
108                            closeSession(session);
109                    }
110            }
111    
112            @SuppressWarnings("unchecked")
113            public List findWithDynamicQuery(
114                            DynamicQuery dynamicQuery, int start, int end)
115                    throws SystemException {
116    
117                    Session session = null;
118    
119                    try {
120                            session = openSession();
121    
122                            dynamicQuery.setLimit(start, end);
123    
124                            dynamicQuery.compile(session);
125    
126                            return dynamicQuery.list();
127                    }
128                    catch (Exception e) {
129                            throw processException(e);
130                    }
131                    finally {
132                            closeSession(session);
133                    }
134            }
135    
136            @SuppressWarnings("unchecked")
137            public List findWithDynamicQuery(
138                            DynamicQuery dynamicQuery, int start, int end,
139                            OrderByComparator orderByComparator)
140                    throws SystemException {
141    
142                    OrderFactoryUtil.addOrderByComparator(dynamicQuery, orderByComparator);
143    
144                    return findWithDynamicQuery(dynamicQuery, start, end);
145            }
146    
147            public DataSource getDataSource() {
148                    return _dataSource;
149            }
150    
151            public Dialect getDialect() {
152                    return _dialect;
153            }
154    
155            public ModelListener<T>[] getListeners() {
156                    return listeners;
157            }
158    
159            public Session openNewSession(Connection connection) throws ORMException {
160                    return _sessionFactory.openNewSession(connection);
161            }
162    
163            public Session openSession() throws ORMException {
164                    return _sessionFactory.openSession();
165            }
166    
167            public SystemException processException(Exception e) {
168                    if (!(e instanceof ORMException)) {
169                            _log.error("Caught unexpected exception " + e.getClass().getName());
170                    }
171    
172                    if (_log.isDebugEnabled()) {
173                            _log.debug(e, e);
174                    }
175    
176                    return new SystemException(e);
177            }
178    
179            public void registerListener(ModelListener<T> listener) {
180                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
181    
182                    listenersList.add(listener);
183    
184                    listeners = listenersList.toArray(
185                            new ModelListener[listenersList.size()]);
186            }
187    
188            @SuppressWarnings("unused")
189            public T remove(Serializable primaryKey)
190                    throws NoSuchModelException, SystemException {
191    
192                    throw new UnsupportedOperationException();
193            }
194    
195            public T remove(T model) throws SystemException {
196                    for (ModelListener<T> listener : listeners) {
197                            listener.onBeforeRemove(model);
198                    }
199    
200                    model = removeImpl(model);
201    
202                    for (ModelListener<T> listener : listeners) {
203                            listener.onAfterRemove(model);
204                    }
205    
206                    return model;
207            }
208    
209            public void setDataSource(DataSource dataSource) {
210                    _dataSource = dataSource;
211            }
212    
213            public void setSessionFactory(SessionFactory sessionFactory) {
214                    _sessionFactory = sessionFactory;
215                    _dialect = _sessionFactory.getDialect();
216            }
217    
218            public void unregisterListener(ModelListener<T> listener) {
219                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
220    
221                    ListUtil.remove(listenersList, listener);
222    
223                    listeners = listenersList.toArray(
224                            new ModelListener[listenersList.size()]);
225            }
226    
227            public T update(T model, boolean merge) throws SystemException {
228                    boolean isNew = model.isNew();
229    
230                    for (ModelListener<T> listener : listeners) {
231                            if (isNew) {
232                                    listener.onBeforeCreate(model);
233                            }
234                            else {
235                                    listener.onBeforeUpdate(model);
236                            }
237                    }
238    
239                    model = updateImpl(model, merge);
240    
241                    for (ModelListener<T> listener : listeners) {
242                            if (isNew) {
243                                    listener.onAfterCreate(model);
244                            }
245                            else {
246                                    listener.onAfterUpdate(model);
247                            }
248                    }
249    
250                    return model;
251            }
252    
253            public T update(T model, boolean merge, ServiceContext serviceContext)
254                    throws SystemException {
255    
256                    ServiceContext previousServiceContext =
257                            ServiceContextThreadLocal.getServiceContext();
258    
259                    try {
260                            ServiceContextThreadLocal.setServiceContext(serviceContext);
261    
262                            update(model, merge);
263    
264                            return model;
265                    }
266                    finally {
267                            ServiceContextThreadLocal.setServiceContext(previousServiceContext);
268                    }
269            }
270    
271            protected void appendOrderByComparator(
272                    StringBundler query, String entityAlias,
273                    OrderByComparator orderByComparator) {
274    
275                    query.append(ORDER_BY_CLAUSE);
276    
277                    String[] orderByFields = orderByComparator.getOrderByFields();
278    
279                    for (int i = 0; i < orderByFields.length; i++) {
280                            query.append(entityAlias);
281                            query.append(orderByFields[i]);
282    
283                            if ((i + 1) < orderByFields.length) {
284                                    if (orderByComparator.isAscending()) {
285                                            query.append(ORDER_BY_ASC_HAS_NEXT);
286                                    }
287                                    else {
288                                            query.append(ORDER_BY_DESC_HAS_NEXT);
289                                    }
290                            }
291                            else {
292                                    if (orderByComparator.isAscending()) {
293                                            query.append(ORDER_BY_ASC);
294                                    }
295                                    else {
296                                            query.append(ORDER_BY_DESC);
297                                    }
298                            }
299                    }
300            }
301    
302            /**
303             * Removes the model instance from the database. {@link #update(BaseModel,
304             * boolean)} depends on this method to implement the remove operation; it
305             * only notifies the model listeners.
306             *
307             * @param  model the model instance to remove
308             * @return the model instance that was removed
309             * @throws SystemException if a system exception occurred
310             */
311            protected T removeImpl(T model) throws SystemException {
312                    throw new UnsupportedOperationException();
313            }
314    
315            /**
316             * Updates the model instance in the database or adds it if it does not yet
317             * exist. {@link #remove(BaseModel)} depends on this method to implement the
318             * update operation; it only notifies the model listeners.
319             *
320             * @param  model the model instance to update
321             * @param  merge whether to merge the model instance with the current
322             *                 session. See {@link
323             *                 com.liferay.portal.service.persistence.BatchSession#update(
324             *                 com.liferay.portal.kernel.dao.orm.Session, BaseModel, boolean)}
325             *                 for an explanation.
326             * @return the model instance that was updated
327             * @throws SystemException if a system exception occurred
328             */
329            protected T updateImpl(T model, boolean merge) throws SystemException {
330                    throw new UnsupportedOperationException();
331            }
332    
333            protected static final String ORDER_BY_ASC = " ASC";
334    
335            protected static final String ORDER_BY_ASC_HAS_NEXT = " ASC, ";
336    
337            protected static final String ORDER_BY_CLAUSE = " ORDER BY ";
338    
339            protected static final String ORDER_BY_DESC = " DESC";
340    
341            protected static final String ORDER_BY_DESC_HAS_NEXT = " DESC, ";
342    
343            protected static final String WHERE_AND = " AND ";
344    
345            protected static final String WHERE_LESSER_THAN = " <= ? ";
346    
347            protected static final String WHERE_LESSER_THAN_HAS_NEXT = " <= ? AND ";
348    
349            protected static final String WHERE_GREATER_THAN = " >= ? ";
350    
351            protected static final String WHERE_GREATER_THAN_HAS_NEXT = " >= ? AND ";
352    
353            protected static final String WHERE_OR = " OR ";
354    
355            protected ModelListener<T>[] listeners = new ModelListener[0];
356    
357            private static Log _log = LogFactoryUtil.getLog(BasePersistenceImpl.class);
358    
359            private DataSource _dataSource;
360            private Dialect _dialect;
361            private SessionFactory _sessionFactory;
362    
363    }