/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed 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 net.ontopia.topicmaps.query.parser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.ontopia.topicmaps.query.core.InvalidQueryException;
import net.ontopia.topicmaps.query.impl.utils.QueryAnalyzer;
/**
* INTERNAL: Represents a parsed rule.
*/
public class ParsedRule {
private String name;
private List parameters;
private List clauses;
private Map typemap;
private TologOptions options;
public ParsedRule(String name) {
this.name = name;
}
public void init(TologOptions options) {
this.options = options;
this.parameters = new ArrayList();
this.clauses = new ArrayList();
}
public boolean initialized() {
return options != null;
}
public String getName() {
return name;
}
public List getClauses() {
return clauses;
}
public List getParameters() {
return parameters;
}
public void setClauseList(List clauses) {
this.clauses = clauses;
}
public void addParameter(Variable var) {
parameters.add(var);
}
public Map getVariableTypes() {
return typemap;
}
public Map getParameterTypes() {
return Collections.EMPTY_MAP;
}
public TologOptions getOptions() {
// will only work after close() has been called
return options;
}
/**
* Some checks can only be performed when we know that we have
* parsed the entire rule. Therefore close() is called once parsing
* of the rule has ended. It verifies that all parameters to the
* rule are actually used in the rule (no free variables), and runs
* type inferencing on the rule.
*/
public void close() throws InvalidQueryException {
// verify that all parameters are used
Set allVariables = new HashSet();
for (int ix = 0; ix < clauses.size(); ix++) {
AbstractClause clause = (AbstractClause) clauses.get(ix);
allVariables.addAll(clause.getAllVariables());
}
for (int ix = 0; ix < parameters.size(); ix++) {
Variable var = (Variable) parameters.get(ix);
if (!allVariables.contains(var))
throw new InvalidQueryException("Parameter " + var + " to rule " + name +
" is not bound by the rule.");
}
// run type inferencing
boolean strict = options.getBooleanValue("compiler.typecheck");
typemap = QueryAnalyzer.analyzeTypes(clauses, strict).getVariableTypes();
}
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj instanceof ParsedRule) {
ParsedRule other = (ParsedRule)obj;
return (name.equals(other.name) &&
parameters.equals(other.parameters) &&
clauses.equals(other.clauses));
}
return false;
}
}