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