001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kew.doctype.dao.impl;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.log4j.Logger;
020import org.kuali.rice.core.api.criteria.Predicate;
021import org.kuali.rice.core.api.criteria.QueryResults;
022import org.kuali.rice.kew.doctype.bo.DocumentType;
023import org.kuali.rice.kew.doctype.dao.DocumentTypeDAO;
024import org.kuali.rice.krad.data.DataObjectService;
025import org.springframework.beans.factory.annotation.Required;
026
027import javax.persistence.EntityManager;
028import javax.persistence.LockModeType;
029import javax.persistence.NoResultException;
030import javax.persistence.TypedQuery;
031import java.util.ArrayList;
032import java.util.Collection;
033import java.util.List;
034
035import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
036
037/**
038 * JPA implementation of DocumentTypeDAo
039 *
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042public class DocumentTypeDAOJpa implements DocumentTypeDAO {
043
044        public static final Logger LOG = Logger.getLogger(DocumentTypeDAOJpa.class);
045
046        private EntityManager entityManager;
047    private DataObjectService dataObjectService;
048
049
050        /**
051         * @return the entityManager
052         */
053        public EntityManager getEntityManager() {
054                return this.entityManager;
055        }
056
057        /**
058         * @param entityManager the entityManager to set
059         */
060        public void setEntityManager(EntityManager entityManager) {
061                this.entityManager = entityManager;
062        }
063
064    @Override
065        public DocumentType findByName(String name){
066                return findByName(name, true); // by default find by name is case sensitive
067        }
068
069    @Override
070    public DocumentType findByName(String name, boolean caseSensitive) {
071        org.kuali.rice.core.api.criteria.QueryByCriteria.Builder builder =
072                org.kuali.rice.core.api.criteria.QueryByCriteria.Builder.create();
073        List<Predicate> predicates = new ArrayList<Predicate>();
074        if (caseSensitive) {
075            if (StringUtils.contains(name, "*")) {
076                name = StringUtils.replace(name, "*", "%");
077                predicates.add(likeIgnoreCase("name", name.trim()));
078            } else {
079                predicates.add(equal("name", name));
080            }
081
082        } else {
083            if (name.contains("*") || name.contains("%")) {
084                name = name.replace("*", "%");
085                predicates.add(likeIgnoreCase("name", name));
086            } else {
087                predicates.add(equalIgnoreCase("name", name));
088            }
089
090        }
091        predicates.add(equal("currentInd", Boolean.TRUE));
092        Predicate[] preds = predicates.toArray(new Predicate[predicates.size()]);
093        builder.setPredicates(preds);
094        QueryResults<DocumentType> results = getDataObjectService().findMatching(DocumentType.class, builder.build());
095        if (results != null && !results.getResults().isEmpty()) {
096            return results.getResults().get(0);
097        }
098
099        return null;
100    }
101
102    @Override
103        public Integer getMaxVersionNumber(String docTypeName) {
104        TypedQuery<Integer> query = getEntityManager().
105                createNamedQuery("DocumentType.GetMaxVersionNumber", Integer.class);
106        query.setParameter("docTypeName", docTypeName);
107        return query.getSingleResult();
108        }
109
110    @Override
111        public List<String> getChildDocumentTypeIds(String parentDocumentTypeId) {
112                try {
113            getEntityManager().flush();
114            TypedQuery<String> query =
115                    getEntityManager().createNamedQuery("DocumentType.GetChildDocumentTypeIds", String.class);
116            query.setParameter("parentDocumentTypeId", parentDocumentTypeId);
117            return query.getResultList();
118                } catch (Exception e) {
119                        LOG.error("Error occured fetching children document type ids for document type " + parentDocumentTypeId, e);
120                        throw new RuntimeException(e);
121                }
122        }
123
124    @Override
125        public Collection<DocumentType> find(DocumentType documentType, DocumentType docTypeParent, boolean climbHierarchy) {
126                LOG.debug("documentType: "+ documentType);
127                LOG.debug("docTypeParent: "+ docTypeParent);
128                LOG.debug("climbHierarchy: " + climbHierarchy);
129        org.kuali.rice.core.api.criteria.QueryByCriteria.Builder builder = org.kuali.rice.core.api.criteria
130                .QueryByCriteria.Builder.create();
131        List<Predicate> predicates = new ArrayList<Predicate>();
132
133        if (documentType != null && !org.apache.commons.lang.StringUtils.isEmpty(documentType.getLabel())) {
134            predicates.add(likeIgnoreCase("label",documentType.getLabel().trim()));
135                }
136                if (documentType != null && !org.apache.commons.lang.StringUtils.isEmpty(documentType.getName())) {
137                        String docTypeName = documentType.getName();
138            predicates.add(likeIgnoreCase("name","%" + docTypeName.trim() + "%"));
139                }
140                if (documentType != null && documentType.getActive() != null) {
141            predicates.add(equal("active", documentType.getActive()));
142                }
143                if (documentType != null && documentType.getDocumentTypeId() != null) {
144            predicates.add(equal("documentTypeId",documentType.getDocumentTypeId()));
145                }
146                if (documentType != null && documentType.getActualApplicationId() != null){
147            predicates.add(equal("actualApplicationId", documentType.getActualApplicationId()));
148                }
149                if (docTypeParent != null) {
150                        if (StringUtils.isNotBlank(docTypeParent.getName())) {
151                List<Predicate> parentCriteria = new ArrayList<Predicate>();
152                                List<Predicate> childCriteria = new ArrayList<Predicate>();
153                                //Criteria parentCrit = new Criteria(DocumentType.class.getName());
154                                addParentIdOrCriteria(docTypeParent.getDocumentTypeId(), parentCriteria);
155
156                                if (climbHierarchy) {
157                                        assembleChildrenCriteria(docTypeParent.getChildrenDocTypes(), childCriteria);
158                                }
159                parentCriteria.add(equal("currentInd", Boolean.TRUE));
160                predicates.add(and((Predicate[]) parentCriteria.toArray(new Predicate[parentCriteria.size()])));
161                if(!childCriteria.isEmpty()){
162                    predicates.add(or((Predicate[])childCriteria.toArray(new Predicate[childCriteria.size()])));
163                }
164                        }
165                } else {
166                        if (documentType != null && StringUtils.isNotBlank(documentType.getName())) {
167                                DocumentType searchDocumentType = findByName(documentType.getName());
168                                if ((searchDocumentType != null) && climbHierarchy) {
169                                        LOG.debug("searchDocumentType: "+ searchDocumentType);
170                    List<Predicate> parentPredicates = new ArrayList<Predicate>();
171                    addParentIdOrCriteria(searchDocumentType.getDocumentTypeId(), parentPredicates);
172                    assembleChildrenCriteria(searchDocumentType.getChildrenDocTypes(), parentPredicates);
173                                        parentPredicates.add(equal("currentInd", Boolean.TRUE));
174                                        predicates.add(or(parentPredicates.toArray(new Predicate[parentPredicates.size()])));
175                                }
176                        }
177                }
178                predicates.add(equal("currentInd", Boolean.TRUE));
179        Predicate[] preds = predicates.toArray(new Predicate[predicates.size()]);
180        builder.setPredicates(preds);
181        QueryResults<DocumentType> results = getDataObjectService().findMatching(DocumentType.class, builder.build());
182        return results.getResults();
183        }
184
185    private void addParentIdOrCriteria(String parentId, List<Predicate> parentPredicates) {
186        parentPredicates.add(equal("docTypeParentId", parentId));
187    }
188
189        private void assembleChildrenCriteria(Collection<DocumentType> childrenDocTypes, List<Predicate> parentPredicates) {
190                if (childrenDocTypes != null) {
191            for (DocumentType child : childrenDocTypes) {
192                                addParentIdOrCriteria(child.getParentId(), parentPredicates);
193                                assembleChildrenCriteria(child.getChildrenDocTypes(), parentPredicates);
194                        }
195                }
196        }
197
198    @Override
199    public List<DocumentType> findAllCurrent() {
200        org.kuali.rice.core.api.criteria.QueryByCriteria.Builder builder = org.kuali
201            .rice.core.api.criteria.QueryByCriteria.Builder.create();
202        builder.setPredicates(
203                equal("currentInd", Boolean.TRUE)
204        );
205        QueryResults<DocumentType> results = getDataObjectService().findMatching(DocumentType.class, builder.build());
206        return results.getResults();
207    }
208
209    @Override
210    public List<DocumentType> findAllCurrentByName(String name) {
211        org.kuali.rice.core.api.criteria.QueryByCriteria.Builder builder = org.kuali
212                .rice.core.api.criteria.QueryByCriteria.Builder.create();
213        builder.setPredicates(equal("name", name), equal("currentInd", Boolean.TRUE));
214        QueryResults<DocumentType> results = getDataObjectService().findMatching(DocumentType.class, builder.build());
215        return results.getResults();
216    }
217
218    @Override
219    public String findDocumentTypeIdByName(String documentTypeName) {
220        TypedQuery<String> query = getEntityManager().
221                createNamedQuery("DocumentType.GetIdByName", String.class);
222        query.setParameter("docTypeName", documentTypeName);
223        try {
224            return query.getSingleResult();
225        } catch (NoResultException e) {
226            return null;
227        }
228    }
229
230    @Override
231    public String findDocumentTypeNameById(String documentTypeId) {
232        TypedQuery<String> query = getEntityManager().
233                createNamedQuery("DocumentType.FindDocumentTypeNameById", String.class);
234        query.setParameter("documentTypeId",documentTypeId);
235        try {
236            return query.getSingleResult();
237        } catch (NoResultException e) {
238            return null;
239        }
240    }
241
242    @Override
243    public DocumentType findDocumentTypeByDocumentId(String documentId){
244        TypedQuery<DocumentType> query =
245                getEntityManager().createNamedQuery("DocumentType.GetDocumentTypeByDocumentId", DocumentType.class);
246        query.setParameter("documentId", documentId);
247        try {
248            return query.getSingleResult();
249        } catch (NoResultException e) {
250            return null;
251        }
252    }
253
254    @Override
255    public void incrementOptimisticLock(String documentTypeId) {
256        DocumentType documentType = getEntityManager().getReference(DocumentType.class, documentTypeId);
257        getEntityManager().lock(documentType, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
258    }
259
260    @Override
261    public String findParentNameByName(String documentTypeName) {
262        TypedQuery<String> query = getEntityManager().createNamedQuery("DocumentType.parentNameByName", String.class);
263        query.setParameter("docTypeName", documentTypeName);
264        try {
265            return query.getSingleResult();
266        } catch (NoResultException e) {
267            return null;
268        }
269    }
270
271
272
273    public DataObjectService getDataObjectService() {
274        return dataObjectService;
275    }
276
277    @Required
278    public void setDataObjectService(DataObjectService dataObjectService) {
279        this.dataObjectService = dataObjectService;
280    }
281
282
283}