001/**
002 * Copyright 2005-2017 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.krms.impl.repository;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krad.data.DataObjectService;
020import org.kuali.rice.krad.data.PersistenceOption;
021import org.kuali.rice.krms.api.repository.action.ActionDefinition;
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029
030import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.deleteMatching;
031import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.findMatchingOrderBy;
032import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.findSingleMatching;
033
034/**
035 * Implementation of the interface for accessing KRMS repository Action related
036 * business objects.
037 *
038 * @author Kuali Rice Team (rice.collab@kuali.org)
039 */
040public class ActionBoServiceImpl implements ActionBoService {
041
042    private DataObjectService dataObjectService;
043
044    /**
045     * This overridden method creates a KRMS Action in the repository.
046     */
047    @Override
048    public ActionDefinition createAction(ActionDefinition action) {
049        if (action == null) {
050            throw new IllegalArgumentException("action is null");
051        }
052
053        final String actionNameKey = action.getName();
054        final String actionNamespaceKey = action.getNamespace();
055        final ActionDefinition existing = getActionByNameAndNamespace(actionNameKey, actionNamespaceKey);
056
057        if (existing != null) {
058            throw new IllegalStateException("the action to create already exists: " + action);
059        }
060
061        ActionBo bo = ActionBo.from(action);
062        RuleBo rule = new RuleBo();
063        rule.setId(action.getRuleId());
064        rule.getActions().add(bo);
065        bo.setRule(rule);
066
067        bo = dataObjectService.save(bo, PersistenceOption.FLUSH);
068
069        return ActionBo.to(bo);
070    }
071
072    /**
073     * This overridden method updates an existing Action in the repository.
074     */
075    @Override
076    public ActionDefinition updateAction(ActionDefinition action) {
077        if (action == null) {
078            throw new IllegalArgumentException("action is null");
079        }
080
081        // must already exist to be able to update
082        final String actionIdKey = action.getId();
083        final ActionBo existing = dataObjectService.find(ActionBo.class, actionIdKey);
084
085        if (existing == null) {
086            throw new IllegalStateException("the action does not exist: " + action);
087        }
088
089        final ActionDefinition toUpdate;
090
091        if (existing.getId().equals(action.getId())) {
092            toUpdate = action;
093        } else {
094            // if passed in id does not match existing id, correct it
095            final ActionDefinition.Builder builder = ActionDefinition.Builder.create(action);
096            builder.setId(existing.getId());
097            toUpdate = builder.build();
098        }
099
100        // copy all updateable fields to bo
101        ActionBo boToUpdate = ActionBo.from(toUpdate);
102
103        // delete any old, existing attributes
104        deleteMatching(dataObjectService, ActionAttributeBo.class, Collections.singletonMap("action.id",
105                toUpdate.getId()));
106
107        // update the action and create new attributes
108        final ActionBo updatedData = dataObjectService.save(boToUpdate, PersistenceOption.FLUSH);
109
110        return ActionBo.to(updatedData);
111    }
112
113    /**
114     * This overridden method retrieves an Action from the repository.
115     */
116    @Override
117    public ActionDefinition getActionByActionId(String actionId) {
118        if (StringUtils.isBlank(actionId)) {
119            throw new IllegalArgumentException("action ID is null or blank");
120        }
121
122        ActionBo bo = dataObjectService.find(ActionBo.class, actionId);
123
124        return ActionBo.to(bo);
125    }
126
127    /**
128     * This overridden method retrieves an Action from the repository.
129     */
130    @Override
131    public ActionDefinition getActionByNameAndNamespace(String name, String namespace) {
132        if (StringUtils.isBlank(name)) {
133            throw new IllegalArgumentException("name is blank");
134        }
135        if (StringUtils.isBlank(namespace)) {
136            throw new IllegalArgumentException("namespace is blank");
137        }
138
139        final Map<String, Object> map = new HashMap<String, Object>();
140        map.put("name", name);
141        map.put("namespace", namespace);
142
143        ActionBo myAction = findSingleMatching(dataObjectService, ActionBo.class, map);
144
145        return ActionBo.to(myAction);
146    }
147
148    /**
149     * This overridden method retrieves a List of Actions associated with a Rule.
150     */
151    @Override
152    public List<ActionDefinition> getActionsByRuleId(String ruleId) {
153        if (StringUtils.isBlank(ruleId)) {
154            throw new IllegalArgumentException("ruleId is null or blank");
155        }
156
157        List<ActionBo> bos = findMatchingOrderBy(dataObjectService, ActionBo.class, Collections.singletonMap("ruleId",
158                ruleId), "sequenceNumber", true);
159
160        return convertListOfBosToImmutables(bos);
161    }
162
163    /**
164     * This overridden method retrieves a specific Action associated with a Rule.
165     */
166    @Override
167    public ActionDefinition getActionByRuleIdAndSequenceNumber(String ruleId, Integer sequenceNumber) {
168        if (StringUtils.isBlank(ruleId)) {
169            throw new IllegalArgumentException("ruleId is null or blank");
170        }
171        if (sequenceNumber == null) {
172            throw new IllegalArgumentException("sequenceNumber is null");
173        }
174
175        final Map<String, Object> map = new HashMap<String, Object>();
176        map.put("ruleId", ruleId);
177        map.put("sequenceNumber", sequenceNumber);
178        ActionBo bo = dataObjectService.find(ActionBo.class, map);
179
180        return ActionBo.to(bo);
181    }
182
183    /**
184     * This method retrieves an ActionAttributeBo by id
185     *
186     * @see org.kuali.rice.krms.impl.repository.ActionBoService#getActionsByRuleId(java.lang.String)
187     */
188    public ActionAttributeBo getActionAttributeById(String attrId) {
189        if (StringUtils.isBlank(attrId)) {
190            return null;
191        }
192
193        return dataObjectService.find(ActionAttributeBo.class, attrId);
194    }
195
196    /**
197     * Sets the dataObjectService attribute value.
198     *
199     * @param dataObjectService The dataObjectService to set.
200     */
201    public void setDataObjectService(final DataObjectService dataObjectService) {
202        this.dataObjectService = dataObjectService;
203    }
204
205    /**
206     * Converts a List<ActionBo> to an Unmodifiable List<Action>
207     *
208     * @param actionBos a mutable List<ActionBo> to made completely immutable.
209     * @return An unmodifiable List<Action>
210     */
211    List<ActionDefinition> convertListOfBosToImmutables(final Collection<ActionBo> actionBos) {
212        if (actionBos == null) {
213            return Collections.emptyList();
214        }
215
216        ArrayList<ActionDefinition> actions = new ArrayList<ActionDefinition>();
217
218        for (ActionBo bo : actionBos) {
219            ActionDefinition action = ActionBo.to(bo);
220            actions.add(action);
221        }
222
223        return Collections.unmodifiableList(actions);
224    }
225}