View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krms.impl.repository;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.criteria.QueryByCriteria;
21  import org.kuali.rice.core.api.criteria.QueryResults;
22  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
23  import org.kuali.rice.core.api.mo.ModelObjectUtils;
24  import org.kuali.rice.krad.data.DataObjectService;
25  import org.kuali.rice.krad.data.PersistenceOption;
26  import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
27  import org.kuali.rice.krms.api.repository.function.FunctionRepositoryService;
28  
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * Default implementation of the {@link FunctionRepositoryService}.
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   *
41   */
42  public class FunctionBoServiceImpl implements FunctionRepositoryService, FunctionBoService {
43  
44      private DataObjectService dataObjectService;
45  
46      // used for converting lists of BOs to model objects
47      private static final ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition> toFunctionDefinition =
48              new ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition>() {
49                  public FunctionDefinition transform(FunctionBo input) {
50                      return FunctionBo.to(input);
51                  };
52              };
53  
54      @Override
55      public FunctionDefinition getFunction(String functionId) {
56          return getFunctionById(functionId);
57      }
58  
59      @Override
60      public List<FunctionDefinition> getFunctions(List<String> functionIds) {
61  
62          if (functionIds == null) throw new RiceIllegalArgumentException();
63  
64          List<FunctionDefinition> functionDefinitions = new ArrayList<FunctionDefinition>();
65          for (String functionId : functionIds){
66              if (!StringUtils.isBlank(functionId)) {
67                  FunctionDefinition functionDefinition = getFunctionById(functionId);
68                  if (functionDefinition != null) {
69                      functionDefinitions.add(functionDefinition);
70                  }
71              }
72          }
73          return Collections.unmodifiableList(functionDefinitions);
74      }
75  
76      /**
77       * This method will create a {@link FunctionDefinition} as described
78       * by the function passed in.
79       *
80       * @see org.kuali.rice.krms.impl.repository.FunctionBoService#createFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
81       */
82      @Override
83      public FunctionDefinition createFunction(FunctionDefinition function) {
84          if (function == null){
85              throw new IllegalArgumentException("function is null");
86          }
87  
88          final String nameKey = function.getName();
89          final String namespaceKey = function.getNamespace();
90          final FunctionDefinition existing = getFunctionByNameAndNamespace(nameKey, namespaceKey);
91  
92          if (existing != null && existing.getName().equals(nameKey) && existing.getNamespace().equals(namespaceKey)){
93              throw new IllegalStateException("the function to create already exists: " + function);
94          }
95  
96          FunctionBo functionBo = FunctionBo.from(function);
97          for (FunctionParameterBo param : functionBo.getParameters()) {
98              param.setFunction(functionBo);
99          }
100 
101         functionBo = dataObjectService.save(functionBo, PersistenceOption.FLUSH);
102 
103         return FunctionBo.to(functionBo);
104     }
105 
106     /**
107      * This overridden method updates an existing Function in the repository
108      *
109      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#updateFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
110      */
111     @Override
112     public void updateFunction(FunctionDefinition function) {
113         if (function == null) {
114             throw new IllegalArgumentException("function is null");
115         }
116 
117         final String functionIdKey = function.getId();
118         final FunctionDefinition existing = getFunctionById(functionIdKey);
119 
120         if (existing == null) {
121             throw new IllegalStateException("the function does not exist: " + function);
122         }
123 
124         final FunctionDefinition toUpdate;
125 
126         if (!existing.getId().equals(function.getId())) {
127             final FunctionDefinition.Builder builder = FunctionDefinition.Builder.create(function);
128             builder.setId(existing.getId());
129             toUpdate = builder.build();
130         } else {
131             toUpdate = function;
132         }
133 
134         dataObjectService.save(FunctionBo.from(toUpdate), PersistenceOption.FLUSH);
135         // TODO: Do we need to return the updated FunctionDefinition?
136     }
137 
138     /**
139      * This overridden method retrieves a function by the given function id.
140      *
141      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionById(java.lang.String)
142      */
143     @Override
144     public FunctionDefinition getFunctionById(String functionId) {
145         if (StringUtils.isBlank(functionId)) {
146             throw new RiceIllegalArgumentException("functionId is null or blank");
147         }
148 
149         FunctionBo functionBo = dataObjectService.find(FunctionBo.class, functionId);
150 
151         return FunctionBo.to(functionBo);
152     }
153 
154     /**
155      * This overridden method retrieves a function by the given name and namespace.
156      *
157      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionByNameAndNamespace(java.lang.String,
158      * java.lang.String)
159      */
160     public FunctionDefinition getFunctionByNameAndNamespace(String name, String namespace) {
161         if (StringUtils.isBlank(name)) {
162             throw new IllegalArgumentException("name is null or blank");
163         }
164         if (StringUtils.isBlank(namespace)) {
165             throw new IllegalArgumentException("namespace is null or blank");
166         }
167 
168         final Map<String, Object> map = new HashMap<String, Object>();
169         map.put("name", name);
170         map.put("namespace", namespace);
171         QueryByCriteria query = QueryByCriteria.Builder.andAttributes(map).build();
172         QueryResults<FunctionBo> results = dataObjectService.findMatching(FunctionBo.class, query);
173 
174         if (results == null || results.getResults().size() == 0) {
175             // fall through and return null
176         } else if (results.getResults().size() == 1) {
177             return FunctionBo.to(results.getResults().get(0));
178         } else if (results.getResults().size() > 1) {
179             throw new IllegalStateException("there can be only one FunctionDefinition for a given name and namespace");
180         }
181 
182         return null;
183     }
184 
185     /**
186      * Gets all of the {@link FunctionDefinition}s within the given namespace
187      *
188      * @param namespace the namespace in which to get the functions
189      * @return the list of function definitions, or if none are found, an empty list
190      */
191     public List<FunctionDefinition> getFunctionsByNamespace(String namespace) {
192         if (StringUtils.isBlank(namespace)){
193             throw new IllegalArgumentException("namespace is null or blank");
194         }
195 
196         QueryByCriteria criteria = QueryByCriteria.Builder.forAttribute("namespace", namespace).build();
197         QueryResults<FunctionBo> queryResults = dataObjectService.findMatching(FunctionBo.class, criteria);
198         List<FunctionBo> functionBos = queryResults.getResults();
199 
200         return convertFunctionBosToImmutables(functionBos);
201     }
202 
203     /**
204      * Converts a Collection of FunctionBos to an Unmodifiable List of Agendas
205      *
206      * @param functionBos a mutable List of FunctionBos to made completely immutable.
207      * @return An unmodifiable List of FunctionDefinitions
208      */
209     private List<FunctionDefinition> convertFunctionBosToImmutables(final Collection<FunctionBo> functionBos) {
210         if (CollectionUtils.isEmpty(functionBos)) {
211             return Collections.emptyList();
212         }
213         return Collections.unmodifiableList(ModelObjectUtils.transform(functionBos, toFunctionDefinition));
214     }
215 
216     public void setDataObjectService(DataObjectService dataObjectService) {
217         this.dataObjectService = dataObjectService;
218     }
219 }