/*
* Copyright (c) MuleSoft, Inc.
*
* 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 org.raml.parser.rule;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.raml.parser.resolver.TupleHandler;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.Tag;
public class DefaultTupleRule<K extends Node, V extends Node> implements TupleRule<K, Node>
{
protected Map<String, TupleRule<?, ?>> rules;
private TupleRule<?, ?> parent;
private TupleHandler tupleHandler;
private boolean required;
private K key;
private String name;
private NodeRuleFactory nodeRuleFactory;
public DefaultTupleRule(String name, TupleHandler handler, NodeRuleFactory nodeRuleFactory)
{
this(name, handler);
this.setNodeRuleFactory(nodeRuleFactory);
}
public DefaultTupleRule(String name, TupleHandler handler)
{
this.name = name;
this.rules = new HashMap<String, TupleRule<?, ?>>();
this.tupleHandler = handler;
}
public boolean isRequired()
{
return required;
}
public void setRequired(boolean required)
{
this.required = required;
}
@Override
public void setNodeRuleFactory(NodeRuleFactory nodeRuleFactory)
{
this.nodeRuleFactory = nodeRuleFactory;
}
@Override
public void setNestedRules(Map<String, TupleRule<?, ?>> rules)
{
this.rules = rules;
}
@Override
public void setHandler(TupleHandler tupleHandler)
{
this.tupleHandler = tupleHandler;
}
@Override
public TupleHandler getHandler()
{
return tupleHandler;
}
@Override
public List<ValidationResult> validateKey(K key)
{
this.key = key;
return new ArrayList<ValidationResult>();
}
@Override
public final List<ValidationResult> validateValue(Node value)
{
ArrayList<ValidationResult> validationResults = new ArrayList<ValidationResult>();
if (!Tag.NULL.equals(value.getTag()) && !isValidValueNodeType(value.getClass()))
{
validationResults.add(ValidationResult.createErrorResult("Invalid value type", value));
}
else
{
validationResults.addAll(doValidateValue((V) value));
}
return validationResults;
}
public List<ValidationResult> doValidateValue(V value)
{
return new ArrayList<ValidationResult>();
}
protected boolean isValidValueNodeType(Class valueNodeClass)
{
for (Class<?> clazz : getValueType())
{
if (clazz.isAssignableFrom(valueNodeClass))
{
return true;
}
}
return false;
}
public Class<?>[] getValueType()
{
return new Class[] {Node.class};
}
@Override
public List<ValidationResult> onRuleEnd()
{
List<ValidationResult> result = new ArrayList<ValidationResult>();
if (isRequired() && !wasAlreadyDefined())
{
result.add(ValidationResult.createErrorResult(ValidationMessage.getMissingRuleMessage(name)));
}
for (TupleRule<?, ?> rule : rules.values())
{
List<ValidationResult> onRuleEnd = rule.onRuleEnd();
result.addAll(onRuleEnd);
}
return result;
}
private boolean wasAlreadyDefined()
{
return key != null;
}
@Override
public K getKey()
{
return key;
}
public void addRulesFor(Class<?> pojoClass)
{
nodeRuleFactory.addRulesTo(pojoClass, this);
}
public NodeRuleFactory getNodeRuleFactory()
{
return nodeRuleFactory;
}
@Override
public TupleRule<?, ?> getRuleForTuple(NodeTuple nodeTuple)
{
for (TupleRule<?, ?> rule : rules.values())
{
if (rule.getHandler().handles(nodeTuple))
{
return rule;
}
}
return new UnknownTupleRule<Node, Node>(nodeTuple.getKeyNode().toString());
}
@Override
public void setParentTupleRule(TupleRule<?, ?> parent)
{
this.parent = parent;
}
@Override
public String getName()
{
return name;
}
@Override
public TupleRule<?, ?> getRuleByFieldName(String fieldName)
{
return rules.get(fieldName);
}
@Override
public TupleRule<?, ?> getParentTupleRule()
{
return parent;
}
@Override
public TupleRule<?, ?> getRootTupleRule()
{
TupleRule<?, ?> parentTupleRule = getParentTupleRule();
if (parentTupleRule == null)
{
return null;
}
while (parentTupleRule.getParentTupleRule() != null)
{
parentTupleRule = parentTupleRule.getParentTupleRule();
}
return parentTupleRule;
}
}