blob: d4b5328ce0eb29c9eecc8935e49f92abf38f7de9 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.annotation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.sf.taverna.t2.workflowmodel.Edit;
import net.sf.taverna.t2.workflowmodel.EditException;
/**
* Convenient abstract superclass for annotated things, manages edits.
* Subclasses of this must implement the Annotated interface with their own
* interface type as the parameter, so for example Processor subclasses would
* implement Annotated<Processor>
*
* @author Tom Oinn
* @author Alan R Williams
*
*/
public abstract class AbstractAnnotatedThing<T> implements Annotated<T> {
private Set<AnnotationChain> annotations = new HashSet<AnnotationChain>();
/**
* Return the set of annotations bound to this annotated object, the set
* returned is an unmodifiable copy of the internal annotation set, if you
* need to modify the annotations you should use the get methods for Edit
* objects to do so.
*
* @see net.sf.taverna.t2.annotation.Annotated#getAnnotations()
*/
public final Set<AnnotationChain> getAnnotations() {
return Collections.unmodifiableSet(annotations);
}
/**
* Set the annotation chains associated with this annotated object. This is
* only needed for deserialization and could almost certainly be done in a
* better way.
*
* @param annotations
*/
public final void setAnnotations(Set<AnnotationChain> annotations) {
this.annotations = annotations;
}
/**
* Superclass of edits to remove, add and replace annotations on instances
* of the enclosing AbstractAnnotatedThing class
*
* @author Tom
*
* @param <TargetType>
*/
private static abstract class AbstractAnnotationEdit<TargetType> implements
Edit<TargetType> {
private AbstractAnnotatedThing<TargetType> subject;
private boolean applied = false;
protected AbstractAnnotationEdit(
AbstractAnnotatedThing<TargetType> subject) {
this.subject = subject;
}
@SuppressWarnings("unchecked")
public final TargetType doEdit() throws EditException {
synchronized (subject) {
if (applied) {
throw new EditException("Edit already applied!");
}
doEditAction(subject);
this.applied = true;
return (TargetType) subject;
}
}
protected abstract void doEditAction(AbstractAnnotatedThing<?> subject)
throws EditException;
protected abstract void undoEditAction(AbstractAnnotatedThing<?> subject);
@SuppressWarnings("unchecked")
public final TargetType getSubject() {
return (TargetType) subject;
}
public final boolean isApplied() {
return this.applied;
}
public final void undo() {
synchronized (subject) {
if (!applied) {
throw new RuntimeException(
"Attempt to undo edit that was never applied");
}
undoEditAction(subject);
applied = false;
}
}
}
/**
* @see net.sf.taverna.t2.annotation.Annotated#getAddAnnotationEdit(net.sf.taverna.t2.annotation.WorkflowAnnotation)
*/
public final Edit<T> getAddAnnotationEdit(
final AnnotationChain newAnnotation) {
return new AbstractAnnotationEdit<T>(this) {
@Override
protected void doEditAction(AbstractAnnotatedThing<?> subject)
throws EditException {
annotations.add(newAnnotation);
}
@Override
protected void undoEditAction(AbstractAnnotatedThing<?> subject) {
annotations.remove(newAnnotation);
}
};
}
/**
* @see net.sf.taverna.t2.annotation.Annotated#getRemoveAnnotationEdit(net.sf.taverna.t2.annotation.WorkflowAnnotation)
*/
public final Edit<T> getRemoveAnnotationEdit(
final AnnotationChain annotationToRemove) {
return new AbstractAnnotationEdit<T>(this) {
@Override
protected void doEditAction(AbstractAnnotatedThing<?> subject)
throws EditException {
annotations.remove(annotationToRemove);
}
@Override
protected void undoEditAction(AbstractAnnotatedThing<?> subject) {
annotations.add(annotationToRemove);
}
};
}
}