/*******************************************************************************
* Copyright (c) 2013 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 java.util.List;
import com.buildml.model.IBuildStore;
import com.buildml.model.IFileGroupMgr;
import com.buildml.model.IPackageMemberMgr;
import com.buildml.utils.errors.FatalError;
/**
* An undo/redo operation for any change that is made to a FileGroup. 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 FileGroupUndoOp implements IUndoOp {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/**
* Bitmap of all the parts of the fileGroup that have changed, and will need to be changed
* back on an undo/redo operation.
*/
private final static int CHANGED_PACKAGE = 1;
private final static int CHANGED_LOCATION = 2;
private final static int CHANGED_MEMBERSHIP = 4;
/** The IBuildStore we're operating on */
private IBuildStore buildStore;
/** The ID of the fileGroup being changed */
private int fileGroupId;
/** The type of this file group (e.g. SOURCE_GROUP, GENERATED_GROUP, etc) */
private int fileGroupType;
/** The fields of this operation that have changed - see above bitmap */
private int changedFields = 0;
/** if CHANGED_PACKAGE set, what is the original package ID? */
private int oldPackage;
/** if CHANGED_PACKAGE set, what is the new package ID? */
private int newPackage;
/** if CHANGED_LOCATION, what is the old (x, y) location */
private int oldX, oldY;
/** if CHANGED_LOCATION, what is the new (x, y) location */
private int newX, newY;
/** if CHANGED_MEMBERSHIP, what are the old members? */
private List<?> oldMembers;
/** if CHANGED_MEMBERSHIP, what are the new members? */
private List<?> newMembers;
/*=====================================================================================*
* CONSTRUCTORS
*=====================================================================================*/
/**
* Create a new {@link FileGroupUndoOp} object, representing a single entry on the
* undo/redo stack.
*
* @param buildStore The IBuildStore we're performing the operation on.
* @param fileGroupId The fileGroupMgr ID of the fileGroup being changed.
*/
public FileGroupUndoOp(IBuildStore buildStore, int fileGroupId) {
IFileGroupMgr fileGroupMgr = buildStore.getFileGroupMgr();
this.buildStore = buildStore;
this.fileGroupId = fileGroupId;
this.fileGroupType = fileGroupMgr.getGroupType(fileGroupId);
}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/**
* Records the fact that the file groups's package has changed. If there is no change in the
* packageId, this method does nothing.
*
* @param prevPackageId The group's current package ID.
* @param nextPackageId The group's future package ID.
*/
public void recordPackageChange(int prevPackageId, int nextPackageId) {
if (prevPackageId != nextPackageId) {
changedFields |= CHANGED_PACKAGE;
oldPackage = prevPackageId;
newPackage = nextPackageId;
}
}
/*-------------------------------------------------------------------------------------*/
/**
* Records the fact that the file groups's pictogram (icon) has been moved to a new location
* on the diagram.
* @param oldX The existing x location
* @param oldY The existing y location
* @param newX The new x location (must be >= 0)
* @param newY The new y location (must be >= 0)
*/
public void recordLocationChange(int oldX, int oldY, int newX, int newY) {
if ((oldX != newX) || (oldY != newY)) {
changedFields |= CHANGED_LOCATION;
this.oldX = oldX;
this.oldY = oldY;
this.newX = newX;
this.newY = newY;
}
}
/*-------------------------------------------------------------------------------------*/
/**
* Record the fact that the file groups's membership (file IDs) has changed.
* @param oldMembers The old members of this file group.
* @param newMembers The new members of this file group.
*/
public void recordMembershipChange(List<?> oldMembers, List<?> newMembers) {
if (!oldMembers.equals(newMembers)){
changedFields |= CHANGED_MEMBERSHIP;
this.oldMembers = oldMembers;
this.newMembers = newMembers;
}
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see com.buildml.model.undo.IUndoOp.undo()
*/
@Override
public boolean undo() {
IPackageMemberMgr pkgMemberMgr = buildStore.getPackageMemberMgr();
/* if the action's package needs to change... */
if ((changedFields & CHANGED_PACKAGE) != 0) {
pkgMemberMgr.setPackageOfMember(IPackageMemberMgr.TYPE_FILE_GROUP, fileGroupId, oldPackage);
}
/* if the action's location needs to change... */
if ((changedFields & CHANGED_LOCATION) != 0){
pkgMemberMgr.setMemberLocation(IPackageMemberMgr.TYPE_FILE_GROUP, fileGroupId, oldX, oldY);
}
if ((changedFields & CHANGED_MEMBERSHIP) != 0){
setFileGroupMembers(fileGroupId, oldMembers);
}
return (changedFields != 0);
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see com.buildml.model.undo.IUndoOp.redo()
*/
@Override
public boolean redo() {
IPackageMemberMgr pkgMemberMgr = buildStore.getPackageMemberMgr();
/* if the file group's package needs to change... */
if ((changedFields & CHANGED_PACKAGE) != 0) {
pkgMemberMgr.setPackageOfMember(IPackageMemberMgr.TYPE_FILE_GROUP, fileGroupId, newPackage);
}
/* if the file group's location needs to change... */
if ((changedFields & CHANGED_LOCATION) != 0){
pkgMemberMgr.setMemberLocation(IPackageMemberMgr.TYPE_FILE_GROUP, fileGroupId, newX, newY);
}
/* if the file group's membership needs to change... */
if ((changedFields & CHANGED_MEMBERSHIP) != 0){
setFileGroupMembers(fileGroupId, newMembers);
}
/* if there's a change, mark the editor as dirty */
return (changedFields != 0);
}
/*=====================================================================================*
* PRIVATE METHODS
*=====================================================================================*/
/**
* Set the membership of a file group to the contents of the specified ArrayList.
* @param fileGroupId The ID of the file group to set membership of.
* @param members The ArrayList of members to populate the file group with.
*/
private void setFileGroupMembers(int fileGroupId, List<?> members) {
IFileGroupMgr fileGroupMgr = buildStore.getFileGroupMgr();
if (fileGroupType == IFileGroupMgr.SOURCE_GROUP) {
fileGroupMgr.setPathIds(fileGroupId, members.toArray(new Integer[0]));
} else if (fileGroupType == IFileGroupMgr.MERGE_GROUP) {
fileGroupMgr.setSubGroups(fileGroupId, members.toArray(new Integer[0]));
} else if (fileGroupType == IFileGroupMgr.FILTER_GROUP) {
fileGroupMgr.setPathStrings(fileGroupId, members.toArray(new String[0]));
} else {
throw new FatalError("Unhandled file group type: " + fileGroupType);
}
}
/*-------------------------------------------------------------------------------------*/
}