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