/** * 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; } } }