[MOBY-guts] biomoby commit
Paul Gordon
gordonp at dev.open-bio.org
Fri Oct 27 20:00:35 UTC 2006
gordonp
Fri Oct 27 16:00:35 EDT 2006
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui
In directory dev.open-bio.org:/tmp/cvs-serv23670/src/main/ca/ucalgary/seahawk/gui
Modified Files:
MobyServicesGUI.java
Log Message:
Improvements to popup-menu hierarchy when there are many, many service options
moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.2,1.3
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2006/10/26 01:31:25 1.2
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2006/10/27 20:00:35 1.3
@@ -22,7 +22,7 @@
public final static String SERVICE_SUBMENU_NAME = "seahawkPopupSubMenuName";
// After this many, subdivide the services for an object into sublists based of service ontology
- public final static int MAX_SERVICES_PER_SUBMENU = 7;
+ public final static int MAX_SERVICES_PER_SUBMENU = 20;
public final static int MAX_SERVICE_DESC_LEN = 100;
public final static String CLIPBOARD_CMD = "clipboard";
/** Always spring MOBY response in a new window if this modifier is present for a click */
@@ -530,48 +530,6 @@
addClipboardItem(submenu, mobyData);
submenu.add(getWaitItem(submenu));
-// MobyService[] foundServices = null;
-// try{
-// mobyData.setXmlMode(MobyDataInstance.CENTRAL_XML_MODE);
-// //logger.debug("Querying central with: " + mobyData.toXML());
-// MobyService templateService = new MobyService("");
-// if(!(mobyData instanceof MobyData)){
-// logger.warn("MobyDataInstance implementer " + mobyData.getClass() +
-// " cannot be used to find services, it does not " +
-// "inherit from MobyData as Central requires");
-// }
-// templateService.addInput((MobyData) mobyData);
-// foundServices = mobyClient.getMobyCentralImpl().findService(templateService);
-// }
-// catch(Exception mobye){
-// logger.error("Could not retrieve list of MobyServices from initialized MobyClient using the " +
-// "MOBY data " + mobyData);mobye.printStackTrace();
-// synchronized(popupList){
-// popupList.setVisible(false);
-// popupList.remove(waitItem);
-// if(submenu.isPopupMenuVisible()){
-// submenu.setPopupMenuVisible(false);
-// submenu.remove(getWaitItem(submenu));
-// submenu.setPopupMenuVisible(true);
-// }
-// else{
-// submenu.remove(getWaitItem(submenu));
-// }
-// popupList.setVisible(true);
-// }
-// return;
-// }
-// if(foundServices == null || foundServices.length == 0){
-// popupList.setVisible(false);
-// return;
-// }
-
-// // Let's make sure all of the services have their service type properly instantiated
-// // for ontology checks later on
-// for(int j = 0; j < foundServices.length; j++){
-// foundServices[j].setServiceType(MobyServiceType.getServiceType(foundServices[j].getServiceType().getName()));
-// }
-
MobyDataServiceAssocInstance serviceAssocObject = null;
// //Services for only the one piece of data
try{
@@ -725,6 +683,140 @@
if(ontologyDepth >= maxOntologyDepth){
// TO DO: for now, a long list will appear instead
//System.err.println("In TODO big sublist ("+ontologyDepth+">="+maxOntologyDepth+")");
+ // Recursively call this method for each type in the ontology at the given depth
+
+ // Make smaller lists based on returned data ontology
+ MobyDataType[][] outputLineages = new MobyDataType[unsortedServices.length][];
+ int maxDataOntologyDepth = 0;
+ for(int i = 0; i < unsortedServices.length; i++){
+ MobyData[] output = unsortedServices[i].getPrimaryOutputs();
+
+ MobyDataType outputType = null;
+ if(output != null && output.length != 0 && output[0] instanceof MobyPrimaryData){
+ outputType = MobyDataType.getDataType(((MobyPrimaryData) output[0]).getDataType().getName());
+ }
+ if(outputType == null){
+ logger.warn("No output data type (ontology) was associated with service " +
+ unsortedServices[i] + ", cannot add to the hierarchical service " +
+ "menus (skipping)");
+ continue;
+ }
+ outputLineages[i] = outputType.getLineage();
+ if(outputLineages[i] == null){
+ logger.debug("No output data type lineage (ontology position) was associated with service type " +
+ outputType + ", cannot add to the hierarchical service " +
+ "menus (skipping)");
+ }
+ else if(outputLineages[i].length > maxOntologyDepth){
+ maxDataOntologyDepth = outputLineages[i].length;
+ }
+ logger.debug("Data lineage for " + unsortedServices[i].getName() +
+ "had length " + outputLineages[i].length);
+ }
+
+ String commonDataAncestorDesc = "";
+ int dataOntologyDepth = 0;
+ breadth_first_data_search: for(; dataOntologyDepth < maxDataOntologyDepth; dataOntologyDepth++){
+ MobyDataType commonOutputType = null;
+ for(int i = 0; i < outputLineages.length; i++){
+ if(outputLineages[i] == null || outputLineages[i].length <= dataOntologyDepth){
+ continue;
+ }
+
+ // Not yet set
+ if(commonOutputType == null){
+ commonOutputType = outputLineages[i][dataOntologyDepth];
+ commonAncestorDesc += outputLineages[i][dataOntologyDepth] + " > ";
+ }
+ // Difference in lineages found, need to split the menu here...
+ else if(!commonOutputType.equals(outputLineages[i][dataOntologyDepth])){
+ break breadth_first_data_search; // labelled break
+ }
+ }
+ }
+ //System.err.println("common ontology depth is " + dataOntologyDepth);
+
+ if(dataOntologyDepth >= maxDataOntologyDepth){
+ // Must separate by name
+ sortServicesByName(unsortedServices);
+ for(int j = 0; j < unsortedServices.length-1;j += MAX_SERVICES_PER_SUBMENU){
+ MobyService[] services = null;
+ if(j+MAX_SERVICES_PER_SUBMENU < unsortedServices.length){ //full slot
+ services = new MobyService[MAX_SERVICES_PER_SUBMENU];
+ System.arraycopy(unsortedServices, j, services, 0, MAX_SERVICES_PER_SUBMENU);
+ }
+ else{
+ services = new MobyService[unsortedServices.length-j];
+ System.arraycopy(unsortedServices, j, services, 0, unsortedServices.length-j);
+ }
+
+ JMenu newMenu = addNameDivSubMenu(submenu, services);
+ MobyDataServiceAssocInstance newMsadi = null;
+ if(msadi instanceof MobyDataXref){
+ newMsadi = new MobyDataXref((MobyDataObject) msadi, services[0]);
+ }
+ else if(msadi instanceof MobyDataObjectSAI){
+ newMsadi = new MobyDataObjectSAI((MobyDataObject) msadi, services);
+ }
+ else if(msadi instanceof MobyDataObjectSetSAI){
+ newMsadi = new MobyDataObjectSetSAI((MobyDataObjectSet) msadi, services);
+ }
+ addServicesToSubMenu(newMenu, newMsadi, handler);
+ }
+ }
+
+ else{
+ // How many submenus do we need?
+ Map<MobyDataType,Vector<MobyService>> outputType2Services =
+ new TreeMap<MobyDataType,Vector<MobyService>>();
+ for(int i = 0; i < outputLineages.length; i++){
+ if(outputLineages[i] == null){
+ continue;
+ }
+ MobyDataType type = null;
+ // Branch
+ if(outputLineages[i].length > dataOntologyDepth){
+ type = outputLineages[i][dataOntologyDepth];
+ }
+ // Leaf
+ else if(dataOntologyDepth >= 1){
+ type = outputLineages[i][outputLineages[i].length-1];
+ }
+ // ?? rootless node?
+ else{
+ type = new MobyDataType("Object (no details)");
+ }
+ MobyService service = unsortedServices[i];
+ // type exists already
+ if(outputType2Services.containsKey(type)){
+ outputType2Services.get(type).add(service);
+ }
+ // otherwise first service of this type
+ else{
+ Vector<MobyService> serviceItems = new Vector<MobyService>();
+ serviceItems.add(service);
+ outputType2Services.put(type, serviceItems);
+ }
+ }
+
+ for(MobyDataType type: outputType2Services.keySet()){
+
+ JMenu newMenu = addOutputTypeSubMenu(submenu, type);
+
+ Vector<MobyService> serviceVector = outputType2Services.get(type);
+ MobyService[] services = serviceVector.toArray(new MobyService[serviceVector.size()]);
+ MobyDataServiceAssocInstance newMsadi = null;
+ if(msadi instanceof MobyDataXref){
+ newMsadi = new MobyDataXref((MobyDataObject) msadi, services[0]);
+ }
+ else if(msadi instanceof MobyDataObjectSAI){
+ newMsadi = new MobyDataObjectSAI((MobyDataObject) msadi, services);
+ }
+ else if(msadi instanceof MobyDataObjectSetSAI){
+ newMsadi = new MobyDataObjectSetSAI((MobyDataObjectSet) msadi, services);
+ }
+ addServicesToSubMenu(newMenu, newMsadi, handler);
+ }}
}
else{
@@ -742,7 +834,7 @@
}
// Leaf
else if(ontologyDepth >= 1){
- type = serviceLineages[i][ontologyDepth-1];
+ type = serviceLineages[i][serviceLineages[i].length-1];
}
// ?? rootless node?
else{
@@ -780,21 +872,21 @@
}
addServicesToSubMenu(newMenu, newMsadi, handler);
}
+ }
- // Causes resizing based on new items
- if(submenu.isPopupMenuVisible()){
- submenu.setPopupMenuVisible(false);
- submenu.remove(getWaitItem(submenu));
- submenu.setPopupMenuVisible(true);
- }
- else{
- submenu.remove(getWaitItem(submenu));
- }
- // If recursed to create more submenus, do not execute the code below,
- // which would add the items to the top level submenu too.
- return;
+ // Causes resizing based on new items
+ if(submenu.isPopupMenuVisible()){
+ submenu.setPopupMenuVisible(false);
+ submenu.remove(getWaitItem(submenu));
+ submenu.setPopupMenuVisible(true);
}
-
+ else{
+ submenu.remove(getWaitItem(submenu));
+ }
+ // If recursed to create more submenus, do not execute the code below,
+ // which would add the items to the top level submenu too.
+ return;
+
}
addHandler(handler);
@@ -900,6 +992,76 @@
return menu;
}
+ protected String getNameStart(MobyService service){
+ String serviceName = service.getName();
+ if(serviceName.length() <= 9){
+ return serviceName;
+ }
+ else{
+ return serviceName.substring(0, 8)+"...";
+ }
+ }
+
+ public JMenu addNameDivSubMenu(JMenu parentMenu, MobyService[] services){
+ if(services == null || services.length == 0){
+ return null;
+ }
+
+ JMenu menu = new JMenu("Service name "+getNameStart(services[0]) + "-"+
+ getNameStart(services[services.length-1])+":");
+ parentMenu.add(menu);
+
+ // The following is to keep track of nested menu parents, which
+ // you can't do directly in Swing (see
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4103931)
+ while(service2submenu.containsKey(parentMenu)){
+ parentMenu = (JMenu) service2submenu.get(parentMenu);
+ }
+
+ // All menus, no matter how nested, point to top submenu that corresponds to the data object
+ service2submenu.put(menu, parentMenu);
+
+ return menu;
+ }
+
+ public JMenu addOutputTypeSubMenu(JMenu parentMenu, MobyDataType type){
+ JMenu menu = new JMenu("Result type: " + type.getName());
+
+ MobyDataType[] typeLineage = type.getLineage();
+ String commonAncestorDesc = "";
+ for(int i = 0; i < typeLineage.length; i++){
+ if(typeLineage == null){
+ commonAncestorDesc = "No details available";
+ break;
+ }
+ commonAncestorDesc += typeLineage[i].getName() + " > ";
+ }
+
+ String desc = type.getDescription();
+ if(desc == null || desc.length() == 0){
+ desc = type.getComment();
+ }
+ String menuToolTip = commonAncestorDesc + desc;
+ if(menuToolTip.length() > MAX_SERVICE_DESC_LEN){
+ // Cut down really long ancestry descs to the last part (most precise)
+ menuToolTip = "..." + menuToolTip.substring(menuToolTip.length()-MAX_SERVICE_DESC_LEN);
+ }
+ menu.setToolTipText(menuToolTip);
+ parentMenu.add(menu);
+
+ // The following is to keep track of nested menu parents, which
+ // you can't do directly in Swing (see
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4103931)
+ while(service2submenu.containsKey(parentMenu)){
+ parentMenu = (JMenu) service2submenu.get(parentMenu);
+ }
+
+ // All menus, no matter how nested, point to top submenu that corresponds to the data object
+ service2submenu.put(menu, parentMenu);
+
+ return menu;
+ }
+
public JMenu createObjectSubMenu(MobyDataInstance mdi){
if(!(mdi instanceof MobyPrimaryData)){
logger.warn("Ignoring non-primary data object submitted to menu creation: " + mdi);
More information about the MOBY-guts
mailing list