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.type;
017
018import javax.xml.namespace.QName;
019
020import org.apache.commons.lang.StringUtils;
021import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
022import org.kuali.rice.krms.api.engine.EngineResourceUnavailableException;
023import org.kuali.rice.krms.api.repository.RepositoryDataException;
024import org.kuali.rice.krms.api.repository.action.ActionDefinition;
025import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
026import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
027import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
028import org.kuali.rice.krms.api.repository.proposition.PropositionType;
029import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
030import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
031import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
032import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
033import org.kuali.rice.krms.framework.type.ActionTypeService;
034import org.kuali.rice.krms.framework.type.AgendaTypeService;
035import org.kuali.rice.krms.framework.type.FunctionTypeService;
036import org.kuali.rice.krms.framework.type.PropositionTypeService;
037import org.kuali.rice.krms.framework.type.RuleTypeService;
038import org.kuali.rice.krms.framework.type.TermResolverTypeService;
039
040/**
041 * An implementation of {@link KrmsTypeResolver} which knows how to load the
042 * various type services in KRMS.
043 * 
044 * @author Kuali Rice Team (rice.collab@kuali.org)
045 *
046 */
047public class KrmsTypeResolverImpl implements KrmsTypeResolver {
048
049        private KrmsTypeRepositoryService typeRepositoryService;
050        private PropositionTypeService defaultCompoundPropositionTypeService;
051        private PropositionTypeService defaultSimplePropositionTypeService;
052        
053        @Override
054        public PropositionTypeService getPropositionTypeService(PropositionDefinition propositionDefinition) {
055                if (propositionDefinition == null) {
056                        throw new IllegalArgumentException("propositionDefinition was null");
057                }
058                if (propositionDefinition.getTypeId() == null) {
059                        PropositionType propositionType = PropositionType.fromCode(propositionDefinition.getPropositionTypeCode());
060                        if (PropositionType.COMPOUND == propositionType) {
061                                return defaultCompoundPropositionTypeService;
062                        } else if (PropositionType.SIMPLE == propositionType) {
063                                return defaultSimplePropositionTypeService;
064                        }
065                        throw new RepositoryDataException("Proposition does not have a typeId defined and does not define a valid proposition type code.  Proposition id is: " + propositionDefinition.getId());
066                }
067                KrmsTypeDefinition typeDefinition = getTypeDefinition(propositionDefinition.getTypeId());
068                return resolveTypeService(typeDefinition, PropositionTypeService.class);
069        }
070
071        @Override
072        public ActionTypeService getActionTypeService(ActionDefinition actionDefinition) {
073                if (actionDefinition == null) {
074                        throw new IllegalArgumentException("actionDefinition was null");
075                }
076                KrmsTypeDefinition typeDefinition = getTypeDefinition(actionDefinition.getTypeId());
077                return resolveTypeService(typeDefinition, ActionTypeService.class);
078        }
079
080    @Override
081    public AgendaTypeService getAgendaTypeService(AgendaDefinition agendaDefinition) {
082        if (agendaDefinition == null) {
083            throw new IllegalArgumentException("agendaDefinition was null");
084        }
085        KrmsTypeDefinition typeDefinition = getTypeDefinition(agendaDefinition.getTypeId());
086        return resolveTypeService(typeDefinition, AgendaTypeService.class);
087    }
088
089    @Override
090        public RuleTypeService getRuleTypeService(RuleDefinition ruleDefinition) {
091        if (ruleDefinition == null) {
092            throw new IllegalArgumentException("ruleDefinition was null");
093        }
094        KrmsTypeDefinition typeDefinition = getTypeDefinition(ruleDefinition.getTypeId());
095
096        if (typeDefinition == null) { return RuleTypeServiceBase.defaultRuleTypeService; }
097
098        return resolveTypeService(typeDefinition, RuleTypeService.class);
099    }
100
101        @Override
102        public TermResolverTypeService getTermResolverTypeService(TermResolverDefinition termResolverDefinition) {
103                if (termResolverDefinition == null) {
104                        throw new IllegalArgumentException("termResolverDefinition was null");
105                }
106                KrmsTypeDefinition typeDefinition = getTypeDefinition(termResolverDefinition.getTypeId());
107                return resolveTypeService(typeDefinition, TermResolverTypeService.class);
108        }
109        
110        @Override
111        public FunctionTypeService getFunctionTypeService(FunctionDefinition functionDefinition) {
112                if (functionDefinition == null) {
113                        throw new IllegalArgumentException("functionDefinition was null");
114                }
115                KrmsTypeDefinition typeDefinition = getTypeDefinition(functionDefinition.getTypeId());
116                return resolveTypeService(typeDefinition, FunctionTypeService.class);
117        }
118        
119        protected KrmsTypeDefinition getTypeDefinition(String typeId) {
120                if (StringUtils.isBlank(typeId)) {
121                        return null;
122                }
123                KrmsTypeDefinition typeDefinition = typeRepositoryService.getTypeById(typeId);
124                if (typeDefinition == null) {
125                        throw new RepositoryDataException("Failed to locate a type definition for typeId: " + typeId);
126                }
127                return typeDefinition;
128        }
129        
130        protected <T> T resolveTypeService(KrmsTypeDefinition typeDefinition, Class<T> typeServiceClass) {
131                QName serviceName = QName.valueOf(typeDefinition.getServiceName());
132                Object service = GlobalResourceLoader.getService(serviceName);
133                if (service == null) {
134                        throw new EngineResourceUnavailableException("Failed to locate the " + typeServiceClass.getSimpleName() + 
135                                        " with name: " + serviceName);
136                }
137                if (!typeServiceClass.isAssignableFrom(service.getClass())) {
138                        throw new EngineResourceUnavailableException("The service with name '" + serviceName + "' defined on typeId '" + typeDefinition.getId() + 
139                                        "' was not of type " + typeServiceClass.getSimpleName() + ": " + service);
140                }
141                return typeServiceClass.cast(service);
142        }
143        
144        public void setTypeRepositoryService(KrmsTypeRepositoryService typeRepositoryService) {
145                this.typeRepositoryService = typeRepositoryService;
146        }
147
148        public void setDefaultCompoundPropositionTypeService(PropositionTypeService defaultCompoundPropositionTypeService) {
149                this.defaultCompoundPropositionTypeService = defaultCompoundPropositionTypeService;
150        }
151
152        public void setDefaultSimplePropositionTypeService(PropositionTypeService defaultSimplePropositionTypeService) {
153                this.defaultSimplePropositionTypeService = defaultSimplePropositionTypeService;
154        }
155        
156}