/*
Copyright (C) 2003 EBI, GRL
This library 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.ensembl.mart.lib.config;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author <a href="mailto:dlondon@ebi.ac.uk">Darin London</a>
* @author <a href="mailto:craig@ebi.ac.uk">Craig Melsopp</a>
*/
public class AttributeCollection extends BaseNamedConfigurationObject {
private Logger logger = Logger.getLogger(AttributeCollection.class.getName());
/**
* The default maxSelect is 0, meaning no limit
*/
public final int DEFAULTMAXSELECT = 0;
private boolean hasBrokenAttributes = false;
private List AttributeDescriptions = new ArrayList();
private Hashtable attributeDescriptionNameMap = new Hashtable();
private List AttributeLists = new ArrayList();
private Hashtable attributeListNameMap = new Hashtable();
//cache one AttributeDescription for call to supports/getAttributeDescriptionByFieldNameTableConstraint
private AttributeDescription lastSupportingAttribute = null;
private final String maxSelectKey = "maxSelect";
protected final String enableSelectAllKey = "enableSelectAll";
private final String[] titles = new String[] {
maxSelectKey,
enableSelectAllKey
};
/**
* Copy constructor. Constructs a new AttributeCollection which
* is an exact copy of an existing AttributeCollection.
* @param ac AttributeCollection to copy
*/
public AttributeCollection(AttributeCollection ac) {
super(ac);
List ads = ac.getAttributeDescriptions();
for (int i = 0, n = ads.size(); i < n; i++) {
Object ad = ads.get(i);
if (ad instanceof AttributeDescription)
addAttributeDescription( new AttributeDescription( (AttributeDescription) ad ) );
//else not needed
}
ads = ac.getAttributeLists();
for (int i = 0, n = ads.size(); i < n; i++) {
Object ad = ads.get(i);
if (ad instanceof AttributeList)
addAttributeList( new AttributeList( (AttributeList) ad ) );
//else not needed
}
}
/**
* Empty Constructor should only be used by DatasetConfigEditor.
*
*/
public AttributeCollection() {
super();
for (int i = 0, n = titles.length; i < n; i++) {
setAttribute(titles[i], null); //establishes the order of the keys, and adds all possible attribute titles to getXMLAttributeTitles, even if never set in future
}
}
/**
* Constructor for an AttributeCollection named by internalName, with a type.
*
* @param internalName String name to internally represent the AttributeCollection. Must not be null
* @param maxSelect String maximum allowable combined attribute selections. 0 means no limit.
* @throws ConfigurationException when the required values are null or empty.
*/
public AttributeCollection(String internalName) throws ConfigurationException {
this(internalName, "0", "", "", "");
}
/**
* Constructor for a AttributeCollection named by internalName, with a displayName, type and maxSelect value.
* May have description description.
*
* @param internalName String name to internally represent the AttributeCollection. Must not be null
* @param maxSelect String maximum allowable combined attribute selections. 0 means no limit.
* @param displayName String name to represent the AttributeCollection.
* @param description String description of the AttributeCollection
* @throws ConfigurationException if required parameters are null or empty, and if Integer.parseInt(maxSelect) throws a NumberFormatException .
*/
public AttributeCollection(String internalName, String maxSelect, String displayName, String description, String enableSelectAll) throws ConfigurationException {
super( internalName, displayName, description);
setAttribute(maxSelectKey, maxSelect);
setAttribute(enableSelectAllKey, enableSelectAll);
}
/**
* Set the maxSelect value for this AttributeCollection
* @param maxSelect -- String value to limit selections of Attributes in groups. 0 means no limit.
*/
public void setMaxSelect(String maxSelect){
setAttribute(maxSelectKey, maxSelect);
}
public String getMaxSelectString() {
return getAttribute(maxSelectKey);
}
/**
* Returns the maxSelect value for attributes in this AttributeCollection.
* If the value for maxSelect provided is not a valid int (eg.
* Integer.parseInt( maxSelect) throws a NumberFormatException)
* this method returns DEFAULTMAXSELECT.
*
* @return int maxSelect value
*/
public int getMaxSelect() {
try {
return Integer.parseInt( getAttribute(maxSelectKey) );
} catch (NumberFormatException e) {
if (logger.isLoggable(Level.FINE))
logger.fine("maxSelect value " + getAttribute(maxSelectKey) + " could not be parsed into an int: " + e.getMessage());
return DEFAULTMAXSELECT;
}
}
/**
* Add a AttributeDescription to the AtttributeCollection.
*
* @param a a AttributeDescription object.
*/
public void addAttributeDescription(AttributeDescription a) {
AttributeDescriptions.add(a);
attributeDescriptionNameMap.put(a.getInternalName(), a);
}
/**
* Remove an AttributeDescription from this AttributeCollection.
* @param a -- AttributeDescription to be removed.
*/
public void removeAttributeDescription(AttributeDescription a) {
attributeDescriptionNameMap.remove(a.getInternalName());
AttributeDescriptions.remove(a);
}
/**
* Insert an AttributeDescription at a particular position within the AttributeCollection.
* AttributeDescriptions set at or after the given position are shift right.
* @param position -- position at which to insert the given AttributeDescription
* @param a -- AttributeDescription to insert
*/
public void insertAttributeDescription(int position, AttributeDescription a) {
AttributeDescriptions.add(position, a);
attributeDescriptionNameMap.put(a.getInternalName(), a);
}
/**
* Insert an AttributeDescription before a specific AttributeDescription, named by internalName.
* @param internalName -- AttributeDescription before which the given AttributeDescription should be inserted.
* @param a -- AttributeDescription to insert.
* @throws ConfigurationException when the AttributeCollection does not contain an AttributeDescription named by internalName.
*/
public void insertAttributeDescriptionBeforeAttributeDescription(String internalName, AttributeDescription a) throws ConfigurationException {
if (!attributeDescriptionNameMap.containsKey(internalName))
throw new ConfigurationException("AttributeCollection does not contain AttributeDescription " + internalName + "\n");
insertAttributeDescription( AttributeDescriptions.indexOf( attributeDescriptionNameMap.get(internalName) ), a );
}
/**
* Insert an AttributeDescription after a specific AttributeDescription, named by internalName.
* @param internalName -- AttributeDescription after which the given AttributeDescription should be inserted.
* @param a -- AttributeDescription to insert.
* @throws ConfigurationException when the AttributeCollection does not contain an AttributeDescription named by internalName.
*/
public void insertAttributeDescriptionAfterAttributeDescription(String internalName, AttributeDescription a) throws ConfigurationException {
if (!attributeDescriptionNameMap.containsKey(internalName))
throw new ConfigurationException("AttributeCollection does not contain AttributeDescription " + internalName + "\n");
insertAttributeDescription( AttributeDescriptions.indexOf( attributeDescriptionNameMap.get(internalName) ) + 1, a );
}
/**
* Add a group of AttributeDescription objects in one call. Note, subsequent calls to addAttributeDescription or addAttributeDescriptions
* will add to what was added before.
*
* @param a an Array of AttributeDescription objects.
*/
public void addAttributeDescriptions(AttributeDescription[] a) {
for (int i = 0, n = a.length; i < n; i++) {
AttributeDescriptions.add(a[i]);
attributeDescriptionNameMap.put(a[i].getInternalName(), a[i]);
}
}
/**
* Returns a List of AttributeDescription objects, in the order they were added.
*
* @return List of AttributeDescription objects.
*/
public List getAttributeDescriptions() {
//return a copy
return new ArrayList(AttributeDescriptions);
}
/**
* Get a specific AttributeDescription, named by internalName.
*
* @param internalName name of the requested AttributeDescription
* @return AttributeDescription requested, or null
*/
public AttributeDescription getAttributeDescriptionByInternalName(String internalName) {
if ( containsAttributeDescription(internalName) )
return (AttributeDescription) attributeDescriptionNameMap.get(internalName);
else
return null;
}
/**
* Check if this AttributeCollection contains a specific AttributeDescription named
* by internalName.
*
* @param internalName name of the requested AttributeDescription object
* @return boolean, true if found, false if not.
*/
public boolean containsAttributeDescription(String internalName) {
return attributeDescriptionNameMap.containsKey(internalName);
}
/**
* Retrieve a specific AttributeDescription that supports a given field and tableConstraint.
* @param field
* @param tableConstraint
* @return AttributeDescription supporting the field and tableConstraint, or null
*/
public AttributeDescription getAttributeDescriptionByFieldNameTableConstraint(String field, String tableConstraint) {
if (supports(field, tableConstraint))
return lastSupportingAttribute;
else
return null;
}
/**
* Determine if this AttributeCollection supports a given field and tableConstraint. Caches the first supporting AttributeDescription
* that it finds, for subsequent call to getAttributeDescriptionByFieldNameTableConstraint.
* @param field
* @param tableConstraint
* @return boolean, true if an AttributeDescription contained in this AttributeCollection supports the field and tableConstraint, false otherwise
*/
public boolean supports(String field, String tableConstraint) {
boolean supports = false;
for (Iterator iter = AttributeDescriptions.iterator(); iter.hasNext();) {
AttributeDescription element = (AttributeDescription) iter.next();
if (element.supports(field, tableConstraint)) {
lastSupportingAttribute = element;
supports = true;
break;
}
}
return supports;
}
/**
* Add a AttributeList to the AtttributeCollection.
*
* @param a a AttributeList object.
*/
public void addAttributeList(AttributeList a) {
AttributeLists.add(a);
attributeListNameMap.put(a.getInternalName(), a);
}
/**
* Remove an AttributeList from this AttributeCollection.
* @param a -- AttributeList to be removed.
*/
public void removeAttributeList(AttributeList a) {
attributeListNameMap.remove(a.getInternalName());
AttributeLists.remove(a);
}
/**
* Insert an AttributeList at a particular position within the AttributeCollection.
* AttributeLists set at or after the given position are shift right.
* @param position -- position at which to insert the given AttributeList
* @param a -- AttributeList to insert
*/
public void insertAttributeList(int position, AttributeList a) {
AttributeLists.add(position, a);
attributeListNameMap.put(a.getInternalName(), a);
}
/**
* Insert an AttributeList before a specific AttributeList, named by internalName.
* @param internalName -- AttributeList before which the given AttributeList should be inserted.
* @param a -- AttributeList to insert.
* @throws ConfigurationException when the AttributeCollection does not contain an AttributeList named by internalName.
*/
public void insertAttributeListBeforeAttributeList(String internalName, AttributeList a) throws ConfigurationException {
if (!attributeListNameMap.containsKey(internalName))
throw new ConfigurationException("AttributeCollection does not contain AttributeList " + internalName + "\n");
insertAttributeList( AttributeLists.indexOf( attributeListNameMap.get(internalName) ), a );
}
/**
* Insert an AttributeList after a specific AttributeList, named by internalName.
* @param internalName -- AttributeList after which the given AttributeList should be inserted.
* @param a -- AttributeList to insert.
* @throws ConfigurationException when the AttributeCollection does not contain an AttributeList named by internalName.
*/
public void insertAttributeListAfterAttributeList(String internalName, AttributeList a) throws ConfigurationException {
if (!attributeListNameMap.containsKey(internalName))
throw new ConfigurationException("AttributeCollection does not contain AttributeList " + internalName + "\n");
insertAttributeList( AttributeLists.indexOf( attributeListNameMap.get(internalName) ) + 1, a );
}
/**
* Add a group of AttributeList objects in one call. Note, subsequent calls to addAttributeList or addAttributeLists
* will add to what was added before.
*
* @param a an Array of AttributeList objects.
*/
public void addAttributeLists(AttributeList[] a) {
for (int i = 0, n = a.length; i < n; i++) {
AttributeLists.add(a[i]);
attributeListNameMap.put(a[i].getInternalName(), a[i]);
}
}
/**
* Returns a List of AttributeList objects, in the order they were added.
*
* @return List of AttributeList objects.
*/
public List getAttributeLists() {
//return a copy
return new ArrayList(AttributeLists);
}
/**
* Get a specific AttributeList, named by internalName.
*
* @param internalName name of the requested AttributeList
* @return AttributeList requested, or null
*/
public AttributeList getAttributeListByInternalName(String internalName) {
if ( containsAttributeList(internalName) )
return (AttributeList) attributeListNameMap.get(internalName);
else
return null;
}
/**
* Check if this AttributeCollection contains a specific AttributeList named
* by internalName.
*
* @param internalName name of the requested AttributeList object
* @return boolean, true if found, false if not.
*/
public boolean containsAttributeList(String internalName) {
return attributeListNameMap.containsKey(internalName);
}
/**
* Returns a List of possible internalNames to add to the MartCompleter command completion system.
* @return List of possible completions.
*/
public List getCompleterNames() {
List names = new ArrayList();
for (Iterator iter = AttributeDescriptions.iterator(); iter.hasNext();) {
AttributeDescription element = (AttributeDescription) iter.next();
if (element.getHidden() != null && element.getHidden().equals("true")) continue;
if (element.getDisplay() != null && element.getDisplay().equals("true")) continue;
//skip placeholders
if ( !(element.getInternalName().indexOf('.') > 0) )
names.add(element.getInternalName());
}
for (Iterator iter = AttributeLists.iterator(); iter.hasNext();) {
AttributeList element = (AttributeList) iter.next();
if (element.getHidden() != null && element.getHidden().equals("true")) continue;
if (element.getDisplay() != null && element.getDisplay().equals("true")) continue;
//skip placeholders
if ( !(element.getInternalName().indexOf('.') > 0) )
names.add(element.getInternalName());
}
return names;
}
/**
* Returns a List of possible internalNames to add to the MartCompleter command completion system.
* @return List of possible completions.
*/
public List getHiddenCompleterNames() {
List names = new ArrayList();
for (Iterator iter = AttributeDescriptions.iterator(); iter.hasNext();) {
AttributeDescription element = (AttributeDescription) iter.next();
names.add(element.getInternalName());
}
for (Iterator iter = AttributeLists.iterator(); iter.hasNext();) {
AttributeList element = (AttributeList) iter.next();
names.add(element.getInternalName());
}
return names;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[");
buf.append( super.toString() );
buf.append(", AttributeDescriptions=").append(AttributeDescriptions);
buf.append(", AttributeLists=").append(AttributeLists);
buf.append("]");
return buf.toString();
}
/**
* Allows Equality Comparisons manipulation of AttributeCollection objects
*/
public boolean equals(Object o) {
return o instanceof AttributeCollection && hashCode() == ((AttributeCollection) o).hashCode();
}
public int hashCode() {
int tmp = super.hashCode();
for (Iterator iter = AttributeDescriptions.iterator(); iter.hasNext();) {
AttributeDescription element = (AttributeDescription) iter.next();
tmp = (31 * tmp) + element.hashCode();
}
for (Iterator iter = AttributeLists.iterator(); iter.hasNext();) {
AttributeList element = (AttributeList) iter.next();
tmp = (31 * tmp) + element.hashCode();
}
return tmp;
}
/**
* Sets the hasBrokenAttributes flag to true, meaning that one or more AttributeDescription objects
* contains invalid field or tableConstraint references to a particular Mart instance.
*/
public void setAttributesBroken() {
hasBrokenAttributes = true;
}
/**
* Determine if this AttributeCollection contains broken AttributeDescriptions
* @return boolean, true if one or more AttributeDescription objects are broken, false otherwise
*/
public boolean hasBrokenAttributes() {
return hasBrokenAttributes;
}
/**
* True if hasBrokenAttributes is true.
* @return boolean
*/
public boolean isBroken() {
return hasBrokenAttributes;
}
public boolean containsOnlyPointerAttributes() {
boolean ret = true;
List atts = getAttributeDescriptions();
for (int i = 0, n = atts.size(); i < n; i++) {
AttributeDescription element = (AttributeDescription) atts.get(i);
if (element.getInternalName().indexOf('.') < 1) {
ret = false;
break;
}
}
atts = getAttributeLists();
for (int i = 0, n = atts.size(); i < n; i++) {
AttributeList element = (AttributeList) atts.get(i);
if (element.getInternalName().indexOf('.') < 1) {
ret = false;
break;
}
}
return ret;
}
public void setEnableSelectAll(String value) {
setAttribute(enableSelectAllKey, value);
}
public String getEnableSelectAll() {
return getAttribute(enableSelectAllKey);
}
}