[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