/*******************************************************************************
* Copyright (c) 2014 Arapiki Solutions Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* psmith - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.model.undo;
import com.buildml.model.IActionMgr;
import com.buildml.model.IActionTypeMgr;
import com.buildml.model.IBuildStore;
import com.buildml.model.IPackageMgr;
import com.buildml.model.ISlotTypes;
import com.buildml.model.ISubPackageMgr;
import com.buildml.model.ISlotTypes.SlotDetails;
/**
* An undo/redo operation for any change that is made to a slot. This object records the
* details of the changes necessary to the IBuildStore so they can be undone or redone later.
*
* @author Peter Smith <psmith@arapiki.com>
*/
public class SlotUndoOp implements IUndoOp {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/**
* What type of event does this operation represent?
*/
private final static int NEW_SLOT = 1;
private final static int CHANGE_SLOT = 2;
private final static int REMOVE_SLOT = 3;
private final static int CHANGE_SLOT_VALUE = 4;
/** The code for this operation */
private int opCode = 0;
/** The type of owner (ISlotTypes.SLOT_OWNER_ACTION/SLOT_OWNER_PACKAGE) */
private int ownerType;
/** Our IPackageMgr for operating on */
private IPackageMgr pkgMgr;
/** Our IActionTypeMgr for operating on */
private IActionTypeMgr actionTypeMgr;
/** Our ISubPackageMgr for operating on */
private ISubPackageMgr subPkgMgr;
/** Our IActionMgr for operating on */
private IActionMgr actionMgr;
/** For NEW_SLOT, REMOVE_SLOT and CHANGE_SLOT_VALUE, what slotId */
private int slotId;
/** For CHANGE_SLOT, the new slot details */
private SlotDetails newDetails;
/** For CHANGE_SLOT, the existing slot details */
private SlotDetails oldDetails;
/** For CHANGE_SLOT_VALUE, the action or sub-package ID */
private int ownerId;
/** For CHANGE_SLOT_VALUE, true if there was an old value (false if it defaulted) */
private boolean oldExisted;
/** For CHANGE_SLOT_VALUE, true if there is a new value (false if it should default) */
private boolean newExists;
/** For CHANGE_SLOT_VALUE, the old slot value (if oldExisted is true) */
private Object oldValue;
/** For CHANGE_SLOT_VALUE, the new slot value (if newExisted is true) */
private Object newValue;
/*=====================================================================================*
* CONSTRUCTORS
*=====================================================================================*/
/**
* Create a new {@link SlotUndoOp} object, representing a single entry on the
* undo/redo stack.
*
* @param buildStore The IBuildStore we're performing the operation on.
* @param ownerType One of SLOT_OWNER_ACTION or SLOT_OWNER_PACKAGE.
*/
public SlotUndoOp(IBuildStore buildStore, int ownerType) {
this.ownerType = ownerType;
this.pkgMgr = buildStore.getPackageMgr();
this.actionTypeMgr = buildStore.getActionTypeMgr();
this.subPkgMgr = buildStore.getSubPackageMgr();
this.actionMgr = buildStore.getActionMgr();
}
/*-------------------------------------------------------------------------------------*/
/**
* Record the creation of a new slot.
*
* @param slotId ID of the newly-created slot.
*/
public void recordNewSlot(int slotId) {
opCode = NEW_SLOT;
this.slotId = slotId;
}
/*-------------------------------------------------------------------------------------*/
/**
* Record the removal of a slot.
*
* @param slotId ID of the slot to remove.
*/
public void recordRemoveSlot(int slotId) {
opCode = REMOVE_SLOT;
this.slotId = slotId;
}
/*-------------------------------------------------------------------------------------*/
/**
* Record the change of a slot.
*
* @param oldDetails The changed slot's old details.
* @param newDetails The changed slot's new details.
*/
public void recordChangeSlot(SlotDetails oldDetails, SlotDetails newDetails) {
opCode = CHANGE_SLOT;
this.oldDetails = oldDetails;
this.newDetails = newDetails;
}
/*-------------------------------------------------------------------------------------*/
/**
* Record a change in a slot's value.
*
* @param ownerId The actionId or subPkgId that owns the slot.
* @param slotId The ID of the slot to be changed.
* @param oldExisted True if the slot previously had a value (false if it defaulted).
* @param oldValue If oldExisted was true, the previous slot value.
* @param newExists True if the slot should now have a value (false if it should default).
* @param newValue If newExisted is true, the new slot value.
*/
public void recordChangeSlotValue(int ownerId, int slotId,
boolean oldExisted, Object oldValue,
boolean newExists, Object newValue) {
opCode = CHANGE_SLOT_VALUE;
this.ownerId = ownerId;
this.slotId = slotId;
this.oldExisted = oldExisted;
this.oldValue = oldValue;
this.newExists = newExists;
this.newValue = newValue;
}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/* (non-Javadoc)
* @see com.buildml.model.undo.IUndoOp#undo()
*/
@Override
public boolean undo() {
switch (opCode) {
/* undo the "new slot" operation by trashing it */
case NEW_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.trashSlot(slotId);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.trashSlot(slotId);
}
break;
/* undo the "change slot" operation */
case CHANGE_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.changeSlot(oldDetails);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.changeSlot(oldDetails);
}
break;
/* undo the "remove slot" operation by reviving it */
case REMOVE_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.reviveSlot(slotId);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.reviveSlot(slotId);
}
break;
case CHANGE_SLOT_VALUE:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
if (oldExisted) {
subPkgMgr.setSlotValue(ownerId, slotId, oldValue);
} else {
subPkgMgr.clearSlotValue(ownerId, slotId);
}
} else {
if (oldExisted) {
actionMgr.setSlotValue(ownerId, slotId, oldValue);
} else {
actionMgr.clearSlotValue(ownerId, slotId);
}
}
break;
default:
return false;
}
/* yes, a change happened */
return true;
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see com.buildml.model.undo.IUndoOp#redo()
*/
@Override
public boolean redo() {
switch (opCode) {
/* redo the "new slot" operation by reviving it */
case NEW_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.reviveSlot(slotId);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.reviveSlot(slotId);
}
break;
/* redo the "change slot" operation */
case CHANGE_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.changeSlot(newDetails);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.changeSlot(newDetails);
}
break;
/* redo the "remove slot" operation by trashing it */
case REMOVE_SLOT:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
pkgMgr.trashSlot(slotId);
} else if (ownerType == ISlotTypes.SLOT_OWNER_ACTION) {
actionTypeMgr.trashSlot(slotId);
}
break;
/* redo the "change slot value" operation */
case CHANGE_SLOT_VALUE:
if (ownerType == ISlotTypes.SLOT_OWNER_PACKAGE) {
if (newExists) {
subPkgMgr.setSlotValue(ownerId, slotId, newValue);
} else {
subPkgMgr.clearSlotValue(ownerId, slotId);
}
} else {
if (newExists) {
actionMgr.setSlotValue(ownerId, slotId, newValue);
} else {
actionMgr.clearSlotValue(ownerId, slotId);
}
}
break;
default:
return false;
}
/* yes, a change happened */
return true;
}
/*-------------------------------------------------------------------------------------*/
}