/*
* Copyright (c) 2011, IETR/INSA of Rennes
* Copyright (c) 2012, Synflow
* 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 IETR/INSA of Rennes 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 net.sf.orcc.df.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import net.sf.orcc.OrccRuntimeException;
import net.sf.orcc.df.Connection;
import net.sf.orcc.df.Instance;
import net.sf.orcc.df.Network;
import net.sf.orcc.df.Port;
import net.sf.orcc.df.util.XdfParser;
import net.sf.orcc.df.util.XdfWriter;
import net.sf.orcc.graph.Edge;
import net.sf.orcc.graph.Vertex;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
/**
* This class defines a resource implementation for the Df model which is used
* to serialize to/deserialize from XDF.
*
* @author Matthieu Wipliez
*
*/
public class XdfResourceImpl extends ResourceImpl {
public XdfResourceImpl() {
}
public XdfResourceImpl(URI uri) {
super(uri);
}
@Override
protected void doLoad(InputStream inputStream, Map<?, ?> options)
throws IOException {
try {
// the parser creates a network and adds it to this resource
new XdfParser(this, inputStream);
} catch (OrccRuntimeException e) {
// if there was an error, removes the network parsed so far
getContents().clear();
e.printStackTrace();
throw new IOException(e);
}
}
@Override
protected void doSave(OutputStream outputStream, Map<?, ?> options)
throws IOException {
try {
Network network = (Network) getContents().get(0);
new XdfWriter().write(network, outputStream);
} catch (OrccRuntimeException e) {
throw new IOException(e);
}
}
/**
* Returns the connection of the given network that corresponds to the given
* fragment.
*
* @param network
* network
* @param fragment
* a fragment of the form
* "//@connections:source.port-target.port"
* @return a connection, or <code>null</code>
*/
private Connection getConnection(Network network, String fragment) {
Vertex source, target;
String sourcePort = null, targetPort = null;
String arg = fragment.substring(12);
int dot = arg.indexOf('.');
int dash = arg.indexOf('-');
if (dash < dot) {
// first vertex is a port
source = network.getInput(arg.substring(0, dash));
} else {
// first vertex is an instance
source = network.getChild(arg.substring(0, dot));
sourcePort = arg.substring(dot + 1, dash);
}
dash++;
dot = arg.indexOf('.', dash);
if (dot == -1) {
// second vertex is a port
target = network.getOutput(arg.substring(dash));
} else {
// second vertex is an instance
target = network.getChild(arg.substring(dash, dot));
targetPort = arg.substring(dot + 1);
}
for (Edge edge : source.getOutgoing()) {
Connection connection = (Connection) edge;
if (connection.getTarget() != target) {
continue;
}
// if source port is not null, check connection's source port
if (sourcePort != null) {
Port port = connection.getSourcePort();
if (port == null || !sourcePort.equals(port.getName())) {
continue;
}
}
// if target port is not null, check connection's target port
if (targetPort != null) {
Port port = connection.getTargetPort();
if (port == null || !targetPort.equals(port.getName())) {
continue;
}
}
return connection;
}
return null;
}
@Override
public EObject getEObject(String uriFragment) {
if (getContents().isEmpty()) {
return null;
}
if (uriFragment.length() < 4 || !uriFragment.startsWith("//@")) {
return super.getEObject(uriFragment);
}
String fragment = uriFragment.substring(3);
EObject root = getContents().get(0);
if (root instanceof Network) {
final Network network = (Network) root;
if (fragment.startsWith("connections:")) {
return getConnection(network, fragment);
} else {
int index = fragment.lastIndexOf('.') + 1;
// The old objects paths style
if (!Character.isDigit(fragment.charAt(index))) {
String name = fragment.substring(index);
if (fragment.startsWith("inputs.")) {
return network.getInput(name);
} else if (fragment.startsWith("outputs.")) {
return network.getOutput(name);
} else if (fragment.startsWith("instances.")) {
return network.getChild(name);
} else if (fragment.startsWith("parameters.")) {
return network.getParameter(name);
} else if (fragment.startsWith("variables.")) {
return network.getVariable(name);
}
}
// The new objects paths style
else {
final int idx = Integer.parseInt(fragment.substring(index));
if (fragment.startsWith("inputs.")) {
return network.getInputs().get(idx);
} else if (fragment.startsWith("outputs.")) {
return network.getOutputs().get(idx);
} else if (fragment.startsWith("instances.")) {
return network.getChildren().get(idx);
}
}
}
}
return super.getEObject(uriFragment);
}
@Override
public String getURIFragment(EObject eObject) {
if(eObject.eContainer() instanceof Network) {
final Network network = (Network) eObject.eContainer();
final StringBuilder fragment = new StringBuilder("//@");
// We customize fragments only for instances and ports
if(eObject instanceof Port) {
final Port port = (Port) eObject;
if(network.getInputs().contains(port)) {
fragment.append("inputs.");
fragment.append(network.getInputs().indexOf(port));
} else if (network.getOutputs().contains(port)) {
fragment.append("outputs.");
fragment.append(network.getOutputs().indexOf(port));
}
return fragment.toString();
} else if (eObject instanceof Instance) {
final Instance instance = (Instance) eObject;
fragment.append("instances.");
fragment.append(network.getChildren().indexOf(instance));
return fragment.toString();
}
}
return super.getURIFragment(eObject);
}
}