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.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.kuali.rice.core.api.criteria.QueryByCriteria; 021import org.kuali.rice.core.api.criteria.QueryResults; 022import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 023import org.kuali.rice.core.api.mo.ModelObjectUtils; 024import org.kuali.rice.krad.data.DataObjectService; 025import org.kuali.rice.krad.data.PersistenceOption; 026import org.kuali.rice.krms.api.repository.function.FunctionDefinition; 027import org.kuali.rice.krms.api.repository.function.FunctionRepositoryService; 028 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.Collections; 032import java.util.HashMap; 033import java.util.List; 034import java.util.Map; 035 036/** 037 * Default implementation of the {@link FunctionRepositoryService}. 038 * 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041public class FunctionBoServiceImpl implements FunctionRepositoryService, FunctionBoService { 042 043 private DataObjectService dataObjectService; 044 045 // used for converting lists of BOs to model objects 046 private static final ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition> toFunctionDefinition = 047 new ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition>() { 048 public FunctionDefinition transform(FunctionBo input) { 049 return FunctionBo.to(input); 050 }; 051 }; 052 053 @Override 054 public FunctionDefinition getFunction(String functionId) { 055 return getFunctionById(functionId); 056 } 057 058 @Override 059 public List<FunctionDefinition> getFunctions(List<String> functionIds) { 060 061 if (functionIds == null) { 062 throw new RiceIllegalArgumentException(); 063 } 064 065 List<FunctionDefinition> functionDefinitions = new ArrayList<FunctionDefinition>(); 066 for (String functionId : functionIds) { 067 if (!StringUtils.isBlank(functionId)) { 068 FunctionDefinition functionDefinition = getFunctionById(functionId); 069 if (functionDefinition != null) { 070 functionDefinitions.add(functionDefinition); 071 } 072 } 073 } 074 return Collections.unmodifiableList(functionDefinitions); 075 } 076 077 /** 078 * This method will create a {@link FunctionDefinition} as described 079 * by the function passed in. 080 * 081 * @see org.kuali.rice.krms.impl.repository.FunctionBoService#createFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition) 082 */ 083 @Override 084 public FunctionDefinition createFunction(FunctionDefinition function) { 085 if (function == null) { 086 throw new IllegalArgumentException("function is null"); 087 } 088 089 final String nameKey = function.getName(); 090 final String namespaceKey = function.getNamespace(); 091 final FunctionDefinition existing = getFunctionByNameAndNamespace(nameKey, namespaceKey); 092 093 if (existing != null && existing.getName().equals(nameKey) && existing.getNamespace().equals(namespaceKey)) { 094 throw new IllegalStateException("the function to create already exists: " + function); 095 } 096 097 FunctionBo functionBo = FunctionBo.from(function); 098 for (FunctionParameterBo param : functionBo.getParameters()) { 099 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}