/*
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;
/**
* Container for a set of Mart AttributeCollections
*
* @author <a href="mailto:dlondon@ebi.ac.uk">Darin London</a>
* @author <a href="mailto:craig@ebi.ac.uk">Craig Melsopp</a>
*/
public class AttributePage extends BaseNamedConfigurationObject {
private boolean hasBrokenGroups = false;
private List attributeGroups = new ArrayList();
private Hashtable attGroupNameMap = new Hashtable();
//cache one AttributeDescription object for call to containsAttributeDescription or getAttributeDescriptionByName
private AttributeDescription lastAtt = null;
private AttributeList lastAttList = null;
//cache one AttributeDescription for call to supports/getAttributeDescriptionByFieldNameTableConstraint
private AttributeDescription lastSupportingAttribute = null;
//cache one AttributeGroup for call to getGroupForAttribute
private AttributeGroup lastGroup = null;
//cache one AttributeCollection for call to getCollectionForAttribute
private AttributeCollection lastColl = null;
private final String outFormatsKey = "outFormats";
private final String maxSelectKey = "maxSelect";
public final int DEFAULTMAXSELECT = 0;
/**
* Copy constructor. Constructs an exact copy of an existing AttributePage.
* @param ap AttributePage to copy.
*/
public AttributePage(AttributePage ap) {
super (ap);
List agroups = ap.getAttributeGroups();
for (int i = 0, n = agroups.size(); i < n; i++) {
Object group = agroups.get(i);
addAttributeGroup( new AttributeGroup( (AttributeGroup) group ));
}
}
/**
* Empty Constructor should really only be used by the DatasetConfigEditor
*/
public AttributePage() {
super();
setAttribute(outFormatsKey, null);
setAttribute(maxSelectKey, null);
}
/**
* Constructor for an AttributePage represented by internalName internally.
*
* @param internalName String name to internally represent the AttributePage
* @throws ConfigurationException when the internalName is null or empty
*/
public AttributePage(String internalName) throws ConfigurationException {
this(internalName, "", "", "","");
}
/**
* Constructor for an AttributePage named internally by internalName, with a
* displayName and described by description.
*
* @param internalName String name to internally represent the AttributePage. Must not be null.
* @param displayName String name to represent the AttributePage
* @param description String description of the AttributePage
* @throws ConfigurationException when the internalName is null or empty
*/
public AttributePage(String internalName, String displayName, String description, String outFormats, String maxSelect) throws ConfigurationException {
super(internalName, displayName, description);
setAttribute(outFormatsKey, outFormats);
setAttribute(maxSelectKey,maxSelect);
}
/**
* Add a single AttributeGroup to the AttributePage.
*
* @param a An AttributeGroup object
*/
public void addAttributeGroup(AttributeGroup a) {
attributeGroups.add(a);
attGroupNameMap.put(a.getInternalName(), a);
}
/**
* Remove an AttributeGroup from the AttributePage
* @param a -- AttributeGroup to be removed.
*/
public void removeAttributeGroup(AttributeGroup a) {
attGroupNameMap.remove(a.getInternalName());
attributeGroups.remove(a);
}
/**
* Insert an AttributeGroup at a particular position within the List of AttributeGroup/DSAttributeGroup objects
* contained in the AttributePage. AttributeGroup/DSAttributeGroup objects at or after this position are shifted right.
* @param position -- position to insert the given AttributeGroup
* @param a -- AttributeGroup to insert.
*/
public void insertAttributeGroup(int position, AttributeGroup a) {
attributeGroups.add(position, a);
attGroupNameMap.put(a.getInternalName(), a);
}
/**
* Insert an AttributeGroup before a specific AttributeGroup/DSAttributeGroup, named by internalName.
* @param internalName -- name of the AttributeGroup/DSAttributeGroup before which the given AttributeGroup should be inserted.
* @param a -- AttributeGroup to insert.
* @throws ConfigurationException when the AttributePage does not contain an AttributeGroup/DSAttributeGroup named by internalName.
*/
public void insertAttributeGroupBeforeAttributeGroup(String internalName, AttributeGroup a) throws ConfigurationException {
if (!attGroupNameMap.containsKey(internalName))
throw new ConfigurationException("AttributePage does not contain AttributeGroup " + internalName + "\n");
insertAttributeGroup( attributeGroups.indexOf( attGroupNameMap.get(internalName) ), a );
}
/**
* Insert an AttributeGroup after a specific AttributeGroup/DSAttributeGroup, named by internalName.
* @param internalName -- name of the AttributeGroup/DSAttributeGroup after which the given AttributeGroup should be inserted.
* @param a -- AttributeGroup to insert.
* @throws ConfigurationException when the AttributePage does not contain an AttributeGroup/DSAttributeGroup named by internalName.
*/
public void insertAttributeGroupAfterAttributeGroup(String internalName, AttributeGroup a) throws ConfigurationException {
if (!attGroupNameMap.containsKey(internalName))
throw new ConfigurationException("AttributePage does not contain AttributeGroup " + internalName + "\n");
insertAttributeGroup( attributeGroups.indexOf( attGroupNameMap.get(internalName) ) + 1, a );
}
/**
* Add a group of AttributeGroup objects at once. Note, subsequent calls
* to addAttributeGroup or setAttributeGroup will add to what has already been added.
*
* @param a an array of AttributeGroup objects
*/
public void addAttributeGroups(AttributeGroup[] a) {
for (int i = 0, n = a.length; i < n; i++) {
attributeGroups.add(a[i]);
attGroupNameMap.put(a[i].getInternalName(), a[i]);
}
}
/**
* Returns a List of AttributeGroup/DSAttributeGroup objects contained in the AttributePage, in the order they were added.
*
* @return A List of AttributeGroup/DSAttributeGroup objects
*/
public List getAttributeGroups() {
//return a copy
return new ArrayList(attributeGroups);
}
/**
* Returns a specific AttributeGroup named by internalName.
*
* @param internalName String name of the requested AttributeGroup
* @return an Object (either AttributeGroup or DSAttributeGroup), or null
*/
public Object getAttributeGroupByName(String internalName) {
if (attGroupNameMap.containsKey(internalName))
return attGroupNameMap.get(internalName);
else
return null;
}
/**
* Check whether the AttributePage contains a particular AttributeGroup named by internalName.
*
* @param internalName String name of the AttributeGroup
* @return boolean, true if AttributePage contains AttributeGroup, false if not
*/
public boolean containsAttributeGroup(String internalName) {
return attGroupNameMap.containsKey(internalName);
}
/**
* Convenience method for non graphical UI. Allows a call against the AttributePage for a particular AttributeDescription.
* Note, it is best to first call containsAttributeDescription,
* as there is a caching system to cache a AttributeDescription during a call to containsAttributeDescription.
*
* @param internalName name of the requested AttributeDescription
* @return AttributeDescription requested, or null
*/
public AttributeDescription getAttributeDescriptionByInternalName(String internalName) {
if (containsAttributeDescription(internalName))
return lastAtt;
else
return null;
}
/**
* Convenience method for non graphical UI. Can determine if the AttributePage contains a specific AttributeDescription.
* As an optimization for initial calls to containsAttributeDescription with an immediate call to getAttributeDescriptionByName if
* found, this method caches the AttributeDescription it has found.
*
* @param internalName name of the requested AttributeDescription
* @return boolean, true if found, false if not.
*/
public boolean containsAttributeDescription(String internalName) {
boolean found = false;
if (lastAtt == null) {
for (Iterator iter = (Iterator) attributeGroups.iterator(); iter.hasNext();) {
Object group = iter.next();
if (group instanceof AttributeGroup && ((AttributeGroup) group).containsAttributeDescription(internalName)) {
lastAtt = ((AttributeGroup) group).getAttributeDescriptionByInternalName(internalName);
found = true;
break;
}
}
} else {
if (lastAtt.getInternalName().equals(internalName))
found = true;
else {
lastAtt = null;
found = containsAttributeDescription(internalName);
}
}
return found;
}
/**
* Convenience method for non graphical UI. Allows a call against the AttributePage for a particular AttributeList.
* Note, it is best to first call containsAttributeList,
* as there is a caching system to cache a AttributeList during a call to containsAttributeList.
*
* @param internalName name of the requested AttributeList
* @return AttributeList requested, or null
*/
public AttributeList getAttributeListByInternalName(String internalName) {
if (containsAttributeList(internalName))
return lastAttList;
else
return null;
}
/**
* Convenience method for non graphical UI. Can determine if the AttributePage contains a specific AttributeList.
* As an optimization for initial calls to containsAttributeList with an immediate call to getAttributeListByName if
* found, this method caches the AttributeList it has found.
*
* @param internalName name of the requested AttributeList
* @return boolean, true if found, false if not.
*/
public boolean containsAttributeList(String internalName) {
boolean found = false;
if (lastAttList == null) {
for (Iterator iter = (Iterator) attributeGroups.iterator(); iter.hasNext();) {
Object group = iter.next();
if (group instanceof AttributeGroup && ((AttributeGroup) group).containsAttributeList(internalName)) {
lastAttList = ((AttributeGroup) group).getAttributeListByInternalName(internalName);
found = true;
break;
}
}
} else {
if (lastAttList.getInternalName().equals(internalName))
found = true;
else {
lastAttList = null;
found = containsAttributeList(internalName);
}
}
return found;
}
/**
* 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 AttributePage 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 AttributePage supports the field and tableConstraint, false otherwise
*/
public boolean supports(String field, String tableConstraint) {
boolean supports = false;
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object element = iter.next();
if (element instanceof AttributeGroup) {
AttributeGroup attgroup = (AttributeGroup) element;
if (attgroup.supports(field, tableConstraint)) {
lastSupportingAttribute = attgroup.getAttributeDescriptionByFieldNameTableConstraint(field, tableConstraint);
supports = true;
break;
}
}
}
return supports;
}
/**
* Convenience method. Returns all of the AttributeDescriptions contained in all of the AttributeGroups.
*
* @return List of AttributeDescription objects
*/
public List getAllAttributeDescriptions() {
List atts = new ArrayList();
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object ag = iter.next();
if (ag instanceof AttributeGroup)
atts.addAll(((AttributeGroup) ag).getAllAttributeDescriptions());
}
return atts;
}
/**
* Returns a AttributeGroup for a particular Attribute Description (AttributeDescription or UIDSAttributeDescription)
* based on its internalName.
*
* @param internalName - String internalname for which a group is requested
* @return AttributeGroup containing Attribute Description with given internalName, or null.
*/
public AttributeGroup getGroupForAttributeDescription(String internalName) {
if (!containsAttributeDescription(internalName))
return null;
else if (lastGroup == null) {
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object groupo = iter.next();
if (groupo instanceof AttributeGroup) {
AttributeGroup group = (AttributeGroup) groupo;
if (group.containsAttributeDescription(internalName)) {
lastGroup = group;
break;
}
}
}
return lastGroup;
} else {
if (lastGroup.getInternalName().equals(internalName))
return lastGroup;
else {
lastGroup = null;
return getGroupForAttributeDescription(internalName);
}
}
}
/**
* Returns a AttributeCollection for a particular Attribute Description (AttributeDescription or UIDSAttributeDescription)
* based on its internalName.
*
* @param internalName - String internalname for which a collection is requested
* @return AttributeCollection object containing Attribute Description with given internalName, or null.
*/
public AttributeCollection getCollectionForAttributeDescription(String internalName) {
if (!containsAttributeDescription(internalName))
return null;
else if (lastColl == null) {
lastColl = getGroupForAttributeDescription(internalName).getCollectionForAttributeDescription(internalName);
return lastColl;
} else {
if (lastColl.getInternalName().equals(internalName))
return lastColl;
else {
lastColl = null;
return getCollectionForAttributeDescription(internalName);
}
}
}
/**
* Convenience method. Returns all of the AttributeLists contained in all of the AttributeGroups.
*
* @return List of AttributeList objects
*/
public List getAllAttributeLists() {
List atts = new ArrayList();
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object ag = iter.next();
if (ag instanceof AttributeGroup)
atts.addAll(((AttributeGroup) ag).getAllAttributeLists());
}
return atts;
}
/**
* Returns a AttributeGroup for a particular Attribute List (AttributeList or UIDSAttributeList)
* based on its internalName.
*
* @param internalName - String internalname for which a group is requested
* @return AttributeGroup containing Attribute List with given internalName, or null.
*/
public AttributeGroup getGroupForAttributeList(String internalName) {
if (!containsAttributeList(internalName))
return null;
else if (lastGroup == null) {
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object groupo = iter.next();
if (groupo instanceof AttributeGroup) {
AttributeGroup group = (AttributeGroup) groupo;
if (group.containsAttributeList(internalName)) {
lastGroup = group;
break;
}
}
}
return lastGroup;
} else {
if (lastGroup.getInternalName().equals(internalName))
return lastGroup;
else {
lastGroup = null;
return getGroupForAttributeList(internalName);
}
}
}
/**
* Returns a AttributeCollection for a particular Attribute List (AttributeList or UIDSAttributeList)
* based on its internalName.
*
* @param internalName - String internalname for which a collection is requested
* @return AttributeCollection object containing Attribute List with given internalName, or null.
*/
public AttributeCollection getCollectionForAttributeList(String internalName) {
if (!containsAttributeList(internalName))
return null;
else if (lastColl == null) {
lastColl = getGroupForAttributeList(internalName).getCollectionForAttributeList(internalName);
return lastColl;
} else {
if (lastColl.getInternalName().equals(internalName))
return lastColl;
else {
lastColl = null;
return getCollectionForAttributeList(internalName);
}
}
}
/**
* Retruns a List of possible Completion names for filters to the MartCompleter command completion system.
* @return List possible completions
*/
public List getCompleterNames() {
List names = new ArrayList();
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object group = iter.next();
if (((BaseNamedConfigurationObject) group).getHidden() != null && ((BaseNamedConfigurationObject) group).getHidden().equals("true")) continue;
if (((BaseNamedConfigurationObject) group).getDisplay() != null && ((BaseNamedConfigurationObject) group).getDisplay().equals("true")) continue;
if (group instanceof AttributeGroup)
names.addAll( ( (AttributeGroup) group).getCompleterNames() );
}
return names;
}
/**
* debug output
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[");
buf.append(super.toString());
buf.append(", AttributeGroups=").append(attributeGroups);
buf.append("]");
return buf.toString();
}
/**
* Allows Equality Comparisons manipulation of AttributePage objects
*/
public boolean equals(Object o) {
return o instanceof AttributePage && hashCode() == ((AttributePage) o).hashCode();
}
public int hashCode() {
int tmp = super.hashCode();
for (Iterator iter = attributeGroups.iterator(); iter.hasNext();) {
Object element = iter.next();
tmp = (31 * tmp) + ((AttributeGroup) element).hashCode();
}
return tmp;
}
/**
* Sets the hasBrokenGroups flag to true, meaning that one or more AttributeGroup Objects
* contain broken AttributeDescriptions.
*/
public void setGroupsBroken() {
hasBrokenGroups = true;
}
/**
* Determine if this AttributePage has broken AttributeGroups.
* @return boolean, true if one or more AttributeGroup Objects contain broken AttributeDescriptions, false otherwise
*/
public boolean hasBrokenGroups() {
return hasBrokenGroups;
}
/**
* True if hasBrokenGroups is true.
* @return boolean
*/
public boolean isBroken() {
return hasBrokenGroups;
}
/**
* Returns the outFormats for this att page.
*
* @return key.
*/
public String getOutFormats() {
return getAttribute(outFormatsKey);
}
/**
* @param key - outFormats for this att page
*/
public void setOutFormats(String outFormats) {
setAttribute(outFormatsKey, outFormats);
}
/**
* 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) {
return DEFAULTMAXSELECT;
}
}
public boolean containsOnlyPointerAttributes() {
boolean ret = true;
List groups = getAttributeGroups();
for (int i = 0, n = groups.size(); i < n; i++) {
AttributeGroup element = (AttributeGroup) groups.get(i);
if (!element.containsOnlyPointerAttributes()) {
ret = false;
break;
}
}
return ret;
}
}