org.jpmml.model.visitors.FieldResolver Maven / Gradle / Ivy
/*
* Copyright (c) 2015 Villu Ruusmann
*/
package org.jpmml.model.visitors;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.dmg.pmml.DataDictionary;
import org.dmg.pmml.DefineFunction;
import org.dmg.pmml.Field;
import org.dmg.pmml.LocalTransformations;
import org.dmg.pmml.Model;
import org.dmg.pmml.Output;
import org.dmg.pmml.PMML;
import org.dmg.pmml.PMMLObject;
import org.dmg.pmml.ResultField;
import org.dmg.pmml.TransformationDictionary;
import org.dmg.pmml.Visitable;
import org.dmg.pmml.VisitorAction;
import org.dmg.pmml.mining.Segment;
import org.dmg.pmml.mining.Segmentation;
import org.dmg.pmml.regression.Regression;
import org.dmg.pmml.tree.DecisionTree;
/**
*
* A Visitor that determines which fields are visible and accessible (aka "in scope") at the specified location of a class model object.
*
*
* @see Scope of Fields
*/
public class FieldResolver extends AbstractVisitor {
private Map>> scopes = new IdentityHashMap<>();
private Map>> customScopes = Collections.emptyMap();
@Override
public void applyTo(Visitable visitable){
this.scopes.clear();
this.customScopes = Collections.emptyMap();
super.applyTo(visitable);
}
@Override
public PMMLObject popParent(){
PMMLObject parent = super.popParent();
if(parent instanceof Field){
Field> field = (Field>)parent;
parent = getParent();
List> customScope = this.customScopes.get(parent);
if(customScope != null){
customScope.add(field);
}
} else
if(parent instanceof TransformationDictionary){
PMML pmml = (PMML)getParent();
declareGlobalFields(pmml, true);
this.customScopes = Collections.emptyMap();
} else
if(parent instanceof LocalTransformations){
Model model = (Model)getParent();
declareLocalFields(model, true);
this.customScopes = Collections.emptyMap();
} else
{
List> customScope = this.customScopes.get(parent);
if(customScope != null){
this.customScopes = Collections.emptyMap();
}
}
return parent;
}
@Override
public VisitorAction visit(Model model){
declareLocalFields(model, true);
return super.visit(model);
}
@Override
public VisitorAction visit(DecisionTree decisionTree){
throw new UnsupportedOperationException();
}
@Override
public VisitorAction visit(DefineFunction defineFunction){
declareFields(defineFunction, defineFunction.hasParameterFields() ? defineFunction.getParameterFields() : Collections.emptyList());
return super.visit(defineFunction);
}
@Override
public VisitorAction visit(LocalTransformations localTransformations){
Model model = (Model)getParent();
if(localTransformations.hasDerivedFields()){
declareLocalFields(model, false);
suppressFields(localTransformations);
}
return super.visit(localTransformations);
}
@Override
public VisitorAction visit(Output output){
if(output.hasOutputFields()){
declareFields(output, output.getOutputFields());
suppressFields(output);
}
return super.visit(output);
}
@Override
public VisitorAction visit(PMML pmml){
declareGlobalFields(pmml, true);
return super.visit(pmml);
}
@Override
public VisitorAction visit(Regression regression){
throw new UnsupportedOperationException();
}
@Override
public VisitorAction visit(ResultField resultField){
throw new UnsupportedOperationException();
}
@Override
public VisitorAction visit(TransformationDictionary transformationDictionary){
PMML pmml = (PMML)getParent();
if(transformationDictionary.hasDerivedFields()){
declareGlobalFields(pmml, false);
suppressFields(transformationDictionary);
}
return super.visit(transformationDictionary);
}
public Collection> getFields(){
Deque parents = getParents();
return getFields(parents);
}
public Collection> getFields(PMMLObject... virtualParents){
Deque parents = new ArrayDeque<>(getParents());
for(PMMLObject virtualParent : virtualParents){
parents.push(virtualParent);
}
return getFields(parents);
}
private Collection> getFields(Deque parents){
List> result = new ArrayList<>();
PMMLObject prevParent = null;
for(PMMLObject parent : parents){
{
List> scope = getScope(parent);
if(scope != null && scope.size() > 0){
result.addAll(scope);
}
}
if(parent instanceof DefineFunction){
break;
} // End if
if((parent instanceof Segmentation) && ((prevParent == null) || (prevParent instanceof Segment))){
List