/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tajo.rule;
import java.util.*;
import java.util.Map.Entry;
import org.apache.tajo.rule.EvaluationResult.EvaluationResultCode;
import org.apache.tajo.rule.SelfDiagnosisRuleEngine.RuleWrapper;
public class SelfDiagnosisRuleSession {
private final SelfDiagnosisRuleEngine ruleEngine;
private final Set<String> categoryPredicate;
private final Set<String> rulePredicate;
protected SelfDiagnosisRuleSession(SelfDiagnosisRuleEngine engine) {
ruleEngine = engine;
categoryPredicate = new HashSet<>();
rulePredicate = new HashSet<>();
}
public SelfDiagnosisRuleSession withCategoryNames(String...categories) {
categoryPredicate.addAll(Arrays.asList(categories));
return this;
}
public SelfDiagnosisRuleSession withRuleNames(String...rules) {
rulePredicate.addAll(Arrays.asList(rules));
return this;
}
public SelfDiagnosisRuleSession reset() {
categoryPredicate.clear();
rulePredicate.clear();
return this;
}
public void fireRules(EvaluationContext context) throws EvaluationFailedException {
List<RuleWrapper> candidateRules = getCandidateRules();
for (RuleWrapper wrapper: candidateRules) {
EvaluationResult result = wrapper.getRule().evaluate(context);
if (result.getReturnCode() == EvaluationResultCode.ERROR) {
throw new EvaluationFailedException(result.getMessage(), result.getThrowable());
}
}
}
protected List<RuleWrapper> getCandidateRules() {
Map<String, Map<String, RuleWrapper>> wrapperMap = null;
List<RuleWrapper> candidateRules = new ArrayList<>();
wrapperMap = ruleEngine.getRules();
Class<?> callerClazz = getCallerClassName();
for (Entry<String, Map<String, RuleWrapper>> entry: wrapperMap.entrySet()) {
String categoryName = entry.getKey();
if (categoryPredicate.size() > 0 && !categoryPredicate.contains(categoryName)) {
continue;
}
Map<String, RuleWrapper> ruleMap = entry.getValue();
for (Entry<String, RuleWrapper> wrapperEntry: ruleMap.entrySet()) {
if (rulePredicate.size() > 0 && !rulePredicate.contains(wrapperEntry.getKey())) {
continue;
}
RuleWrapper ruleWrapper = wrapperEntry.getValue();
if (callerClazz != null && ruleWrapper.getAcceptedCallers().length > 0
&& !hasCallerClazz(callerClazz, ruleWrapper.getAcceptedCallers())) {
continue;
}
candidateRules.add(ruleWrapper);
}
}
Collections.sort(candidateRules);
return candidateRules;
}
protected boolean hasCallerClazz(Class<?> callerClazz, Class<?>[] acceptedCallers) {
boolean result = false;
String callerClazzName = callerClazz.getName();
for (Class<?> acceptedCaller: acceptedCallers) {
if (callerClazzName.equals(acceptedCaller.getName())) {
result = true;
break;
}
}
return result;
}
protected Class<?> getCallerClassName() {
return new RuleSessionSecurityManager().getCallerClassName();
}
static class RuleSessionSecurityManager extends SecurityManager {
public Class<?> getCallerClassName() {
Class<?>[] clazzArray = getClassContext();
int clazzIdx = 2;
for (; clazzIdx < clazzArray.length; clazzIdx++) {
if (!clazzArray[clazzIdx].getName().equals(SelfDiagnosisRuleSession.class.getName())) {
break;
}
}
return clazzIdx < clazzArray.length?clazzArray[clazzIdx]:null;
}
}
}