001/**
002 * Copyright 2005-2015 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.lang.StringUtils;
019import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
020import org.kuali.rice.core.api.exception.RiceIllegalStateException;
021import org.kuali.rice.krad.data.DataObjectService;
022import org.kuali.rice.krad.data.PersistenceOption;
023import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
024import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplaterContract;
025import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
026import org.kuali.rice.krms.impl.repository.language.SimpleNaturalLanguageTemplater;
027import org.kuali.rice.krms.impl.util.KrmsImplConstants;
028
029import java.util.Collection;
030import java.util.Collections;
031import java.util.HashMap;
032import java.util.HashSet;
033import java.util.LinkedList;
034import java.util.List;
035import java.util.Map;
036import java.util.Set;
037
038import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.deleteMatching;
039import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.findMatching;
040
041/**
042 * Implementation of the @{link NaturalLanguageTemplateBoService} interface for accessing  {@link
043 * NaturalLanguageTemplateBo} related business objects.
044 *
045 * @author Kuali Rice Team (rice.collab@kuali.org)
046 */
047public class NaturalLanguageTemplateBoServiceImpl implements NaturalLanguageTemplateBoService {
048
049    private DataObjectService dataObjectService;
050    private KrmsAttributeDefinitionService attributeDefinitionService;
051    private NaturalLanguageTemplaterContract naturalLanguageTemplater = new SimpleNaturalLanguageTemplater();
052
053    /**
054     * Sets the value of DataObjectService to the given value.
055     *
056     * @param dataObjectService the DataObjectService value to set.
057     */
058    public void setDataObjectService(DataObjectService dataObjectService) {
059        this.dataObjectService = dataObjectService;
060    }
061
062    public void setAttributeDefinitionService(KrmsAttributeDefinitionService attributeDefinitionService) {
063        this.attributeDefinitionService = attributeDefinitionService;
064    }
065
066    public KrmsAttributeDefinitionService getAttributeDefinitionService() {
067        if (attributeDefinitionService == null) {
068            attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
069        }
070
071        return attributeDefinitionService;
072    }
073
074    public NaturalLanguageTemplaterContract getNaturalLanguageTemplater() {
075        return naturalLanguageTemplater;
076    }
077
078    public void setNaturalLanguageTemplater(NaturalLanguageTemplaterContract naturalLanguageTemplater) {
079        this.naturalLanguageTemplater = naturalLanguageTemplater;
080    }
081
082    @Override
083    public NaturalLanguageTemplate createNaturalLanguageTemplate(NaturalLanguageTemplate naturalLanguageTemplate) {
084        incomingParamCheck(naturalLanguageTemplate, "naturalLanguageTemplate");
085        NaturalLanguageTemplateBo bo;
086        NaturalLanguageTemplate naturalLanguageTemplateUpdated;
087
088        if (StringUtils.isNotBlank(naturalLanguageTemplate.getId())) {
089            final String naturalLanguageTemplateIdKey = naturalLanguageTemplate.getId();
090            final NaturalLanguageTemplate existing = getNaturalLanguageTemplate(naturalLanguageTemplateIdKey);
091
092            if (existing != null) {
093                throw new IllegalStateException(
094                        "the NaturalLanguageTemplate to create already exists: " + naturalLanguageTemplate);
095            }
096
097            bo = dataObjectService.save(from(naturalLanguageTemplate), PersistenceOption.FLUSH);
098
099            naturalLanguageTemplateUpdated = NaturalLanguageTemplateBo.to(bo);
100        } else {
101            Map<String, String> attributes = new HashMap<String, String>(naturalLanguageTemplate.getAttributes());
102
103            bo = dataObjectService.save(from(naturalLanguageTemplate), PersistenceOption.FLUSH);
104
105            NaturalLanguageTemplate.Builder naturalLanguageTemplateBuilder = NaturalLanguageTemplate.Builder.create(
106                    bo.getLanguageCode(), bo.getNaturalLanguageUsageId(), bo.getTemplate(), bo.getTypeId());
107            naturalLanguageTemplateBuilder.setActive(bo.isActive());
108            naturalLanguageTemplateBuilder.setId(bo.getId());
109            naturalLanguageTemplateBuilder.setVersionNumber(bo.getVersionNumber());
110            naturalLanguageTemplateBuilder.setAttributes(attributes);
111            naturalLanguageTemplateUpdated = naturalLanguageTemplateBuilder.build();
112            updateNaturalLanguageTemplate(naturalLanguageTemplateUpdated);
113        }
114
115        return naturalLanguageTemplateUpdated;
116    }
117
118    @Override
119    public NaturalLanguageTemplate getNaturalLanguageTemplate(String naturalLanguageTemplateId) {
120        incomingParamCheck(naturalLanguageTemplateId, "naturalLanguageTemplateId");
121        NaturalLanguageTemplateBo bo = dataObjectService.find(NaturalLanguageTemplateBo.class,
122                naturalLanguageTemplateId);
123
124        return NaturalLanguageTemplateBo.to(bo);
125    }
126
127    @Override
128    public NaturalLanguageTemplate updateNaturalLanguageTemplate(NaturalLanguageTemplate naturalLanguageTemplate) {
129        incomingParamCheck(naturalLanguageTemplate, "naturalLanguageTemplate");
130        final NaturalLanguageTemplate existing = getNaturalLanguageTemplate(naturalLanguageTemplate.getId());
131
132        if (existing == null) {
133            throw new IllegalStateException(
134                    "the NaturalLanguageTemplate to update does not exists: " + naturalLanguageTemplate);
135        }
136
137        final NaturalLanguageTemplate toUpdate;
138
139        if (!existing.getId().equals(naturalLanguageTemplate.getId())) {
140            // if passed in id does not match existing id, correct it
141            final NaturalLanguageTemplate.Builder builder = NaturalLanguageTemplate.Builder.create(
142                    naturalLanguageTemplate);
143            builder.setId(existing.getId());
144            toUpdate = builder.build();
145        } else {
146            toUpdate = naturalLanguageTemplate;
147        }
148
149        // copy all updateable fields to bo
150        NaturalLanguageTemplateBo boToUpdate = from(toUpdate);
151
152        // delete any old, existing attributes
153        Map<String, String> fields = new HashMap<String, String>(1);
154        fields.put(KrmsImplConstants.PropertyNames.NaturalLanguageTemplate.NATURAL_LANGUAGE_TEMPLATE_ID,
155                toUpdate.getId()); // TODO verify PropertyNames.NaturalLanguageTemplate.NATURAL_LANGUAGE_TEMPLATE_ID
156        deleteMatching(dataObjectService, NaturalLanguageTemplateAttributeBo.class, fields);
157
158        // update the rule and create new attributes
159        NaturalLanguageTemplateBo updatedData = dataObjectService.save(boToUpdate, PersistenceOption.FLUSH);
160
161        return to(updatedData);
162    }
163
164    @Override
165    public void deleteNaturalLanguageTemplate(String naturalLanguageTemplateId) {
166        incomingParamCheck(naturalLanguageTemplateId, "naturalLanguageTemplateId");
167        final NaturalLanguageTemplate existing = getNaturalLanguageTemplate(naturalLanguageTemplateId);
168
169        if (existing == null) {
170            throw new IllegalStateException(
171                    "the NaturalLanguageTemplate to delete does not exists: " + naturalLanguageTemplateId);
172        }
173
174        // delete any existing attributes
175        Map<String, String> fields = new HashMap<String, String>(1);
176        fields.put(KrmsImplConstants.PropertyNames.NaturalLanguageTemplate.NATURAL_LANGUAGE_TEMPLATE_ID,
177                existing.getId());
178        deleteMatching(dataObjectService, NaturalLanguageTemplateAttributeBo.class, fields);
179
180        dataObjectService.delete(from(existing));
181    }
182
183    @Override
184    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByAttributes(Map attributes) {
185        if (attributes == null) {
186            throw new IllegalArgumentException("attributes is null");
187        }
188
189        final Map<String, Object> map = new HashMap<String, Object>();
190        map.put("attributes", attributes);
191        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
192
193        return convertBosToImmutables(bos);
194    }
195
196    @Override
197    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByLanguageCode(String languageCode) {
198        if (org.apache.commons.lang.StringUtils.isBlank(languageCode)) {
199            throw new IllegalArgumentException("languageCode is null or blank");
200        }
201
202        final Map<String, Object> map = new HashMap<String, Object>();
203        map.put("languageCode", languageCode);
204        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
205
206        return convertBosToImmutables(bos);
207    }
208
209    @Override
210    public NaturalLanguageTemplate findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(String languageCode,
211            String typeId, String naturalLanguageUsageId) {
212        if (org.apache.commons.lang.StringUtils.isBlank(languageCode)) {
213            throw new IllegalArgumentException("languageCode is null or blank");
214        }
215
216        final Map<String, Object> map = new HashMap<String, Object>();
217        map.put("languageCode", languageCode);
218        map.put("naturalLanguageUsageId", naturalLanguageUsageId);
219        map.put("typeId", typeId);
220        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
221
222        if (bos.isEmpty()) {
223            return null;
224        }
225
226        if (bos.size() > 1) {
227            throw new RiceIllegalArgumentException(
228                    languageCode + typeId + naturalLanguageUsageId + " is supposed to be unique");
229        }
230
231        return convertBosToImmutables(bos).get(0);
232    }
233
234    @Override
235    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByNaturalLanguageUsage(
236            String naturalLanguageUsageId) {
237        if (org.apache.commons.lang.StringUtils.isBlank(naturalLanguageUsageId)) {
238            throw new IllegalArgumentException("naturalLanguageUsageId is null or blank");
239        }
240
241        final Map<String, Object> map = new HashMap<String, Object>();
242        map.put("naturalLanguageUsageId", naturalLanguageUsageId);
243        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
244
245        return convertBosToImmutables(bos);
246    }
247
248    @Override
249    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByType(String typeId) {
250        if (org.apache.commons.lang.StringUtils.isBlank(typeId)) {
251            throw new IllegalArgumentException("typeId is null or blank");
252        }
253
254        final Map<String, Object> map = new HashMap<String, Object>();
255        map.put("typeId", typeId);
256        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
257
258        return convertBosToImmutables(bos);
259    }
260
261    @Override
262    public List<NaturalLanguageTemplate> findNaturalLanguageTemplatesByTemplate(String template) {
263        if (org.apache.commons.lang.StringUtils.isBlank(template)) {
264            throw new IllegalArgumentException("template is null or blank");
265        }
266
267        final Map<String, Object> map = new HashMap<String, Object>();
268        map.put("template", template);
269        List<NaturalLanguageTemplateBo> bos = findMatching(dataObjectService, NaturalLanguageTemplateBo.class, map);
270
271        return convertBosToImmutables(bos);
272    }
273
274    public List<NaturalLanguageTemplate> convertBosToImmutables(
275            final Collection<NaturalLanguageTemplateBo> naturalLanguageTemplateBos) {
276        List<NaturalLanguageTemplate> immutables = new LinkedList<NaturalLanguageTemplate>();
277
278        if (naturalLanguageTemplateBos != null) {
279            NaturalLanguageTemplate immutable = null;
280            for (NaturalLanguageTemplateBo bo : naturalLanguageTemplateBos) {
281                immutable = to(bo);
282                immutables.add(immutable);
283            }
284        }
285
286        return Collections.unmodifiableList(immutables);
287    }
288
289    @Override
290    public NaturalLanguageTemplate to(NaturalLanguageTemplateBo naturalLanguageTemplateBo) {
291        return NaturalLanguageTemplateBo.to(naturalLanguageTemplateBo);
292    }
293
294    public NaturalLanguageTemplateBo from(NaturalLanguageTemplate naturalLanguageTemplate) {
295        return NaturalLanguageTemplateBo.from(naturalLanguageTemplate);
296    }
297
298    private Collection<NaturalLanguageTemplateAttributeBo> buildAttributes(NaturalLanguageTemplate im,
299            Collection<NaturalLanguageTemplateAttributeBo> attributes) {
300        // build a map from attribute name to definition
301        Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
302
303        List<KrmsAttributeDefinition> attributeDefinitions =
304                getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId());
305
306        for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
307            attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
308        }
309
310        // for each entry, build a NaturalLanguageTemplateAttributeBo and add it
311        if (im.getAttributes() != null) {
312            for (Map.Entry<String, String> entry : im.getAttributes().entrySet()) {
313                KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey());
314
315                if (attrDef != null) {
316                    NaturalLanguageTemplateAttributeBo attributeBo = new NaturalLanguageTemplateAttributeBo();
317                    attributeBo.setNaturalLanguageTemplateId(im.getId());
318                    attributeBo.setAttributeDefinitionId(attrDef.getId());
319                    attributeBo.setValue(entry.getValue());
320                    attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef));
321                    attributes.add(attributeBo);
322                } else {
323                    throw new RiceIllegalStateException("there is no attribute definition with the name '" +
324                            entry.getKey() + "' that is valid for the naturalLanguageTemplate type with id = '" + im
325                            .getTypeId() + "'");
326                }
327            }
328        }
329
330        return attributes;
331    }
332
333    private Set<NaturalLanguageTemplateAttributeBo> buildAttributeBoSet(NaturalLanguageTemplate im) {
334        Set<NaturalLanguageTemplateAttributeBo> attributes = new HashSet<NaturalLanguageTemplateAttributeBo>();
335
336        return (Set) buildAttributes(im, attributes);
337    }
338
339    private List<NaturalLanguageTemplateAttributeBo> buildAttributeBoList(NaturalLanguageTemplate im) {
340        List<NaturalLanguageTemplateAttributeBo> attributes = new LinkedList<NaturalLanguageTemplateAttributeBo>();
341
342        return (List) buildAttributes(im, attributes);
343    }
344
345    private void incomingParamCheck(Object object, String name) {
346        if (object == null) {
347            throw new IllegalArgumentException(name + " was null");
348        } else if (object instanceof String && StringUtils.isBlank((String) object)) {
349            throw new IllegalArgumentException(name + " was blank");
350        }
351    }
352}