/*******************************************************************************
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package hr.fer.zemris.vhdllab.applets.editor.schema2.model.commands;
import hr.fer.zemris.vhdllab.applets.editor.schema2.enums.EErrorTypes;
import hr.fer.zemris.vhdllab.applets.editor.schema2.enums.EPropertyChange;
import hr.fer.zemris.vhdllab.applets.editor.schema2.exceptions.DuplicateKeyException;
import hr.fer.zemris.vhdllab.applets.editor.schema2.exceptions.InvalidCommandOperationException;
import hr.fer.zemris.vhdllab.applets.editor.schema2.exceptions.OverlapException;
import hr.fer.zemris.vhdllab.applets.editor.schema2.exceptions.UnknownKeyException;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ICommand;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ICommandResponse;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ISchemaComponent;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ISchemaComponentCollection;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ISchemaInfo;
import hr.fer.zemris.vhdllab.applets.editor.schema2.interfaces.ISchemaWire;
import hr.fer.zemris.vhdllab.applets.editor.schema2.misc.Caseless;
import hr.fer.zemris.vhdllab.applets.editor.schema2.misc.ChangeTuple;
import hr.fer.zemris.vhdllab.applets.editor.schema2.misc.PlacedComponent;
import hr.fer.zemris.vhdllab.applets.editor.schema2.misc.SchemaError;
import hr.fer.zemris.vhdllab.applets.editor.schema2.misc.SchemaPort;
import hr.fer.zemris.vhdllab.applets.editor.schema2.model.CommandResponse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class DeleteWireCommand implements ICommand {
private static class ConnectionInfo {
public Caseless cmpname, portname;
public ConnectionInfo(Caseless componentName, Caseless schemaPortName) {
cmpname = componentName;
portname = schemaPortName;
}
}
/* static fields */
public static final String COMMAND_NAME = "DeleteWireCommand";
/* private fields */
private Caseless name;
private ISchemaWire deleted;
private List<ConnectionInfo> cachedconnections;
/* ctors */
public DeleteWireCommand(Caseless wireName) {
name = wireName;
deleted = null;
cachedconnections = new ArrayList<ConnectionInfo>();
}
/* methods */
public String getCommandName() {
return COMMAND_NAME;
}
public boolean isUndoable() {
return true;
}
public ICommandResponse performCommand(ISchemaInfo info) {
deleted = info.getWires().fetchWire(name);
if (deleted == null) {
return new CommandResponse(new SchemaError(EErrorTypes.NONEXISTING_WIRE_NAME,
"Wire with name '" + name.toString() + "' could not be found."));
}
try {
info.getWires().removeWire(name);
} catch (UnknownKeyException e) {
throw new IllegalStateException("Wire was found once, but not twice!");
}
unplugAndCacheConnections(info);
return new CommandResponse(new ChangeTuple(EPropertyChange.ANY_CHANGE));
}
public ICommandResponse undoCommand(ISchemaInfo info) throws InvalidCommandOperationException {
if (deleted == null)
throw new InvalidCommandOperationException("Cannot call undo before command has been performed.");
try {
info.getWires().addWire(deleted);
} catch (DuplicateKeyException e) {
return new CommandResponse(new SchemaError(EErrorTypes.DUPLICATE_WIRE_NAME,
"Wire with name '" + name.toString() + "' already exists."));
} catch (OverlapException e) {
return new CommandResponse(new SchemaError(EErrorTypes.WIRE_OVERLAP,
"Wire with name '" + name.toString() + "' would overlap something else."));
}
plugCachedConnections(info);
deleted = null;
return new CommandResponse(new ChangeTuple(EPropertyChange.CANVAS_CHANGE));
}
private void unplugAndCacheConnections(ISchemaInfo info) {
SchemaPort sp = null;
Iterator<SchemaPort> spit = null;
for (PlacedComponent placed : info.getComponents()) {
if (placed.comp.isInvalidated()) continue;
spit = placed.comp.schemaPortIterator();
while (spit.hasNext()) {
sp = spit.next();
if (name.equals(sp.getMapping())) {
cachedconnections.add(new ConnectionInfo(placed.comp.getName(), sp.getName()));
sp.setMapping(null);
}
}
}
}
private void plugCachedConnections(ISchemaInfo info) {
ISchemaComponentCollection components = info.getComponents();
for (ConnectionInfo ci : cachedconnections) {
ISchemaComponent cmp = components.fetchComponent(ci.cmpname);
SchemaPort sp = cmp.getSchemaPort(ci.portname);
sp.setMapping(name);
}
cachedconnections.clear();
}
}