/** * 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 org.ow2.mind.annotation.AnnotationHelper.getAnnotation; import java.util.Map; import org.objectweb.fractal.adl.Node; import org.objectweb.fractal.adl.error.NodeErrorLocator; import org.objectweb.fractal.adl.merger.MergeException; import org.ow2.mind.adl.ast.Binding; import org.ow2.mind.st.STNodeMergerImpl; /** * Node merger component that implements the node merging algorithm that * respects the STCF ADL language. */ public class STCFNodeMerger extends STNodeMergerImpl { @Override protected void computeInhertedSubNodeMergeInfos(final Node inheritedSubNode, final MergeInfo parentInfo, final String subNodeType, final Map<Node, MergeInfo> infos) throws MergeException { if (subNodeType.equals("import") || subNodeType.equals("formalParameter") || subNodeType.equals("formalTypeParameter") || subNodeType.equals("extends")) { // these elements are not inherited. return; } else { super.computeInhertedSubNodeMergeInfos(inheritedSubNode, parentInfo, subNodeType, infos); } } @Override protected void computeMergedSubNodesMergeInfos(final Node subNode, final Node inheritedSubNode, final MergeInfo parentInfo, final Map<Node, MergeInfo> infos, final Map<String, String> idAttributes, final String subNodeType) throws MergeException { if (subNodeType.equals("annotation") || subNodeType.equals("formalParameter") || subNodeType.equals("formalTypeParameter") || subNodeType.equals("value")) { // these elements are simply overridden (i.e. not merged). super.computeSubNodeMergeInfos(subNode, parentInfo, subNodeType, infos); } else if (subNodeType.equals("interface")) { // interface elements can't be merge, this is considered as an error throw new InvalidMergeException( ADLErrors.INVALID_INTERFACE_NAME_OVERRIDE_INHERITED_INTERFACE, subNode, new NodeErrorLocator(inheritedSubNode)); } else if (subNodeType.equals("attribute")) { // Attribute can be overridden, but the type cannot be changed final String inheritedType = inheritedSubNode.astGetAttributes().get( "type"); final String overridingType = subNode.astGetAttributes().get("type"); if (!overridingType.equals(inheritedType)) { throw new InvalidMergeException( ADLErrors.INVALID_ATTRIBUTE_OVERRIDE_INHERITED_ATTRIBUTE_TYPE, subNode, new NodeErrorLocator(inheritedSubNode)); } super.computeMergedSubNodesMergeInfos(subNode, inheritedSubNode, parentInfo, infos, idAttributes, subNodeType); } else if (subNodeType.equals("component")) { super.computeSubNodeMergeInfos(subNode, parentInfo, subNodeType, infos); } else if (subNodeType.equals("binding")) { super.computeSubNodeMergeInfos(subNode, parentInfo, subNodeType, infos); } else { super.computeMergedSubNodesMergeInfos(subNode, inheritedSubNode, parentInfo, infos, idAttributes, subNodeType); } } @Override protected void computeSubNodeMergeInfos(final Node subNode, final MergeInfo parentInfo, final String subNodeType, final Map<Node, MergeInfo> infos) throws MergeException { if (getAnnotation(subNode, org.ow2.mind.adl.annotation.predefined.Override.class) != null) { // subNode is marked has overriding an inherited element but it doesn't. throw new InvalidMergeException(ADLErrors.DO_NOT_OVERRIDE, subNode); } super.computeSubNodeMergeInfos(subNode, parentInfo, subNodeType, infos); } @Override protected Node findOverridingNode(final Node superNode, final Node[] nodes, final String nodeType, final Map<String, String> idAttributes) { if (nodeType.equals("binding")) { final Binding superBinding = (Binding) superNode; final String superCompName = superBinding.getFromComponent(); final String superItfName = superBinding.getFromInterface(); for (final Node node : nodes) { final Binding binding = (Binding) node; if (superCompName.equals(binding.getFromComponent()) && superItfName.equals(binding.getFromInterface())) { return node; } } return null; } else { return super.findOverridingNode(superNode, nodes, nodeType, idAttributes); } } }