// $Id: MemberList.java 14521 2008-04-29 22:49:07Z tfmorris $
// Copyright (c) 2004-2008 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.kernel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.apache.log4j.Logger;
import org.argouml.uml.ProjectMemberModel;
import org.argouml.uml.cognitive.ProjectMemberTodoList;
import org.argouml.uml.diagram.ProjectMemberDiagram;
import org.tigris.gef.base.Diagram;
/**
* List of ProjectMembers. <p>
*
* <p>The project members are grouped into 4 categories:
* model, diagrams, the todo item list and the profile configuration. <p>
*
* <p>The purpose of these categories is to make sure that members are read
* and written in the correct order.
*
* <p>When reading the todo items it will fail if the diagrams elements or model
* elements have not yet been read that they refer to. When reading diagrams
* that will fail if the model elements don't yet exist that they refer to.
* When loading the model that may fail if the correct profile has not been
* loaded.
*
* <p>Hence, the save (and therefore load) order is profile, model, diagrams,
* todo items.
*
* <p>This implementation supports only one profile configuration, one model
* member, multiple diagram members, one todo list member.
*
* <p>Comments by mvw: <p>
* This class should be reworked to be independent
* of the org.argouml.uml package. That can be done by extending the
* ProjectMember interface with functions returning the sorting order,
* and if multiple entries of the same type are allowed. <p>
*
* In preparation, this class is made simpler by deprecating
* all operations that are not part of the List interface.
*
* @author Bob Tarling
*/
class MemberList implements List<ProjectMember> {
/**
* Logger.
*/
private static final Logger LOG = Logger.getLogger(MemberList.class);
private AbstractProjectMember model;
private List<ProjectMemberDiagram> diagramMembers =
new ArrayList<ProjectMemberDiagram>(10);
private AbstractProjectMember todoList;
private AbstractProjectMember profileConfiguration;
/**
* The constructor.
*/
public MemberList() {
LOG.info("Creating a member list");
}
public synchronized boolean add(ProjectMember member) {
if (member instanceof ProjectMemberModel) {
// Always put the model at the top
model = (AbstractProjectMember) member;
return true;
} else if (member instanceof ProjectMemberTodoList) {
// otherwise add the diagram at the start
setTodoList((AbstractProjectMember) member);
return true;
} else if (member instanceof ProfileConfiguration) {
profileConfiguration = (AbstractProjectMember) member;
return true;
} else if (member instanceof ProjectMemberDiagram) {
// otherwise add the diagram at the start
return diagramMembers.add((ProjectMemberDiagram) member);
}
return false;
}
public synchronized boolean remove(Object member) {
LOG.info("Removing a member");
if (member instanceof Diagram) {
return removeDiagram((Diagram) member);
}
((AbstractProjectMember) member).remove();
if (model == member) {
model = null;
return true;
} else if (todoList == member) {
LOG.info("Removing todo list");
setTodoList(null);
return true;
} else if (profileConfiguration == member) {
LOG.info("Removing profile configuration");
profileConfiguration = null;
return true;
} else {
final boolean removed = diagramMembers.remove(member);
if (!removed) {
LOG.warn("Failed to remove diagram member " + member);
}
return removed;
}
}
public synchronized Iterator<ProjectMember> iterator() {
return buildOrderedMemberList().iterator();
}
public synchronized ListIterator<ProjectMember> listIterator() {
return buildOrderedMemberList().listIterator();
}
public synchronized ListIterator<ProjectMember> listIterator(int arg0) {
return buildOrderedMemberList().listIterator(arg0);
}
/**
* @return the list of members in the order that they need to be written
* out in.
*/
private List<ProjectMember> buildOrderedMemberList() {
List<ProjectMember> temp =
new ArrayList<ProjectMember>(size());
if (profileConfiguration != null) {
temp.add(profileConfiguration);
}
if (model != null) {
temp.add(model);
}
temp.addAll(diagramMembers);
if (todoList != null) {
temp.add(todoList);
}
return temp;
}
private boolean removeDiagram(Diagram d) {
for (ProjectMemberDiagram pmd : diagramMembers) {
if (pmd.getDiagram() == d) {
pmd.remove();
diagramMembers.remove(pmd);
return true;
}
}
LOG.debug("Failed to remove diagram " + d);
return false;
}
public synchronized int size() {
int size = diagramMembers.size();
if (model != null) {
++size;
}
if (todoList != null) {
++size;
}
if (profileConfiguration != null) {
++size;
}
return size;
}
public synchronized boolean contains(Object member) {
if (todoList == member) {
return true;
}
if (model == member) {
return true;
}
if (profileConfiguration == member) {
return true;
}
return diagramMembers.contains(member);
}
public synchronized void clear() {
LOG.info("Clearing members");
if (model != null) {
model.remove();
}
if (todoList != null) {
todoList.remove();
}
if (profileConfiguration != null) {
profileConfiguration.remove();
}
Iterator membersIt = diagramMembers.iterator();
while (membersIt.hasNext()) {
((AbstractProjectMember) membersIt.next()).remove();
}
diagramMembers.clear();
}
/**
* @param type the type of the member
* @return the member of the project
* @deprecated by MVW in V0.25.2: no replacement needed since not used.
* Rationale: this class should ONLY implement List, nothing more.
*/
@Deprecated
public synchronized ProjectMember getMember(Class type) {
if (type == ProjectMemberModel.class) {
return model;
}
if (type == ProjectMemberTodoList.class) {
return todoList;
}
if (type == ProfileConfiguration.class) {
return profileConfiguration;
}
throw new IllegalArgumentException(
"There is no single instance of a " + type.getName() + " member");
}
/**
* @param type the type of the member
* @return the member of the project
* @deprecated by MVW in V0.25.2: no replacement needed since not used.
* Rationale: this class should ONLY implement List, nothing more.
*/
@Deprecated
public synchronized List getMembers(Class type) {
if (type == ProjectMemberModel.class) {
List<ProjectMember> temp = new ArrayList<ProjectMember>(1);
temp.add(model);
return temp;
}
if (type == ProjectMemberTodoList.class) {
List<ProjectMember> temp = new ArrayList<ProjectMember>(1);
temp.add(todoList);
return temp;
}
if (type == ProjectMemberDiagram.class) {
return diagramMembers;
}
if (type == ProfileConfiguration.class) {
List<ProjectMember> temp = new ArrayList<ProjectMember>(1);
temp.add(profileConfiguration);
return temp;
}
throw new IllegalArgumentException(
"There is no single instance of a " + type.getName() + " member");
}
public synchronized ProjectMember get(int i) {
if (model != null) {
if (i == 0) {
return model;
}
--i;
}
if (i == diagramMembers.size()) {
if (todoList != null) {
return todoList;
} else {
return profileConfiguration;
}
}
if (i == (diagramMembers.size() + 1)) {
return profileConfiguration;
}
return diagramMembers.get(i);
}
public synchronized boolean isEmpty() {
return size() == 0;
}
public synchronized ProjectMember[] toArray() {
ProjectMember[] temp = new ProjectMember[size()];
int pos = 0;
if (model != null) {
temp[pos++] = model;
}
for (ProjectMemberDiagram d : diagramMembers) {
temp[pos++] = d;
}
if (todoList != null) {
temp[pos++] = todoList;
}
if (profileConfiguration != null) {
temp[pos++] = profileConfiguration;
}
return temp;
}
private void setTodoList(AbstractProjectMember member) {
LOG.info("Setting todoList to " + member);
todoList = member;
}
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection< ? > arg0) {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection< ? extends ProjectMember> arg0) {
throw new UnsupportedOperationException();
}
public boolean addAll(int arg0, Collection< ? extends ProjectMember> arg1) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection< ? > arg0) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection< ? > arg0) {
throw new UnsupportedOperationException();
}
public ProjectMember set(int arg0, ProjectMember arg1) {
throw new UnsupportedOperationException();
}
public void add(int arg0, ProjectMember arg1) {
throw new UnsupportedOperationException();
}
public ProjectMember remove(int arg0) {
throw new UnsupportedOperationException();
}
public int indexOf(Object arg0) {
throw new UnsupportedOperationException();
}
public int lastIndexOf(Object arg0) {
throw new UnsupportedOperationException();
}
public List<ProjectMember> subList(int arg0, int arg1) {
throw new UnsupportedOperationException();
}
/**
* @return the project member
* @deprecated by MVW in V0.25.2: no replacement needed since not used.
* Rationale: this class should ONLY implement List, nothing more.
*/
@Deprecated
public AbstractProjectMember getProfileConfiguration() {
return profileConfiguration;
}
/**
* @param profileConfig the new profile configuration
* @deprecated by MVW in V0.25.2: no replacement needed since not used.
* Rationale: this class should ONLY implement List, nothing more.
*/
@Deprecated
public void setProfileConfiguration(AbstractProjectMember profileConfig) {
profileConfiguration = profileConfig;
}
}