View Javadoc
1   /**
2    * Copyright 2005-2015 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  public class FunctionBoServiceImpl implements FunctionRepositoryService, FunctionBoService {
42  
43      private DataObjectService dataObjectService;
44  
45      // used for converting lists of BOs to model objects
46      private static final ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition> toFunctionDefinition =
47              new ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition>() {
48                  public FunctionDefinition transform(FunctionBo input) {
49                      return FunctionBo.to(input);
50                  };
51              };
52  
53      @Override
54      public FunctionDefinition getFunction(String functionId) {
55          return getFunctionById(functionId);
56      }
57  
58      @Override
59      public List<FunctionDefinition> getFunctions(List<String> functionIds) {
60  
61          if (functionIds == null) {
62              throw new RiceIllegalArgumentException();
63          }
64  
65          List<FunctionDefinition> functionDefinitions = new ArrayList<FunctionDefinition>();
66          for (String functionId : functionIds) {
67              if (!StringUtils.isBlank(functionId)) {
68                  FunctionDefinition functionDefinition = getFunctionById(functionId);
69                  if (functionDefinition != null) {
70                      functionDefinitions.add(functionDefinition);
71                  }
72              }
73          }
74          return Collections.unmodifiableList(functionDefinitions);
75      }
76  
77      /**
78       * This method will create a {@link FunctionDefinition} as described
79       * by the function passed in.
80       *
81       * @see org.kuali.rice.krms.impl.repository.FunctionBoService#createFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
82       */
83      @Override
84      public FunctionDefinition createFunction(FunctionDefinition function) {
85          if (function == null) {
86              throw new IllegalArgumentException("function is null");
87          }
88  
89          final String nameKey = function.getName();
90          final String namespaceKey = function.getNamespace();
91          final FunctionDefinition existing = getFunctionByNameAndNamespace(nameKey, namespaceKey);
92  
93          if (existing != null && existing.getName().equals(nameKey) && existing.getNamespace().equals(namespaceKey)) {
94              throw new IllegalStateException("the function to create already exists: " + function);
95          }
96  
97          FunctionBo functionBo = FunctionBo.from(function);
98          for (FunctionParameterBo param : functionBo.getParameters()) {
99              param.setFunction(functionBo);
100         }
101 
102         functionBo = dataObjectService.save(functionBo, PersistenceOption.FLUSH);
103 
104         return FunctionBo.to(functionBo);
105     }
106 
107     /**
108      * This overridden method updates an existing Function in the repository
109      *
110      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#updateFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
111      */
112     @Override
113     public FunctionDefinition updateFunction(FunctionDefinition function) {
114         if (function == null) {
115             throw new IllegalArgumentException("function is null");
116         }
117 
118         final String functionIdKey = function.getId();
119         final FunctionDefinition existing = getFunctionById(functionIdKey);
120 
121         if (existing == null) {
122             throw new IllegalStateException("the function does not exist: " + function);
123         }
124 
125         final FunctionDefinition toUpdate;
126 
127         if (!existing.getId().equals(function.getId())) {
128             final FunctionDefinition.Builder builder = FunctionDefinition.Builder.create(function);
129             builder.setId(existing.getId());
130             toUpdate = builder.build();
131         } else {
132             toUpdate = function;
133         }
134 
135         return FunctionBo.to(dataObjectService.save(FunctionBo.from(toUpdate), PersistenceOption.FLUSH));
136         // TODO: Do we need to return the updated FunctionDefinition?
137     }
138 
139     /**
140      * This overridden method retrieves a function by the given function id.
141      *
142      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionById(java.lang.String)
143      */
144     @Override
145     public FunctionDefinition getFunctionById(String functionId) {
146         if (StringUtils.isBlank(functionId)) {
147             throw new RiceIllegalArgumentException("functionId is null or blank");
148         }
149 
150         FunctionBo functionBo = dataObjectService.find(FunctionBo.class, functionId);
151 
152         return FunctionBo.to(functionBo);
153     }
154 
155     /**
156      * This overridden method retrieves a function by the given name and namespace.
157      *
158      * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionByNameAndNamespace(java.lang.String,
159      * java.lang.String)
160      */
161     public FunctionDefinition getFunctionByNameAndNamespace(String name, String namespace) {
162         if (StringUtils.isBlank(name)) {
163             throw new IllegalArgumentException("name is null or blank");
164         }
165         if (StringUtils.isBlank(namespace)) {
166             throw new IllegalArgumentException("namespace is null or blank");
167         }
168 
169         final Map<String, Object> map = new HashMap<String, Object>();
170         map.put("name", name);
171         map.put("namespace", namespace);
172         QueryByCriteria query = QueryByCriteria.Builder.andAttributes(map).build();
173         QueryResults<FunctionBo> results = dataObjectService.findMatching(FunctionBo.class, query);
174 
175         if (results == null || results.getResults().size() == 0) {
176             // fall through and return null
177         } else if (results.getResults().size() == 1) {
178             return FunctionBo.to(results.getResults().get(0));
179         } else if (results.getResults().size() > 1) {
180             throw new IllegalStateException("there can be only one FunctionDefinition for a given name and namespace");
181         }
182 
183         return null;
184     }
185 
186     /**
187      * Gets all of the {@link FunctionDefinition}s within the given namespace
188      *
189      * @param namespace the namespace in which to get the functions
190      * @return the list of function definitions, or if none are found, an empty list
191      */
192     public List<FunctionDefinition> getFunctionsByNamespace(String namespace) {
193         if (StringUtils.isBlank(namespace)) {
194             throw new IllegalArgumentException("namespace is null or blank");
195         }
196 
197         QueryByCriteria criteria = QueryByCriteria.Builder.forAttribute("namespace", namespace).build();
198         QueryResults<FunctionBo> queryResults = dataObjectService.findMatching(FunctionBo.class, criteria);
199         List<FunctionBo> functionBos = queryResults.getResults();
200 
201         return convertFunctionBosToImmutables(functionBos);
202     }
203 
204     /**
205      * Converts a Collection of FunctionBos to an Unmodifiable List of Agendas
206      *
207      * @param functionBos a mutable List of FunctionBos to made completely immutable.
208      * @return An unmodifiable List of FunctionDefinitions
209      */
210     private List<FunctionDefinition> convertFunctionBosToImmutables(final Collection<FunctionBo> functionBos) {
211         if (CollectionUtils.isEmpty(functionBos)) {
212             return Collections.emptyList();
213         }
214         return Collections.unmodifiableList(ModelObjectUtils.transform(functionBos, toFunctionDefinition));
215     }
216 
217     public void setDataObjectService(DataObjectService dataObjectService) {
218         this.dataObjectService = dataObjectService;
219     }
220 }