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.krms.impl.repository;
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.mo.ModelObjectUtils;
022import org.kuali.rice.krad.service.BusinessObjectService;
023import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
024import org.kuali.rice.krms.api.repository.function.FunctionRepositoryService;
025
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Collections;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032
033/**
034 * Default implementation of the {@link FunctionRepositoryService}.
035 * 
036 * @author Kuali Rice Team (rice.collab@kuali.org)
037 *
038 */
039public class FunctionBoServiceImpl implements FunctionRepositoryService, FunctionBoService {
040                
041    private BusinessObjectService businessObjectService;
042
043    // used for converting lists of BOs to model objects
044    private static final ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition> toFunctionDefinition =
045            new ModelObjectUtils.Transformer<FunctionBo, FunctionDefinition>() {
046                public FunctionDefinition transform(FunctionBo input) {
047                    return FunctionBo.to(input);
048                };
049            };
050    
051        @Override
052        public FunctionDefinition getFunction(String functionId) {
053                return getFunctionById(functionId);
054        }
055        
056        @Override
057        public List<FunctionDefinition> getFunctions(List<String> functionIds) {
058
059        if (functionIds == null) throw new RiceIllegalArgumentException();
060
061                List<FunctionDefinition> functionDefinitions = new ArrayList<FunctionDefinition>();
062                for (String functionId : functionIds){
063            if (!StringUtils.isBlank(functionId)) {
064                FunctionDefinition functionDefinition = getFunctionById(functionId);
065                if (functionDefinition != null) {
066                    functionDefinitions.add(functionDefinition);
067                }
068            }
069                }
070        return Collections.unmodifiableList(functionDefinitions);
071        }
072        
073        /**
074         * This method will create a {@link FunctionDefintion} as described
075         * by the function passed in.
076         * 
077         * @see org.kuali.rice.krms.impl.repository.FunctionBoService#createFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
078         */
079        @Override
080        public FunctionDefinition createFunction(FunctionDefinition function) {
081                if (function == null){
082                throw new IllegalArgumentException("function is null");
083                }
084                
085                final String nameKey = function.getName();
086                final String namespaceKey = function.getNamespace();
087                final FunctionDefinition existing = getFunctionByNameAndNamespace(nameKey, namespaceKey);
088                if (existing != null && existing.getName().equals(nameKey) && existing.getNamespace().equals(namespaceKey)){
089            throw new IllegalStateException("the function to create already exists: " + function);                      
090                }
091                
092                FunctionBo functionBo = FunctionBo.from(function);
093                businessObjectService.save(functionBo);
094                return FunctionBo.to(functionBo);
095        }
096
097        /**
098         * This overridden method updates an existing Function in the repository
099         * 
100         * @see org.kuali.rice.krms.impl.repository.FunctionBoService#updateFunction(org.kuali.rice.krms.api.repository.function.FunctionDefinition)
101         */
102        @Override
103        public void updateFunction(FunctionDefinition function) {
104                if (function == null){
105                        throw new IllegalArgumentException("function is null");
106                }
107                
108                final String functionIdKey = function.getId();
109                final FunctionDefinition existing = getFunctionById(functionIdKey);
110                if (existing == null) {
111                        throw new IllegalStateException("the function does not exist: " + function);
112                }
113                final FunctionDefinition toUpdate;
114                if (!existing.getId().equals(function.getId())){
115                        final FunctionDefinition.Builder builder = FunctionDefinition.Builder.create(function);
116                        builder.setId(existing.getId());
117                        toUpdate = builder.build();
118                } else {
119                        toUpdate = function;
120                }
121
122                businessObjectService.save(FunctionBo.from(toUpdate));
123        }
124        
125    
126        /**
127         * This overridden method retrieves a function by the given function id.
128         * 
129         * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionById(java.lang.String)
130         */
131        @Override
132        public FunctionDefinition getFunctionById(String functionId) {
133                if (StringUtils.isBlank(functionId)){
134            throw new RiceIllegalArgumentException("functionId is null or blank");
135                }
136                FunctionBo functionBo = businessObjectService.findBySinglePrimaryKey(FunctionBo.class, functionId);
137                return FunctionBo.to(functionBo);
138        }
139        
140        /**
141         * 
142         * This overridden method retrieves a function by the given name and namespace.
143         * 
144         * @see org.kuali.rice.krms.impl.repository.FunctionBoService#getFunctionByNameAndNamespace(java.lang.String, java.lang.String)
145         */
146        public FunctionDefinition getFunctionByNameAndNamespace( String name, String namespace ){
147                if (StringUtils.isBlank(name)){
148                        throw new IllegalArgumentException("name is null or blank");
149                }
150                if (StringUtils.isBlank(namespace)){
151                        throw new IllegalArgumentException("namespace is null or blank");
152                }
153                                
154        final Map<String, Object> map = new HashMap<String, Object>();
155        map.put("name", name);
156        map.put("namespace", namespace);
157                FunctionBo functionBo = businessObjectService.findByPrimaryKey(FunctionBo.class, Collections.unmodifiableMap(map));
158                return FunctionBo.to(functionBo);
159        }
160
161    /**
162     * Gets all of the {@link FunctionDefinition}s within the given namespace
163     *
164     * @param namespace the namespace in which to get the functions
165     * @return the list of function definitions, or if none are found, an empty list
166     */
167    public List<FunctionDefinition> getFunctionsByNamespace(String namespace) {
168        if (StringUtils.isBlank(namespace)){
169            throw new IllegalArgumentException("namespace is null or blank");
170        }
171
172        final Map<String, Object> map = new HashMap<String, Object>();
173        map.put("namespace", namespace);
174        Collection<FunctionBo> functionBos = businessObjectService.findMatching(FunctionBo.class, map);
175
176        return convertFunctionBosToImmutables(functionBos);
177    }
178
179    /**
180     * Converts a Collection of FunctionBos to an Unmodifiable List of Agendas
181     *
182     * @param functionBos a mutable List of FunctionBos to made completely immutable.
183     * @return An unmodifiable List of FunctionDefinitions
184     */
185    private List<FunctionDefinition> convertFunctionBosToImmutables(final Collection<FunctionBo> functionBos) {
186        if (CollectionUtils.isEmpty(functionBos)) {
187            return Collections.emptyList();
188        }
189        return Collections.unmodifiableList(ModelObjectUtils.transform(functionBos, toFunctionDefinition));
190    }
191
192    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
193        this.businessObjectService = businessObjectService;
194    }
195}