/* $Id: SimpleListModel.java 18773 2010-09-20 18:45:08Z bobtarling $
*******************************************************************************
* Copyright (c) 2009 Contributors - see below
* 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:
* Bob Tarling - Original implementation
*******************************************************************************
*/
package org.argouml.core.propertypanels.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import org.argouml.core.propertypanels.model.GetterSetterManager;
import org.argouml.kernel.Command;
import org.argouml.model.AddAssociationEvent;
import org.argouml.model.AttributeChangeEvent;
import org.argouml.model.InvalidElementException;
import org.argouml.model.Model;
import org.argouml.model.RemoveAssociationEvent;
import org.argouml.util.CollectionUtil;
/**
* The simplest model for a list of UML elements
*/
class SimpleListModel
extends DefaultListModel implements PropertyChangeListener {
/**
* The class uid
*/
private static final long serialVersionUID = -8491023641828449064L;
private static final Logger LOG = Logger.getLogger(SimpleListModel.class);
/**
* The metatypes to provide buttons to create
*/
private final List<Class<?>> metaTypes;
private final Object umlElement;
private final String propertyName;
final private GetterSetterManager getterSetterManager;
SimpleListModel(
final String propertyName,
final List<Class<?>> types,
final Object umlElement,
final GetterSetterManager getterSetterManager) {
super();
this.getterSetterManager = getterSetterManager;
metaTypes = types;
this.propertyName = propertyName;
this.umlElement = umlElement;
build();
Model.getPump().addModelEventListener(this, umlElement, propertyName);
}
public void removeModelEventListener() {
Model.getPump().removeModelEventListener(this, umlElement, propertyName);
}
public Object getMetaType() {
if (metaTypes.size() > 0) {
return metaTypes.get(0);
}
return getterSetterManager.getMetaType(propertyName);
}
public String getPropertyName() {
return propertyName;
}
public List getMetaTypes() {
return metaTypes;
}
public Command getRemoveCommand(Object objectToRemove) {
return getterSetterManager.getRemoveCommand(propertyName, umlElement, objectToRemove);
}
public Command getAddCommand() {
return getterSetterManager.getAddCommand(propertyName, umlElement);
}
public List<Command> getAdditionalCommands() {
return getterSetterManager.getAdditionalCommands(propertyName, umlElement);
}
/*
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
*/
public void propertyChange(final PropertyChangeEvent e) {
if (e instanceof RemoveAssociationEvent
|| e instanceof AddAssociationEvent) {
Runnable doWorkRunnable = new Runnable() {
public void run() {
try {
if (getterSetterManager.isFullBuildOnly(
propertyName)) {
removeAllElements();
build();
} else {
if (e instanceof RemoveAssociationEvent) {
final Object objectToRemove =
((RemoveAssociationEvent) e).getChangedValue();
removeElement(objectToRemove);
} else if (e instanceof AddAssociationEvent) {
Object newElement = ((AddAssociationEvent) e).getChangedValue();
boolean typeValid = false;
for (Class<?> cls : metaTypes) {
if (cls.isInstance(newElement)) {
typeValid = true;
}
}
if (typeValid
&& !SimpleListModel.this.contains(newElement)) {
if (Model.getUmlHelper().isMovable(getMetaType())) {
final Collection c =
(Collection) getterSetterManager.getOptions(
umlElement,
propertyName,
metaTypes);
final int index =
CollectionUtil.indexOf(c, newElement);
if (index < 0 || index > getSize() - 1) {
LOG.warn(
"Unable to add element at correct position "
+ index + " added to end instead");
addElement(newElement);
} else {
add(index, newElement);
}
} else {
addElement(newElement);
}
}
}
}
} catch (InvalidElementException e) {
LOG.debug("propertyChange accessed a deleted element ", e);
}
}
};
SwingUtilities.invokeLater(doWorkRunnable);
} else if (e.getPropertyName().equals("baseClass")
&& e.getPropertyName().equals(propertyName)
&& e instanceof AttributeChangeEvent) {
// TODO: We have some quirk that the a baseClass addition or
// removal from a steroetype comes back as an AttributeChangeEvent
// rather than an AssociationChangeEvent. This needs further
// investigation to see if this can be made consistent.
removeAllElements();
build();
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("We are listening for too much here. An event we don't need " + e);
}
}
}
/**
* Delete and rebuild the model list from scratch.
*/
private void build() {
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Getting options for " + umlElement
+ " " + propertyName + " " + metaTypes);
}
final Collection c = (Collection) getterSetterManager.getOptions(
umlElement,
propertyName,
metaTypes);
for (Object o : c) {
addElement(o);
}
} catch (InvalidElementException exception) {
LOG.debug("buildModelList threw exception for target "
+ umlElement + ": "
+ exception);
}
}
public Object getUmlElement() {
return umlElement;
}
}