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.impl.peopleflow;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.apache.commons.lang.StringUtils;
020import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
021import org.kuali.rice.core.api.exception.RiceIllegalStateException;
022import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition;
023import org.kuali.rice.kew.api.peopleflow.PeopleFlowDelegate;
024import org.kuali.rice.kew.api.peopleflow.PeopleFlowMember;
025import org.kuali.rice.kew.api.peopleflow.PeopleFlowService;
026import org.kuali.rice.kew.api.repository.type.KewTypeDefinition;
027import org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService;
028import org.kuali.rice.kew.impl.KewImplConstants;
029import org.kuali.rice.krad.service.BusinessObjectService;
030import org.kuali.rice.kew.responsibility.service.ResponsibilityIdService;
031
032import java.util.Collection;
033import java.util.HashMap;
034import java.util.Map;
035
036public class PeopleFlowServiceImpl implements PeopleFlowService {
037
038    private BusinessObjectService businessObjectService;
039    private KewTypeRepositoryService kewTypeRepositoryService;
040    private ResponsibilityIdService responsibilityIdService;
041
042    @Override
043    public PeopleFlowDefinition getPeopleFlow(String peopleFlowId) {
044        if (StringUtils.isBlank(peopleFlowId)) {
045            throw new RiceIllegalArgumentException("peopleFlowId is null or blank");
046        }
047
048        return PeopleFlowBo.to(getPeopleFlowBo(peopleFlowId));
049    }
050
051    @Override
052    public PeopleFlowDefinition getPeopleFlowByName(String namespaceCode, String name) {
053        if (StringUtils.isBlank(namespaceCode)) {
054            throw new RiceIllegalArgumentException("namespaceCode is null or blank");
055        }
056
057        if (StringUtils.isBlank(name)) {
058            throw new RiceIllegalArgumentException("name is null or blank");
059        }
060
061        return PeopleFlowBo.to(getPeopleFlowBoByName(namespaceCode, name));
062    }
063
064    @Override
065    public PeopleFlowDefinition createPeopleFlow(PeopleFlowDefinition peopleFlow) {
066        validateForCreate(peopleFlow);
067        KewTypeDefinition kewTypeDefinition = loadKewTypeDefinition(peopleFlow);
068        PeopleFlowBo peopleFlowBo = PeopleFlowBo.from(peopleFlow, kewTypeDefinition);
069        peopleFlowBo = savePeopleFlow(peopleFlowBo);
070        return PeopleFlowBo.to(peopleFlowBo);
071    }
072
073    @Override
074    public PeopleFlowDefinition updatePeopleFlow(PeopleFlowDefinition peopleFlow) {
075        PeopleFlowBo existingBo = validateForUpdate(peopleFlow);
076        KewTypeDefinition kewTypeDefinition = loadKewTypeDefinition(peopleFlow);
077        PeopleFlowBo peopleFlowBo = PeopleFlowBo.fromAndUpdate(peopleFlow, kewTypeDefinition, existingBo);
078        peopleFlowBo = savePeopleFlow(peopleFlowBo);
079        return PeopleFlowBo.to(peopleFlowBo);
080    }
081
082    protected KewTypeDefinition loadKewTypeDefinition(PeopleFlowDefinition peopleFlow) {
083        KewTypeDefinition kewTypeDefinition = null;
084        if (peopleFlow.getTypeId() != null) {
085            kewTypeDefinition = getKewTypeRepositoryService().getTypeById(peopleFlow.getTypeId());
086            if (kewTypeDefinition == null) {
087                throw new RiceIllegalArgumentException("Failed to locate a KewTypeDefinition for the given type id of '" + peopleFlow.getTypeId() + "'");
088            }
089        }
090        return kewTypeDefinition;
091    }
092
093    protected void validateForCreate(PeopleFlowDefinition peopleFlow) {
094        if (peopleFlow == null) {
095            throw new RiceIllegalArgumentException("peopleFlow is null");
096        }
097        if (StringUtils.isNotBlank(peopleFlow.getId())) {
098            throw new RiceIllegalArgumentException("Attempted to create a new PeopleFlow definition with a specified peopleFlowId of '"
099                    + peopleFlow.getId() + "'.  This is not allowed, when creating a new PeopleFlow definition, id must be null.");
100        }
101        if (peopleFlow.getVersionNumber() != null) {
102            throw new RiceIllegalArgumentException("The version number on the given PeopleFlow definition was not null, value was " + peopleFlow.getVersionNumber() +
103                    "  When creating a new PeopleFlow, the given version number must be null.");
104        }
105        validatePeopleFlowMembersForCreate(peopleFlow);
106        if (getPeopleFlowBoByName(peopleFlow.getNamespaceCode(), peopleFlow.getName()) != null) {
107            throw new RiceIllegalStateException("A PeopleFlow definition with the namespace code '" + peopleFlow.getNamespaceCode() +
108            "' and name '" + peopleFlow.getName() + "' already exists.");
109        }
110    }
111
112    protected void validatePeopleFlowMembersForCreate(PeopleFlowDefinition peopleFlowDefinition) {
113        for (PeopleFlowMember member : peopleFlowDefinition.getMembers()) {
114            if (StringUtils.isNotBlank(member.getResponsibilityId())) {
115                throw new RiceIllegalArgumentException("Attempted to create a new PeopleFlow with a member that already had a responsibility id of '" +
116                        member.getResponsibilityId() + "' specified.  All members must have a null responsibility id upon creation.");
117            }
118            for (PeopleFlowDelegate delegate : member.getDelegates()) {
119                if (StringUtils.isNotBlank(delegate.getResponsibilityId())) {
120                    throw new RiceIllegalArgumentException("Attempted to create a new PeopleFlow with a delegate that already had a responsibility id of '" +
121                            delegate.getResponsibilityId() + "' specified.  All delegates must have a null responsibility id upon creation.");
122                }
123            }
124        }
125    }
126
127    protected PeopleFlowBo validateForUpdate(PeopleFlowDefinition peopleFlow) {
128        if (peopleFlow == null) {
129            throw new RiceIllegalArgumentException("peopleFlow is null");
130        }
131        if (StringUtils.isBlank(peopleFlow.getId())) {
132            throw new RiceIllegalArgumentException("Attempted to update a PeopleFlow definition without a specified peopleFlowId, the id is required when performing an update.");
133        }
134        if (peopleFlow.getVersionNumber() == null) {
135            throw new RiceIllegalArgumentException("The version number on the given PeopleFlow definition was null, a version number must be supplied when updating a PeopleFlow.");
136        }
137        PeopleFlowBo peopleFlowBo = getPeopleFlowBo(peopleFlow.getId());
138        if (peopleFlowBo == null) {
139            throw new RiceIllegalArgumentException("Failed to locate an existing PeopleFlow definition with the given id of '" + peopleFlow.getId() + "'");
140        }
141        return peopleFlowBo;
142    }
143
144    protected PeopleFlowBo getPeopleFlowBo(String peopleFlowId) {
145        if (StringUtils.isBlank(peopleFlowId)) {
146            throw new RiceIllegalArgumentException("peopleFlowId was a null or blank value");
147        }
148        return businessObjectService.findBySinglePrimaryKey(PeopleFlowBo.class, peopleFlowId);
149    }
150
151    protected PeopleFlowBo getPeopleFlowBoByName(String namespaceCode, String name) {
152        if (StringUtils.isBlank(namespaceCode)) {
153            throw new RiceIllegalArgumentException("namespaceCode was a null or blank value");
154        }
155        if (StringUtils.isBlank(name)) {
156            throw new RiceIllegalArgumentException("name was a null or blank value");
157        }
158        Map<String,String> criteria = new HashMap<String,String>();
159                criteria.put(KewImplConstants.PropertyConstants.NAMESPACE_CODE, namespaceCode);
160        criteria.put(KewImplConstants.PropertyConstants.NAME, name);
161                Collection<PeopleFlowBo> peopleFlows = businessObjectService.findMatching(PeopleFlowBo.class, criteria);
162        if (CollectionUtils.isEmpty(peopleFlows)) {
163            return null;
164        } else if (peopleFlows.size() > 1) {
165            throw new RiceIllegalStateException("Found more than one PeopleFlow with the given namespace code '" + namespaceCode + "' and name '" + name + "'");
166                }
167        return peopleFlows.iterator().next();
168    }
169
170    protected PeopleFlowBo savePeopleFlow(PeopleFlowBo peopleFlowBo) {
171                if ( peopleFlowBo == null ) {
172                        return null;
173                }
174        assignResponsibilityIds(peopleFlowBo);
175        return businessObjectService.save(peopleFlowBo);
176    }
177
178    protected void assignResponsibilityIds(PeopleFlowBo peopleFlowBo) {
179        if (CollectionUtils.isNotEmpty(peopleFlowBo.getMembers())) {
180            for (PeopleFlowMemberBo memberBo : peopleFlowBo.getMembers()) {
181                if (StringUtils.isBlank(memberBo.getResponsibilityId())) {
182                    memberBo.setResponsibilityId(responsibilityIdService.getNewResponsibilityId());
183                }
184                if (CollectionUtils.isNotEmpty(memberBo.getDelegates())) {
185                    for (PeopleFlowDelegateBo delegateBo : memberBo.getDelegates()) {
186                        if (StringUtils.isBlank(delegateBo.getResponsibilityId())) {
187                            delegateBo.setResponsibilityId(responsibilityIdService.getNewResponsibilityId());
188                        }
189                    }
190                }
191            }
192        }
193    }
194
195    public BusinessObjectService getBusinessObjectService() {
196        return businessObjectService;
197    }
198
199    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
200        this.businessObjectService = businessObjectService;
201    }
202
203    public KewTypeRepositoryService getKewTypeRepositoryService() {
204        return kewTypeRepositoryService;
205    }
206
207    public void setKewTypeRepositoryService(KewTypeRepositoryService kewTypeRepositoryService) {
208        this.kewTypeRepositoryService = kewTypeRepositoryService;
209    }
210
211    public ResponsibilityIdService getResponsibilityIdService() {
212        return responsibilityIdService;
213    }
214
215    public void setResponsibilityIdService(ResponsibilityIdService responsibilityIdService) {
216        this.responsibilityIdService = responsibilityIdService;
217    }
218    
219}