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.provider.repository;
017
018import java.util.HashMap;
019import java.util.Map;
020
021import org.kuali.rice.krms.api.engine.ExecutionOptions;
022import org.kuali.rice.krms.api.engine.SelectionCriteria;
023import org.kuali.rice.krms.api.engine.Term;
024import org.kuali.rice.krms.api.repository.RuleRepositoryService;
025import org.kuali.rice.krms.api.repository.context.ContextDefinition;
026import org.kuali.rice.krms.api.repository.context.ContextSelectionCriteria;
027import org.kuali.rice.krms.framework.engine.Context;
028import org.kuali.rice.krms.framework.engine.ContextProvider;
029
030public class RuleRepositoryContextProvider implements ContextProvider {
031
032        // may want to move these out to a constants file somewhere so they are accessible to engine clients?
033        private static final String NAME_CONTEXT_QUALIFIER = "name";
034        private static final String NAMESPACE_CODE_CONTEXT_QUALIFIER = "namespaceCode";
035        
036        private RuleRepositoryService ruleRepositoryService;
037        private RepositoryToEngineTranslator repositoryToEngineTranslator;
038        
039        @Override
040        public Context loadContext(SelectionCriteria selectionCriteria, Map<Term, Object> facts, ExecutionOptions executionOptions) {
041                ContextSelectionCriteria contextSelectionCriteria = constructContextSelectionCriteria(selectionCriteria);
042                ContextDefinition contextDefinition = ruleRepositoryService.selectContext(contextSelectionCriteria);
043                
044                // TODO should have an execution option that throws an error here if a context does not exist?
045                
046                if (contextDefinition != null) {
047                        return loadContextFromDefinition(contextDefinition);
048                }
049                return null;
050        }
051        
052        protected Context loadContextFromDefinition(ContextDefinition contextDefinition) {
053                return repositoryToEngineTranslator.translateContextDefinition(contextDefinition);
054        }
055        
056        public void setRuleRepositoryService(RuleRepositoryService ruleRepositoryService) {
057                this.ruleRepositoryService = ruleRepositoryService;
058        }
059        
060        public void setRepositoryToEngineTranslator(RepositoryToEngineTranslator repositoryToEngineTranslator) {
061                this.repositoryToEngineTranslator = repositoryToEngineTranslator;
062        }
063        
064        protected ContextSelectionCriteria constructContextSelectionCriteria(SelectionCriteria selectionCriteria) {
065                Map<String, String> givenContextQualifiers = selectionCriteria.getContextQualifiers();
066                if (givenContextQualifiers == null || givenContextQualifiers.isEmpty()) {
067                        throw new IllegalArgumentException("Context qualifiers in the selection criteria were null or empty.  At least one context qualifier must be passed in selection criteria.");
068                }
069                
070                // extract the "standard" context qualifiers for the rule repository, name and namespaceCode
071                
072                String namespaceCode = null;
073                String name = null;
074                Map<String, String> contextQualifiers = new HashMap<String, String>();
075                for (String key : givenContextQualifiers.keySet()) {
076                        String value = givenContextQualifiers.get(key);
077                        if (key.equals(NAME_CONTEXT_QUALIFIER)) {
078                                name = value;
079                        } else if (key.equals(NAMESPACE_CODE_CONTEXT_QUALIFIER)) {
080                                namespaceCode = value;
081                        } else {
082                                contextQualifiers.put(key, value);
083                        }
084                }
085                
086                return ContextSelectionCriteria.newCriteria(namespaceCode, name, contextQualifiers);
087                
088        }
089
090}