/*
* License (BSD Style License):
* Copyright (c) 2011
* Software Engineering
* Department of Computer Science
* Technische Universitiät Darmstadt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Software Engineering Group or Technische
* Universität Darmstadt nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.tud.cs.st.vespucci.diagram.creator;
import java.util.List;
import de.tud.cs.st.vespucci.exceptions.VespucciIllegalArgumentException;
import de.tud.cs.st.vespucci.vespucci_model.Connection;
import de.tud.cs.st.vespucci.vespucci_model.Dummy;
import de.tud.cs.st.vespucci.vespucci_model.Ensemble;
import de.tud.cs.st.vespucci.vespucci_model.Expected;
import de.tud.cs.st.vespucci.vespucci_model.GlobalIncoming;
import de.tud.cs.st.vespucci.vespucci_model.GlobalOutgoing;
import de.tud.cs.st.vespucci.vespucci_model.InAndOut;
import de.tud.cs.st.vespucci.vespucci_model.Incoming;
import de.tud.cs.st.vespucci.vespucci_model.NotAllowed;
import de.tud.cs.st.vespucci.vespucci_model.Outgoing;
import de.tud.cs.st.vespucci.vespucci_model.Shape;
import de.tud.cs.st.vespucci.vespucci_model.Violation;
/**
* This class encapsulates the dependency prolog facts.
*
* @author Patrick Jahnke
* @author Thomas Schulz
* @author Alexander Weitzmann
* @author Theo Kischka
* @author Dominic Scheurer
*/
public class DependencyPrologFacts {
private DependencyPrologFacts() {}
/**
* Name of the current diagram file.
*/
private static String diagramFileName;
/**
* Counter for dependencies in given diagram.
*/
private static int dependencyCounter;
/**
* A convenience method to retrieve the dependency prolog facts.
*
* @param shapeList
* @param diagramFileName
* @return Returns the formatted dependency facts.
*/
static StringBuilder getFacts(final List<Shape> shapeList, final String diagramFileName) {
DependencyPrologFacts.diagramFileName = diagramFileName;
// reset transaction counter
dependencyCounter = 1;
return createDependencyFacts(shapeList);
}
/**
* Search the diagram recursively and create all facts.
*
* @param shapeList
* @return Returns the formatted dependency facts.
* @author Patrick Jahnke
*/
static StringBuilder createDependencyFacts(final List<Shape> shapeList) {
final StringBuilder dependencyFacts = new StringBuilder();
for (final Shape shape : shapeList) {
if (shape instanceof Ensemble) {
final Ensemble ensemble = (Ensemble) shape;
if (shape != null) {
for (final Connection connection : ensemble.getTargetConnections()) {
dependencyFacts.append(createSingleDependencyFact(connection));
}
}
if (ensemble.getShapes() != null) {
dependencyFacts.append(createDependencyFacts(ensemble.getShapes()));
}
}
}
return dependencyFacts;
}
/**
* @param connection
* @return Return a fact for a single dependency.
*/
private static String createSingleDependencyFact(final Connection connection) {
final Shape source = getSource(connection);
final Shape target = getTarget(connection);
final StringBuilder transactionSB = new StringBuilder();
// TODO: delete next 2 lines if saved sad file doesn't
// contain copy/paste artifact references.
// Problem: if, from one sad file, an ensemble with a dependency is copied
// to another sad file than the copy of the Ensemble will contain a reference
// to the original Ensemble in the first sad file.
// This reference has no influence to working process but it is a problem
// for prolog fact conversion.
if (connection.getSource().eIsProxy() || connection.getTarget().eIsProxy()) {
return "";
}
final String dependencySuffix = String.format("('%s', %s, %s, [], %s, [], [%s]).\n", diagramFileName, dependencyCounter,
getEnsembleName(source), getEnsembleName(target), connection.getName());
if (connection instanceof InAndOut) {
transactionSB.append("incoming").append(dependencySuffix);
transactionSB.append("outgoing").append(dependencySuffix);
} else {
final String connectionName = getDependencyTypeIdentifier(connection);
transactionSB.append(connectionName).append(dependencySuffix);
}
dependencyCounter++;
return transactionSB.toString();
}
/**
* Do not use this method for InAndOut connection, for there are two
* types connected with this.
*
* @param connection Connection to get the type name from.
* @return Type identifier for the given Connection.
*/
private static String getDependencyTypeIdentifier(final Connection connection) {
String connectionName = "";
if (connection instanceof Outgoing) {
connectionName = "outgoing";
} else if (connection instanceof Incoming) {
connectionName = "incoming";
} else if (connection instanceof Expected) {
connectionName = "expected";
} else if (connection instanceof NotAllowed) {
connectionName = "not_allowed";
} else if (connection instanceof GlobalIncoming) {
connectionName = "global_incoming";
} else if (connection instanceof GlobalOutgoing) {
connectionName = "global_outgoing";
} else if (connection instanceof Violation) {
connectionName = "violation";
} else {
throw new VespucciIllegalArgumentException(
String.format("Unsupported dependency type: %s", connection));
}
return connectionName;
}
/**
* Note, that {@link Connection#getSource()} does not return the same. That's because the source
* of the connection
* will be set to the parent of the semantic source-ensemble, if a red line is used.
*
* @param connection
* @return Returns the source of given connection.
*/
private static Shape getSource(final Connection connection) {
if ((connection.getOriginalSource() == null) || (connection.getOriginalSource().size() == 0)) {
return connection.getSource();
} else {
return connection.getOriginalSource().get(0);
}
}
/**
* Note, that {@link Connection#getTarget()} does not return the same. That's because the target
* of the connection
* will be set to the parent of the semantic target-ensemble, if a red line is used.
*
* @param connection
* @return Returns the source of given connection.
*/
private static Shape getTarget(final Connection connection) {
// Get the original target (and not the red line target)
if ((connection.getOriginalTarget() == null) || (connection.getOriginalTarget().size() == 0)) {
return connection.getTarget();
} else {
return connection.getOriginalTarget().get(0);
}
}
/**
* @param shape
* @return Returns the name of an ensemble (without the parameter).
*/
private static String getEnsembleName(final Shape shape) {
if (shape instanceof Ensemble) {
return EnsemblePrologFacts.createEnsembleDescriptor(shape);
} else if (shape instanceof Dummy) {
return "empty";
}
return "not_defined";
}
}