/**
* 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 java.util.HashMap;
import java.util.Map;
import org.objectweb.fractal.adl.ADLException;
import org.objectweb.fractal.adl.Definition;
import org.objectweb.fractal.adl.Loader;
import org.objectweb.fractal.adl.Node;
import org.ow2.mind.error.ErrorManager;
import com.google.inject.Inject;
/**
* Generic abstract class that ease the implementation of {@link Loader} that
* checks that sub-nodes of a given type of sub-nodes have a unique Id.
*
* @param <T> The type of the sub-nodes to check.
*/
public abstract class AbstractNormalizerLoader<T extends Node>
extends
AbstractDelegatingLoader {
@Inject
protected ErrorManager errorManagerItf;
// ---------------------------------------------------------------------------
// Implementation of the Loader interface
// ---------------------------------------------------------------------------
public Definition load(final String name, final Map<Object, Object> context)
throws ADLException {
final Definition d = clientLoader.load(name, context);
normalize(d);
return d;
}
protected void normalize(final Definition d) throws ADLException {
final T[] subNodes = getSubNodes(d);
if (subNodes == null) return;
final Map<Object, T> nodeByIds = new HashMap<Object, T>();
for (final T subNode : subNodes) {
final Object id = getId(subNode);
final T previousDeclaration = nodeByIds.put(id, subNode);
if (previousDeclaration != null) {
handleNameClash(previousDeclaration, subNode);
removeSubNode(d, subNode);
}
}
}
/**
* Method calls when two sub-nodes with the same Id are found.
*
* @param previousDeclaration The first node with the Id.
* @param subNode The second node with the same Id.
* @throws ADLException The exception thrown as a consequence of the error.
*/
protected abstract void handleNameClash(T previousDeclaration, T subNode)
throws ADLException;
/**
* Method to remove a sub-node. This method is called when two sub-nodes with
* the same Id are found.
*
* @param node the parent node.
* @param subNode the node to remove.
*/
protected abstract void removeSubNode(Node node, T subNode);
/**
* Returns the array of sub nodes to check. May return <code>null</code>.
*
* @param node the parent node.
* @return the array of sub nodes to check. May return <code>null</code>.
*/
protected abstract T[] getSubNodes(Node node);
/**
* Returns the Id of the given sub-node.
*
* @param node a sub-node
* @return the Id of the given sub-node.
* @throws ADLException If an error occurs.
*/
protected abstract Object getId(T node) throws ADLException;
}