/**
* Copyright (C) 2009 STMicroelectronics
*
* This file is part of "Mind Compiler" is free software: you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: mind@ow2.org
*
* Authors: Matthieu Leclercq
* Contributors:
*/
package org.ow2.mind.adl;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.ow2.mind.adl.ast.ASTHelper.RESOLVED_DEFINITION_DECORATION_NAME;
import static org.ow2.mind.adl.ast.ASTHelper.getResolvedComponentDefinition;
import static org.ow2.mind.adl.parameter.ast.ParameterASTHelper.getInferredParameterType;
import static org.ow2.mind.value.ast.ValueASTHelper.getValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.fractal.adl.ADLException;
import org.objectweb.fractal.adl.Definition;
import org.objectweb.fractal.adl.Node;
import org.objectweb.fractal.adl.interfaces.Interface;
import org.objectweb.fractal.adl.interfaces.InterfaceContainer;
import org.objectweb.fractal.adl.types.TypeInterface;
import org.objectweb.fractal.adl.types.TypeInterfaceUtil;
import org.ow2.mind.adl.ast.ASTHelper;
import org.ow2.mind.adl.ast.ASTHelper.DefinitionDecoration;
import org.ow2.mind.adl.ast.Attribute;
import org.ow2.mind.adl.ast.AttributeContainer;
import org.ow2.mind.adl.ast.Component;
import org.ow2.mind.adl.ast.ComponentContainer;
import org.ow2.mind.adl.ast.DefinitionReference;
import org.ow2.mind.adl.ast.MindDefinition;
import org.ow2.mind.adl.generic.ast.FormalTypeParameter;
import org.ow2.mind.adl.generic.ast.FormalTypeParameterContainer;
import org.ow2.mind.adl.generic.ast.FormalTypeParameterReference;
import org.ow2.mind.adl.parameter.ast.Argument;
import org.ow2.mind.adl.parameter.ast.ArgumentContainer;
import org.ow2.mind.adl.parameter.ast.FormalParameter;
import org.ow2.mind.adl.parameter.ast.FormalParameterContainer;
import org.ow2.mind.adl.parameter.ast.ParameterASTHelper.ParameterType;
import org.ow2.mind.value.ast.CompoundValue;
import org.ow2.mind.value.ast.CompoundValueField;
import org.ow2.mind.value.ast.NumberLiteral;
import org.ow2.mind.value.ast.Reference;
import org.ow2.mind.value.ast.StringLiteral;
import org.ow2.mind.value.ast.Value;
public class ASTChecker {
protected final Map<Node, Object> checkers = new IdentityHashMap<Node, Object>();
// ---------------------------------------------------------------------------
// Definition checking
// ---------------------------------------------------------------------------
protected void checkDefinition(final Definition definition) {
assertNotNull("Definition is null", definition);
assertNotNull("Definition name is null", definition.getName());
if (definition instanceof MindDefinition
&& ((MindDefinition) definition).getExtends() != null) {
// definition contains 'extends' sub nodes
final DefinitionReference[] extendedDefs = ((MindDefinition) definition)
.getExtends().getDefinitionReferences();
for (final DefinitionReference extendedDef : extendedDefs) {
checkDefinitionReference(extendedDef);
}
}
if (definition instanceof InterfaceContainer)
checkInterfaceContainer((InterfaceContainer) definition);
if (definition instanceof ComponentContainer)
checkComponentContainer((ComponentContainer) definition);
if (definition instanceof FormalTypeParameterContainer)
checkFormalTypeParameterContainer((FormalTypeParameterContainer) definition);
}
public DefinitionChecker assertDefinition(final Definition def) {
DefinitionChecker checker = (DefinitionChecker) checkers.get(def);
if (checker == null) {
checker = createDefinitionChecker(def);
checkers.put(def, checker);
}
return checker;
}
protected DefinitionChecker createDefinitionChecker(final Definition def) {
return new DefinitionChecker(def);
}
public class DefinitionChecker {
public final Definition def;
public DefinitionChecker(final Definition def) {
this.def = def;
checkDefinition(def);
}
public DefinitionChecker that() {
return this;
}
public InterfaceChecker containsInterface(final String name) {
if (!(def instanceof InterfaceContainer))
fail("definition do not implements InterfaceContainer");
final InterfaceContainer container = (InterfaceContainer) def;
for (final Interface itf : container.getInterfaces()) {
if (name.equals(itf.getName())) return assertInterface(itf, container);
}
fail("definition " + def.getName() + " does not contains a \"" + name
+ "\" interface.");
// unreachable
return null;
}
public InterfaceCheckerIterator containsInterfaces(final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<InterfaceChecker> list = new ArrayList<InterfaceChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsInterface(name));
}
assertEquals("Definition contains more interfaces than expected.",
names.length, ((InterfaceContainer) def).getInterfaces().length);
return new InterfaceCheckerIterator(list);
}
public ComponentChecker containsComponent(final String name) {
if (!(def instanceof ComponentContainer))
fail("definition do not implements ComponentContainer");
final ComponentContainer container = (ComponentContainer) def;
for (final Component subComp : container.getComponents()) {
if (name.equals(subComp.getName()))
return assertComponent(subComp, container);
}
fail("definition " + def.getName() + " does not contains a \"" + name
+ "\" sub component.");
// unreachable
return null;
}
public ComponentCheckerIterator containsComponents(final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<ComponentChecker> list = new ArrayList<ComponentChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsComponent(name));
}
assertEquals("Definition contains more sub-components than expected.",
names.length, ((ComponentContainer) def).getComponents().length);
return new ComponentCheckerIterator(list);
}
public FormalTypeParameterChecker containsFormalTypeParameter(
final String name) {
if (!(def instanceof FormalTypeParameterContainer))
fail("definition do not implements FormalTypeParameterContainer");
final FormalTypeParameterContainer container = (FormalTypeParameterContainer) def;
for (final FormalTypeParameter formalTypeParameter : container
.getFormalTypeParameters()) {
if (name.equals(formalTypeParameter.getName()))
return assertFormalTypeParameter(formalTypeParameter, container);
}
fail("definition " + def.getName() + " does not contains a \"" + name
+ "\" formal type parameter.");
// unreachable
return null;
}
public FormalTypeParameterCheckerIterator containsFormalTypeParameters(
final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<FormalTypeParameterChecker> list = new ArrayList<FormalTypeParameterChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsFormalTypeParameter(name));
}
assertEquals(
"Definition contains more FormalTypeParameter than expected.",
names.length,
((FormalTypeParameterContainer) def).getFormalTypeParameters().length);
return new FormalTypeParameterCheckerIterator(list);
}
public FormalParameterChecker containsFormalParameter(final String name) {
if (!(def instanceof FormalParameterContainer))
fail("definition do not implements FormalParameterContainer");
final FormalParameterContainer container = (FormalParameterContainer) def;
for (final FormalParameter formalParameter : container
.getFormalParameters()) {
if (name.equals(formalParameter.getName()))
return assertFormalParameter(formalParameter, container);
}
fail("definition " + def.getName() + " does not contains a \"" + name
+ "\" formal parameter.");
// unreachable
return null;
}
public FormalParameterCheckerIterator containsFormalParameters(
final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<FormalParameterChecker> list = new ArrayList<FormalParameterChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsFormalParameter(name));
}
assertEquals("Definition contains more FormalParameter than expected.",
names.length,
((FormalParameterContainer) def).getFormalParameters().length);
return new FormalParameterCheckerIterator(list);
}
public AttributeChecker containsAttribute(final String name) {
if (!(def instanceof AttributeContainer))
fail("definition do not implements AttributeContainer");
final AttributeContainer container = (AttributeContainer) def;
for (final Attribute attribute : container.getAttributes()) {
if (name.equals(attribute.getName()))
return assertAttribute(attribute, container);
}
fail("definition " + def.getName() + " does not contains a \"" + name
+ "\" attribute.");
// unreachable
return null;
}
public AttributeCheckerIterator containsAttributes(final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<AttributeChecker> list = new ArrayList<AttributeChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsAttribute(name));
}
assertEquals("Definition contains more attribute than expected.",
names.length, ((AttributeContainer) def).getAttributes().length);
return new AttributeCheckerIterator(list);
}
public DefinitionChecker isSingleton() {
assertTrue("Definition is not singleton", ASTHelper.isSingleton(def));
assertTrue(
"Definition does not contain the is-singleton decoration",
def.astGetDecoration(ASTHelper.SINGLETON_DECORATION_NAME) != null
&& (Boolean) def
.astGetDecoration(ASTHelper.SINGLETON_DECORATION_NAME));
return this;
}
public DefinitionChecker isMultiton() {
assertFalse("Definition is singleton", ASTHelper.isSingleton(def));
assertTrue("Definition contains the is-singleton decoration",
def.astGetDecoration(ASTHelper.SINGLETON_DECORATION_NAME) == null);
return this;
}
}
// ---------------------------------------------------------------------------
// Definition Reference checking
// ---------------------------------------------------------------------------
protected Definition checkDefinitionReference(final DefinitionReference defRef) {
assertNotNull("Given definition reference is null", defRef);
assertNotNull("definition reference name is null", defRef.getName());
final DefinitionDecoration deco = (DefinitionDecoration) defRef
.astGetDecoration(RESOLVED_DEFINITION_DECORATION_NAME);
assertNotNull(RESOLVED_DEFINITION_DECORATION_NAME + " decoration is null.",
deco);
final Definition resolvedDefinition = deco.getDefinition();
assertNotNull(RESOLVED_DEFINITION_DECORATION_NAME + " definition is null.",
resolvedDefinition);
assertEquals(
"Name of resolved definition is not coherent with decoration.",
deco.getDefinitionName(), resolvedDefinition.getName());
assertEquals(
"Name of resolved definition does not match definition reference name.",
defRef.getName(), resolvedDefinition.getName());
return resolvedDefinition;
}
DefinitionReferenceChecker assertDefinitionReference(
final DefinitionReference defRef) {
DefinitionReferenceChecker checker = (DefinitionReferenceChecker) checkers
.get(defRef);
if (checker == null) {
checker = createDefinitionReferenceChecker(defRef);
checkers.put(defRef, checker);
}
return checker;
}
protected DefinitionReferenceChecker createDefinitionReferenceChecker(
final DefinitionReference defRef) {
return new DefinitionReferenceChecker(defRef);
}
public class DefinitionReferenceChecker {
public final DefinitionReference defRef;
protected DefinitionReferenceChecker(final DefinitionReference defRef) {
this.defRef = defRef;
checkDefinitionReference(defRef);
}
public DefinitionReferenceChecker that() {
return this;
}
public DefinitionReferenceChecker references(final String name) {
assertEquals("Unexpected referenced definition", name, defRef.getName());
return this;
}
public ArgumentChecker containsArgument(final String name) {
if (!(defRef instanceof ArgumentContainer))
fail("definition reference do not implements ArgumentContainer");
final ArgumentContainer container = (ArgumentContainer) defRef;
for (final Argument argument : container.getArguments()) {
if (name.equals(argument.getName()))
return assertArgument(argument, container);
}
fail("definition reference does not contains a \"" + name
+ "\" argument.");
// unreachable
return null;
}
public ArgumentCheckerIterator containsArguments(final String... names) {
final Set<String> nameSet = new HashSet<String>();
final List<ArgumentChecker> list = new ArrayList<ArgumentChecker>(
names.length);
for (final String name : names) {
assertTrue("Duplucated string in given names " + names,
nameSet.add(name));
list.add(containsArgument(name));
}
assertEquals("Definition contains more FormalParameter than expected.",
names.length, ((ArgumentContainer) defRef).getArguments().length);
return new ArgumentCheckerIterator(list);
}
}
// ---------------------------------------------------------------------------
// Interface checking
// ---------------------------------------------------------------------------
protected void checkInterface(final Interface itf) {
assertNotNull("Given interface is null", itf);
assertNotNull("interface name is null", itf.getName());
}
protected void checkInterfaceContainer(final InterfaceContainer container) {
final Set<String> names = new HashSet<String>();
for (final Interface itf : container.getInterfaces()) {
assertTrue("Duplicated interface name.", names.add(itf.getName()));
checkInterface(itf);
}
}
public InterfaceChecker assertInterface(final Interface itf,
final InterfaceContainer container) {
InterfaceChecker checker = (InterfaceChecker) checkers.get(itf);
if (checker == null) {
checker = createInterfaceChecker(itf, container);
checkers.put(itf, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected InterfaceChecker createInterfaceChecker(final Interface itf,
final InterfaceContainer container) {
return new InterfaceChecker(itf, container);
}
public class InterfaceChecker {
public final Interface itf;
public final InterfaceContainer container;
protected InterfaceChecker(final Interface itf,
final InterfaceContainer container) {
this.itf = itf;
this.container = container;
checkInterface(itf);
}
public InterfaceChecker isClient() {
assertTrue("Interface is not a TypeInterface",
itf instanceof TypeInterface);
assertTrue("Interface is not a client interface",
TypeInterfaceUtil.isClient(itf));
return this;
}
public InterfaceChecker isServer() {
assertTrue("Interface is not a TypeInterface",
itf instanceof TypeInterface);
assertTrue("Interface is not a client interface",
TypeInterfaceUtil.isServer(itf));
return this;
}
public InterfaceChecker isMandatory() {
assertTrue("Interface is not a TypeInterface",
itf instanceof TypeInterface);
assertTrue("Interface is not a client interface",
TypeInterfaceUtil.isMandatory(itf));
return this;
}
public InterfaceChecker isOptional() {
assertTrue("Interface is not a TypeInterface",
itf instanceof TypeInterface);
assertTrue("Interface is not a client interface",
TypeInterfaceUtil.isOptional(itf));
return this;
}
public InterfaceChecker hasSignature(final String signature) {
assertTrue("Interface is not a TypeInterface",
itf instanceof TypeInterface);
assertEquals("Unexpected interface signature", signature,
((TypeInterface) itf).getSignature());
return this;
}
}
public static class InterfaceCheckerIterator
extends
CheckerIterator<InterfaceCheckerIterator, InterfaceChecker> {
public InterfaceCheckerIterator(final List<InterfaceChecker> list) {
super(list);
}
@Override
protected InterfaceCheckerIterator getThis() {
return this;
}
public InterfaceCheckerIterator isClient() {
element.isClient();
return this;
}
public InterfaceCheckerIterator isServer() {
element.isServer();
return this;
}
public InterfaceCheckerIterator isMandatory() {
element.isMandatory();
return this;
}
public InterfaceCheckerIterator isOptional() {
element.isOptional();
return this;
}
public InterfaceCheckerIterator hasSignature(final String signature) {
element.hasSignature(signature);
return this;
}
}
// ---------------------------------------------------------------------------
// Component checking
// ---------------------------------------------------------------------------
protected void checkComponent(final Component component) {
assertNotNull("Given component is null", component);
assertNotNull("component name is null", component.getName());
if (component.getDefinitionReference() != null)
checkDefinitionReference(component.getDefinitionReference());
}
protected void checkComponentContainer(final ComponentContainer container) {
final Set<String> names = new HashSet<String>();
for (final Component comp : container.getComponents()) {
assertTrue("Duplicated sub-component name.", names.add(comp.getName()));
checkComponent(comp);
}
}
public ComponentChecker assertComponent(final Component comp,
final ComponentContainer container) {
ComponentChecker checker = (ComponentChecker) checkers.get(comp);
if (checker == null) {
checker = createComponentChecker(comp, container);
checkers.put(comp, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected ComponentChecker createComponentChecker(final Component comp,
final ComponentContainer container) {
return new ComponentChecker(comp, container);
}
public class ComponentChecker {
public final Component comp;
public final ComponentContainer container;
protected ComponentChecker(final Component comp,
final ComponentContainer container) {
this.comp = comp;
this.container = container;
assertTrue("Unexpected container", container instanceof Definition);
checkComponent(comp);
}
public ComponentChecker that() {
return this;
}
public DefinitionReferenceChecker isReferencing(final String name) {
return assertDefinitionReference(comp.getDefinitionReference())
.references(name);
}
public DefinitionChecker isAnInstanceOf(final String defName) {
final Definition compDef;
try {
compDef = getResolvedComponentDefinition(comp, null, null);
} catch (final ADLException e) {
// never happen
return null;
}
assertNotNull("Component does not contains a definition reference",
compDef);
if (defName != null)
assertEquals("Unexpected definition for component " + comp.getName(),
defName, compDef.getName());
return new DefinitionChecker(compDef);
}
public ComponentChecker isAnInstanceOfSingleton() {
isAnInstanceOf(null).isSingleton();
return this;
}
public ComponentChecker isAnInstanceOfMultiton() {
isAnInstanceOf(null).isMultiton();
return this;
}
public FormalTypeParameterChecker referencesFormalTypeParameter(
final String name) {
assertTrue("Compoenent does not implement FormalTypeParameterReference",
comp instanceof FormalTypeParameterReference);
final String typeParameterReference = ((FormalTypeParameterReference) comp)
.getTypeParameterReference();
assertNotNull("Compoenent does not reference a formal type parameter",
typeParameterReference);
assertEquals(
"Compoenent does not reference the expected formal type parameter",
name, typeParameterReference);
return assertDefinition((Definition) container)
.containsFormalTypeParameter(name);
}
}
public static class ComponentCheckerIterator
extends
CheckerIterator<ComponentCheckerIterator, ComponentChecker> {
public ComponentCheckerIterator(final List<ComponentChecker> list) {
super(list);
}
@Override
protected ComponentCheckerIterator getThis() {
return this;
}
public DefinitionReferenceChecker isReferencing(final String name) {
return element.isReferencing(name);
}
public ComponentCheckerIterator isAnInstanceOf(final String defName) {
element.isAnInstanceOf(defName);
return this;
}
public ComponentCheckerIterator isAnInstanceOfSingleton() {
element.isAnInstanceOfSingleton();
return this;
}
public ComponentCheckerIterator isAnInstanceOfMultiton() {
element.isAnInstanceOfMultiton();
return this;
}
public ComponentCheckerIterator referencesFormalTypeParameter(
final String name) {
element.referencesFormalTypeParameter(name);
return this;
}
}
// ---------------------------------------------------------------------------
// Attribute checking
// ---------------------------------------------------------------------------
protected void checkAttribute(final Attribute attribute) {
assertNotNull("Given attribute is null", attribute);
assertNotNull("Attribute name is null", attribute.getName());
}
protected void checkAttributeContainer(final AttributeContainer container) {
final Set<String> names = new HashSet<String>();
for (final Attribute attribute : container.getAttributes()) {
assertTrue("Duplicated FormalTypeParameter name.",
names.add(attribute.getName()));
checkAttribute(attribute);
}
}
public AttributeChecker assertAttribute(final Attribute attribute,
final AttributeContainer container) {
AttributeChecker checker = (AttributeChecker) checkers.get(attribute);
if (checker == null) {
checker = createAttributeChecker(attribute, container);
checkers.put(attribute, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected AttributeChecker createAttributeChecker(final Attribute attribute,
final AttributeContainer container) {
return new AttributeChecker(attribute, container);
}
public class AttributeChecker {
public final Attribute attribute;
public final AttributeContainer container;
protected AttributeChecker(final Attribute attribute,
final AttributeContainer container) {
this.attribute = attribute;
this.container = container;
assertTrue("Unexpected container", container instanceof Definition);
checkAttribute(attribute);
}
public AttributeChecker hasType(final String type) {
final String attrType = attribute.getIdt() != null ? attribute.getIdt()
+ ":" + attribute.getType() : attribute.getType();
assertEquals("Unexpected attribute type ", type, attrType);
return this;
}
public AttributeChecker and() {
return this;
}
public ValueChecker value() {
assertNotNull(attribute.getValue());
return assertValue(attribute.getValue());
}
public void hasNoValue() {
assertNull(attribute.getValue());
}
}
public static class AttributeCheckerIterator
extends
CheckerIterator<AttributeCheckerIterator, AttributeChecker> {
public AttributeCheckerIterator(final List<AttributeChecker> list) {
super(list);
}
@Override
protected AttributeCheckerIterator getThis() {
return this;
}
public AttributeCheckerIterator hasType(final String type) {
element.hasType(type);
return this;
}
public AttributeCheckerIterator and() {
return this;
}
public AttributeCheckerIterator valueIs(final int v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueIs(final String v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueIs(final Object[] v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueIs(final Iterable<?> v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueIs(final Map<?, ?> v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueIs(final ReferenceValue v) {
element.value().is(v);
return this;
}
public AttributeCheckerIterator valueReferences(final String ref) {
element.value().references(ref);
return this;
}
public AttributeCheckerIterator hasNoValue() {
element.hasNoValue();
return this;
}
}
// ---------------------------------------------------------------------------
// FormalTypeParameter checking
// ---------------------------------------------------------------------------
protected void checkFormalTypeParameter(
final FormalTypeParameter formalTypeParameter) {
assertNotNull("Given FormalTypeParameter is null", formalTypeParameter);
assertNotNull("FormalTypeParameter name is null",
formalTypeParameter.getName());
if (formalTypeParameter.getDefinitionReference() != null)
checkDefinitionReference(formalTypeParameter.getDefinitionReference());
}
protected void checkFormalTypeParameterContainer(
final FormalTypeParameterContainer container) {
final Set<String> names = new HashSet<String>();
for (final FormalTypeParameter formalTypeParameter : container
.getFormalTypeParameters()) {
assertTrue("Duplicated FormalTypeParameter name.",
names.add(formalTypeParameter.getName()));
checkFormalTypeParameter(formalTypeParameter);
}
}
public FormalTypeParameterChecker assertFormalTypeParameter(
final FormalTypeParameter formalTypeParameter,
final FormalTypeParameterContainer container) {
FormalTypeParameterChecker checker = (FormalTypeParameterChecker) checkers
.get(formalTypeParameter);
if (checker == null) {
checker = createFormalTypeParameterChecker(formalTypeParameter, container);
checkers.put(formalTypeParameter, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected FormalTypeParameterChecker createFormalTypeParameterChecker(
final FormalTypeParameter formalTypeParameter,
final FormalTypeParameterContainer container) {
return new FormalTypeParameterChecker(formalTypeParameter, container);
}
public class FormalTypeParameterChecker {
public final FormalTypeParameter formalTypeParameter;
public final FormalTypeParameterContainer container;
protected FormalTypeParameterChecker(
final FormalTypeParameter formalTypeParameter,
final FormalTypeParameterContainer container) {
this.formalTypeParameter = formalTypeParameter;
this.container = container;
assertTrue("Unexpected container", container instanceof Definition);
checkFormalTypeParameter(formalTypeParameter);
}
public DefinitionChecker conformsTo(final String defName) {
assertEquals("Unexpected type for formalTypeParameter "
+ formalTypeParameter.getName(), defName, formalTypeParameter
.getDefinitionReference().getName());
return assertDefinition(checkDefinitionReference(formalTypeParameter
.getDefinitionReference()));
}
}
public static class FormalTypeParameterCheckerIterator
extends
CheckerIterator<FormalTypeParameterCheckerIterator, FormalTypeParameterChecker> {
public FormalTypeParameterCheckerIterator(
final List<FormalTypeParameterChecker> list) {
super(list);
}
@Override
protected FormalTypeParameterCheckerIterator getThis() {
return this;
}
public FormalTypeParameterCheckerIterator conformsTo(final String defName) {
element.conformsTo(defName);
return this;
}
}
// ---------------------------------------------------------------------------
// FormalParameter checking
// ---------------------------------------------------------------------------
protected void checkFormalParameter(final FormalParameter formalParameter) {
assertNotNull("Given FormalParameter is null", formalParameter);
assertNotNull("FormalParameter name is null", formalParameter.getName());
}
protected void checkFormalParameterContainer(
final FormalParameterContainer container) {
final Set<String> names = new HashSet<String>();
for (final FormalParameter formalParameter : container
.getFormalParameters()) {
assertTrue("Duplicated FormalTypeParameter name.",
names.add(formalParameter.getName()));
checkFormalParameter(formalParameter);
}
}
public FormalParameterChecker assertFormalParameter(
final FormalParameter formalParameter,
final FormalParameterContainer container) {
FormalParameterChecker checker = (FormalParameterChecker) checkers
.get(formalParameter);
if (checker == null) {
checker = createFormalParameterChecker(formalParameter, container);
checkers.put(formalParameter, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected FormalParameterChecker createFormalParameterChecker(
final FormalParameter formalParameter,
final FormalParameterContainer container) {
return new FormalParameterChecker(formalParameter, container);
}
public class FormalParameterChecker {
public final FormalParameter formalParameter;
public final FormalParameterContainer container;
protected FormalParameterChecker(final FormalParameter formalParameter,
final FormalParameterContainer container) {
this.formalParameter = formalParameter;
this.container = container;
assertTrue("Unexpected container", container instanceof Definition);
checkFormalParameter(formalParameter);
}
public void hasType(final ParameterType type) {
final ParameterType inferredParameterType = getInferredParameterType(formalParameter);
assertNotNull("FormalParamter has no inferred type",
inferredParameterType);
assertEquals(
"Unexpected type for formalParameter " + formalParameter.getName(),
type, inferredParameterType);
}
public void hasNoType() {
final ParameterType inferredParameterType = getInferredParameterType(formalParameter);
assertNull("FormalParamter has an inferred type", inferredParameterType);
}
}
public static class FormalParameterCheckerIterator
extends
CheckerIterator<FormalParameterCheckerIterator, FormalParameterChecker> {
public FormalParameterCheckerIterator(
final List<FormalParameterChecker> list) {
super(list);
}
@Override
protected FormalParameterCheckerIterator getThis() {
return this;
}
public FormalParameterCheckerIterator hasType(final ParameterType type) {
element.hasType(type);
return this;
}
public FormalParameterCheckerIterator hasNoType() {
element.hasNoType();
return this;
}
}
// ---------------------------------------------------------------------------
// Argument checking
// ---------------------------------------------------------------------------
protected void checkArgument(final Argument argument) {
assertNotNull("Given Argument is null", argument);
assertNotNull("Argument name is null", argument.getName());
assertNotNull("Argument value is null", argument.getValue());
}
public ArgumentChecker assertArgument(final Argument argument,
final ArgumentContainer container) {
ArgumentChecker checker = (ArgumentChecker) checkers.get(argument);
if (checker == null) {
checker = createArgumentChecker(argument, container);
checkers.put(argument, checker);
} else {
assertSame("Unexpected container", container, checker.container);
}
return checker;
}
protected ArgumentChecker createArgumentChecker(final Argument argument,
final ArgumentContainer container) {
return new ArgumentChecker(argument, container);
}
public class ArgumentChecker {
public final Argument argument;
public final ArgumentContainer container;
protected ArgumentChecker(final Argument argument,
final ArgumentContainer container) {
this.argument = argument;
this.container = container;
checkArgument(argument);
}
public ValueChecker value() {
return assertValue(argument.getValue());
}
public ArgumentChecker valueIs(final int v) {
assertValue(argument.getValue()).is(v);
return this;
}
public ArgumentChecker valueIs(final String v) {
assertValue(argument.getValue()).is(v);
return this;
}
public ArgumentChecker valueReferences(final String ref) {
assertValue(argument.getValue()).references(ref);
return this;
}
}
public static class ArgumentCheckerIterator
extends
CheckerIterator<ArgumentCheckerIterator, ArgumentChecker> {
public ArgumentCheckerIterator(final List<ArgumentChecker> list) {
super(list);
}
@Override
protected ArgumentCheckerIterator getThis() {
return this;
}
public ValueChecker value() {
return element.value();
}
public ArgumentCheckerIterator valueIs(final int v) {
element.valueIs(v);
return this;
}
public ArgumentCheckerIterator valueIs(final String v) {
element.valueIs(v);
return this;
}
public ArgumentCheckerIterator valueIs(final Object[] v) {
element.value().is(v);
return this;
}
public ArgumentCheckerIterator valueIs(final Iterable<?> v) {
element.value().is(v);
return this;
}
public ArgumentCheckerIterator valueIs(final Map<?, ?> v) {
element.value().is(v);
return this;
}
public ArgumentCheckerIterator valueIs(final ReferenceValue v) {
element.value().is(v);
return this;
}
public ArgumentCheckerIterator valueReferences(final String ref) {
element.valueReferences(ref);
return this;
}
}
// ---------------------------------------------------------------------------
// Value checking
// ---------------------------------------------------------------------------
protected void checkValue(final Value value) {
assertNotNull("Given value is null", value);
assertTrue("Unknown value type " + value.astGetType(),
(value instanceof NumberLiteral) || (value instanceof Reference)
|| (value instanceof StringLiteral)
|| (value instanceof CompoundValue));
}
public ValueChecker assertValue(final Value value) {
ValueChecker checker = (ValueChecker) checkers.get(value);
if (checker == null) {
checker = createValueChecker(value);
checkers.put(value, checker);
}
return checker;
}
public static final class ReferenceValue {
private final String referenceName;
public ReferenceValue(final String referenceName) {
this.referenceName = referenceName;
}
public String getReferenceName() {
return referenceName;
}
}
protected ValueChecker createValueChecker(final Value value) {
return new ValueChecker(value);
}
public class ValueChecker {
public final Value value;
public ValueChecker(final Value value) {
this.value = value;
checkValue(value);
}
public void is(final int v) {
assertTrue("Value is not an IntegerLiteral",
value instanceof NumberLiteral);
assertEquals("Unexpected integer value", v,
getValue((NumberLiteral) value));
}
public void is(final String v) {
assertTrue("Value is not an StringLiteral",
value instanceof StringLiteral);
final String strValue = ((StringLiteral) value).getValue();
assertEquals("Unexpected string value", v,
strValue.substring(1, strValue.length() - 1));
}
public void is(final ReferenceValue v) {
references(v.getReferenceName());
}
public void is(final Object[] compoundValues) {
is(Arrays.asList(compoundValues));
}
public void is(final Iterable<?> compoundValues) {
assertTrue("Value is not an CompoundValue",
value instanceof CompoundValue);
final Iterator<?> values = compoundValues.iterator();
for (final CompoundValueField field : ((CompoundValue) value)
.getCompoundValueFields()) {
assertTrue("More compound value fields than expected", values.hasNext());
final Object v = values.next();
assertNotNull("Value missing in compound field", field.getValue());
createValueChecker(field.getValue()).is(v);
}
}
public void is(final Map<?, ?> compoundValues) {
assertTrue("Value is not an CompoundValue",
value instanceof CompoundValue);
final Map<Object, Object> values = new HashMap<Object, Object>(
compoundValues);
for (final CompoundValueField field : ((CompoundValue) value)
.getCompoundValueFields()) {
assertFalse("More compound value fields than expected",
values.isEmpty());
assertNotNull("Name missing in compound field", field.getName());
assertNotNull("Value missing in compound field", field.getValue());
final Object v = values.get(field.getName());
assertNotNull("Unexpected name of compound field '" + field.getName()
+ "'", v);
createValueChecker(field.getValue()).is(v);
}
}
public void is(final Object v) {
if (v instanceof String) {
is((String) v);
} else if (v instanceof Number) {
is(((Number) v).intValue());
} else if (v instanceof Iterable<?>) {
is((Iterable<?>) v);
} else if (v instanceof Object[]) {
is((Object[]) v);
} else if (v instanceof ReferenceValue) {
is((ReferenceValue) v);
} else {
fail("Unknown value type: " + v.getClass());
}
}
public void references(final String ref) {
assertTrue("Value is not a reference", value instanceof Reference);
assertEquals("Unexpected reference", ref, ((Reference) value).getRef());
}
}
public static class ValueCheckerIterator
extends
CheckerIterator<ValueCheckerIterator, ValueChecker> {
public ValueCheckerIterator(final List<ValueChecker> list) {
super(list);
}
@Override
protected ValueCheckerIterator getThis() {
return this;
}
public ValueCheckerIterator is(final int v) {
element.is(v);
return this;
}
public ValueCheckerIterator is(final String v) {
element.is(v);
return this;
}
public ValueCheckerIterator references(final String ref) {
element.references(ref);
return this;
}
}
// ---------------------------------------------------------------------------
// Utility
// ---------------------------------------------------------------------------
public static abstract class CheckerIterator<T extends CheckerIterator, U> {
protected final List<U> list;
protected Iterator<U> iterator;
protected U element;
public CheckerIterator(final List<U> list) {
this.list = list;
}
protected abstract T getThis();
public T whereFirst() {
iterator = list.iterator();
if (!iterator.hasNext()) fail("List is empty");
element = iterator.next();
return getThis();
}
public T andNext() {
if (!iterator.hasNext()) fail("List has no more element");
element = iterator.next();
return getThis();
}
public U that() {
return element;
}
}
}