001/**
002 * Copyright 2005-2014 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.CriteriaLookupService;
021import org.kuali.rice.core.api.criteria.QueryByCriteria;
022import org.kuali.rice.core.api.criteria.QueryResults;
023import org.kuali.rice.krad.data.DataObjectService;
024import org.kuali.rice.krad.data.PersistenceOption;
025import org.kuali.rice.krad.service.KRADServiceLocator;
026import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
027
028import java.util.ArrayList;
029import java.util.Collection;
030import java.util.Collections;
031import java.util.HashMap;
032import java.util.List;
033import java.util.Map;
034
035import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
036import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.findMatching;
037
038public final class KrmsAttributeDefinitionServiceImpl implements KrmsAttributeDefinitionService {
039    private CriteriaLookupService criteriaLookupService;
040
041    private DataObjectService dataObjectService;
042
043    /**
044     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#convertAttributeKeys(java.util.Map, String)
045     */
046    @Override
047    public Map<String,String> convertAttributeKeys(Map<String,String> attributesByName, String namespace) {
048        Map<String,String> attributesById = new HashMap<String,String>();
049
050        if(attributesByName != null) {
051            for(Map.Entry<String, String> attr : attributesByName.entrySet()) {
052                String newKey = getKrmsAttributeId(attr.getKey(), namespace);
053                if(StringUtils.isNotEmpty(newKey)) {
054                    attributesById.put(newKey, attr.getValue());
055                }
056            }
057        }
058
059        return attributesById;
060    }
061
062    /**
063     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#getKrmsAttributeId(String, String)
064     */
065    @Override
066    public String getKrmsAttributeId( String attributeName, String namespace) {
067        String returnId = null;
068
069        KrmsAttributeDefinitionBo bo = getKrmsAttributeBo(attributeName, namespace);
070        if (bo != null){
071            returnId = bo.getId();
072        }
073
074        return returnId;
075    }
076
077    /**
078     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#getKrmsAttributeBo(String, String)
079     */
080    @Override
081    public KrmsAttributeDefinitionBo getKrmsAttributeBo( String attributeName, String namespace) {
082        KrmsAttributeDefinitionBo result = null;
083        Map<String,Object> criteria = new HashMap<String,Object>( 3 );
084        criteria.put( "name", attributeName );
085        criteria.put( "namespace", namespace );
086        criteria.put( "active", Boolean.TRUE );
087        Collection<KrmsAttributeDefinitionBo> defs =
088                findMatching(getDataObjectService(), KrmsAttributeDefinitionBo.class, criteria );
089
090        if(CollectionUtils.isNotEmpty(defs)) {
091            if (defs.size() > 1){
092                throw new IllegalStateException("Multiple KrmsAttributeDefinitions found with same name and namespace");
093            }
094
095            result = defs.iterator().next();
096        }
097
098        return result;
099    }
100
101    /**
102     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#createAttributeDefinition(org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition)
103     */
104    @Override
105    public KrmsAttributeDefinition createAttributeDefinition(KrmsAttributeDefinition attributeDefinition) {
106        if (attributeDefinition == null){
107            throw new IllegalArgumentException("attributeDefinition is null");
108        }
109
110        final String nameKey = attributeDefinition.getName();
111        final String namespaceKey = attributeDefinition.getNamespace();
112        final KrmsAttributeDefinition existing = getAttributeDefinitionByNameAndNamespace(nameKey, namespaceKey);
113
114        if (existing != null && existing.getName().equals(nameKey) && existing.getNamespace().equals(namespaceKey)){
115            throw new IllegalStateException("the krms attribute definition to create already exists: " + attributeDefinition);
116        }
117
118        KrmsAttributeDefinitionBo bo = KrmsAttributeDefinitionBo.from(attributeDefinition);
119        bo = getDataObjectService().save(bo, PersistenceOption.FLUSH);
120
121        return KrmsAttributeDefinitionBo.to(bo);
122    }
123
124    /**
125     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#updateAttributeDefinition(org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition)
126     */
127    @Override
128    public void updateAttributeDefinition(KrmsAttributeDefinition attributeDefinition) {
129        if (attributeDefinition == null){
130            throw new IllegalArgumentException("attributeDefinition is null");
131        }
132
133        final String idKey = attributeDefinition.getId();
134        final KrmsAttributeDefinitionBo existing = getDataObjectService().find(KrmsAttributeDefinitionBo.class, idKey);
135
136        if (existing == null){
137            throw new IllegalStateException("the krms attribute definition does not exist: " + attributeDefinition);
138        }
139
140        final KrmsAttributeDefinition toUpdate;
141
142        if (!existing.getId().equals(attributeDefinition.getId())){
143            final KrmsAttributeDefinition.Builder builder = KrmsAttributeDefinition.Builder.create(attributeDefinition);
144            builder.setId(existing.getId());
145            toUpdate = builder.build();
146        } else {
147            toUpdate = attributeDefinition;
148        }
149
150        KrmsAttributeDefinitionBo bo = KrmsAttributeDefinitionBo.from(toUpdate);
151
152        getDataObjectService().save(bo, PersistenceOption.FLUSH);
153    }
154
155    /**
156     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#getAttributeDefinitionById(String)
157     */
158    @Override
159    public KrmsAttributeDefinition getAttributeDefinitionById(final String id) {
160        if (StringUtils.isBlank(id)) {
161            throw new IllegalArgumentException("id is blank");
162        }
163
164        KrmsAttributeDefinitionBo bo = getDataObjectService().find(KrmsAttributeDefinitionBo.class, id);
165
166        return KrmsAttributeDefinitionBo.to(bo);
167    }
168
169    /**
170     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#getAttributeDefinitionByNameAndNamespace(String, String)
171     */
172    @Override
173    public KrmsAttributeDefinition getAttributeDefinitionByNameAndNamespace(final String name, final String namespace) {
174        if (StringUtils.isBlank(name)) {
175            throw new IllegalArgumentException("name is blank");
176        }
177        if (StringUtils.isBlank(namespace)) {
178            throw new IllegalArgumentException("namespace is blank");
179        }
180
181        KrmsAttributeDefinitionBo bo = getKrmsAttributeBo(name, namespace);
182
183        if (bo == null) {
184            return null;
185        }
186
187        return KrmsAttributeDefinitionBo.to(bo);
188    }
189
190    /**
191     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#findAttributeDefinitionsByNamespace(String)
192     */
193    @Override
194    public List<KrmsAttributeDefinition> findAttributeDefinitionsByNamespace(final String namespace) {
195        final Map<String, Object> map = new HashMap<String, Object>();
196        map.put("namespace", namespace);
197        map.put("active", Boolean.TRUE);
198        Collection<KrmsAttributeDefinitionBo> krmsAttributeDefinitionBos = findMatching(getDataObjectService(),
199                KrmsAttributeDefinitionBo.class, Collections.unmodifiableMap(map));
200
201        return convertListOfBosToImmutables(krmsAttributeDefinitionBos);
202    }
203
204    @Override
205    /**
206     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#findAttributeDefinitionsByType(String)
207     */
208    public List<KrmsAttributeDefinition> findAttributeDefinitionsByType(final String typeId) {
209
210        List<KrmsAttributeDefinition> results = Collections.emptyList();
211
212        final Map<String, Object> map = new HashMap<String, Object>();
213        map.put("type.id", typeId);
214        map.put("active", Boolean.TRUE);
215        Collection<KrmsTypeAttributeBo> krmsTypeAttributeBos = findMatching(getDataObjectService(),
216                KrmsTypeAttributeBo.class, Collections.unmodifiableMap(map));
217
218        if (!CollectionUtils.isEmpty(krmsTypeAttributeBos)) {
219            String [] inList = new String[krmsTypeAttributeBos.size()];
220            int inListIdex = 0;
221            for (KrmsTypeAttributeBo krmsTypeAttributeBo : krmsTypeAttributeBos) {
222                inList[inListIdex] = krmsTypeAttributeBo.getAttributeDefinitionId();
223                ++inListIdex; // don't forget to increment our index
224            }
225
226            QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();
227            qBuilder.setPredicates(in("id", inList));
228            QueryResults<KrmsAttributeDefinitionBo> queryResults =
229                    getDataObjectService().findMatching(KrmsAttributeDefinitionBo.class, qBuilder.build());
230            results = convertListOfBosToImmutables(queryResults.getResults());
231        }
232
233        return results;
234    }
235
236
237    /**
238     * @see org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService#findAllAttributeDefinitions()
239     */
240    @Override
241    public List<KrmsAttributeDefinition> findAllAttributeDefinitions() {
242        final Map<String, Object> map = new HashMap<String, Object>();
243        map.put("active", Boolean.TRUE);
244
245        Collection<KrmsAttributeDefinitionBo> krmsAttributeDefinitionBos = findMatching(getDataObjectService(),
246                KrmsAttributeDefinitionBo.class, Collections.unmodifiableMap(map));
247
248        return convertListOfBosToImmutables(krmsAttributeDefinitionBos);
249    }
250
251    /**
252     * Converts a List<KrmsAttributeDefinitionBo> to an Unmodifiable List<KrmsAttributeDefinition>
253     *
254     * @param krmsAttributeDefinitionBos a mutable List<KrmsAttributeDefinitionBo> to made completely immutable.
255     * @return An unmodifiable List<KrmsAttributeDefinition>
256     */
257    public List<KrmsAttributeDefinition> convertListOfBosToImmutables(final Collection<KrmsAttributeDefinitionBo> krmsAttributeDefinitionBos) {
258        ArrayList<KrmsAttributeDefinition> krmsAttributeDefinitions = new ArrayList<KrmsAttributeDefinition>();
259
260        for (KrmsAttributeDefinitionBo bo : krmsAttributeDefinitionBos) {
261            KrmsAttributeDefinition krmsAttributeDefinition = KrmsAttributeDefinitionBo.to(bo);
262            krmsAttributeDefinitions.add(krmsAttributeDefinition);
263        }
264
265        return Collections.unmodifiableList(krmsAttributeDefinitions);
266    }
267
268    /**
269     * Sets the dataObjectService attribute value.
270     *
271     * @param dataObjectService The dataObjectService to set.
272     */
273    public void setDataObjectService(final DataObjectService dataObjectService) {
274        this.dataObjectService = dataObjectService;
275    }
276
277    /**
278     * This method returns a reference to the dataObjectService.
279     * If the dataObjectService is not set, get it from the KRADServiceLocator.
280     * @return dataObjectService
281     */
282    protected DataObjectService getDataObjectService() {
283        if ( dataObjectService == null ) {
284            dataObjectService = KRADServiceLocator.getDataObjectService();
285        }
286
287        return dataObjectService;
288    }
289
290}