private boolean isDiseaseObject(Renderable r, Set<Long> diseaseIds) {
   if (r instanceof FlowLine) {
     FlowLine fl = (FlowLine) r;
     return isFlowLineRelatedToSet(fl, diseaseIds);
   }
   // Assume normal objects only: this is a very strong assumption
   if (r.getReactomeId() == null) return false;
   // A PE may be represented multiple times in a pathway diagram. Some of them
   // are linked to normal reactions, and some linked to disease reactions.
   // Have to check these cases.
   if (r instanceof HyperEdge) return diseaseIds.contains(r.getReactomeId());
   if (r instanceof Node) {
     Node node = (Node) r;
     List<HyperEdge> edges = node.getConnectedReactions();
     boolean isDisease = false;
     for (HyperEdge edge : edges) {
       if (edge instanceof FlowLine) {
         isDisease = isFlowLineRelatedToSet((FlowLine) edge, diseaseIds);
       } else if (edge.getReactomeId() != null && diseaseIds.contains(edge.getReactomeId())) {
         isDisease = true;
       }
       if (isDisease) return true;
     }
   }
   return false;
 }
 private boolean isNormalObject(Renderable r, Set<Long> normalIds) {
   if (r instanceof HyperEdge) {
     if (r instanceof FlowLine) return isFlowLineRelatedToSet((FlowLine) r, normalIds);
     // Most likely the following statements should not be reached. But place
     // here just in case.
     if (r.getReactomeId() == null) return true;
     if (normalIds.contains(r.getReactomeId())) return true;
   } else if (r instanceof Node) {
     if (r instanceof ProcessNode) return true; // Should be used only for normal pathway.
     if (r.getReactomeId() == null) return true;
     // Check if it is linked to another disease entities
     Node node = (Node) r;
     List<HyperEdge> edges = node.getConnectedReactions();
     boolean isNormal = false;
     for (HyperEdge edge : edges) {
       if (edge instanceof FlowLine) isNormal = isFlowLineRelatedToSet((FlowLine) edge, normalIds);
       if (isNormal) return true;
       if (edge.getReactomeId() != null && normalIds.contains(edge.getReactomeId())) return true;
       // Some special cases that use links
       if (!(edge instanceof EntitySetAndEntitySetLink)
           && !(edge instanceof EntitySetAndMemberLink)
           && edge.getReactomeId() == null) return true;
     }
   }
   return false;
 }
 /**
  * Some of disease reactions may not be drawn in the pathway diagram (e.g. LoF or GoF reactions).
  * These reactions should be overlaid onto their normalReaction counterparts, which are encoded by
  * their normalReaction attributes.
  *
  * @param diseaseIds
  */
 private void overlayDiseaseReactions(Set<Long> diseaseIds) {
   // Get the list of all drawing objects for checking
   Map<Long, Renderable> idToObject = new HashMap<Long, Renderable>();
   List<Renderable> components = displayedObject.getComponents();
   if (components == null || components.size() == 0) return;
   for (Renderable r : components) {
     if (r.getReactomeId() == null) continue;
     idToObject.put(r.getReactomeId(), r);
   }
   try {
     normalToDiseaseNode = new HashMap<Node, Node>();
     for (Long diseaseId : diseaseIds) {
       if (idToObject.containsKey(diseaseId)) continue;
       // Have to copy the normal reactions to draw
       GKInstance inst = adaptor.fetchInstance(diseaseId);
       if (inst.getSchemClass().isa(ReactomeJavaConstants.ReactionlikeEvent)) {
         List<GKInstance> normalReactions =
             inst.getAttributeValuesList(ReactomeJavaConstants.normalReaction);
         if (normalReactions != null && normalReactions.size() > 0) {
           for (GKInstance normalRxt : normalReactions) {
             Renderable r = idToObject.get(normalRxt.getDBID());
             if (r instanceof HyperEdge) overlayDiseaseReaction((HyperEdge) r, inst);
           }
         }
       }
     }
     return;
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
 private void checkLossOfFunctionNodes() {
   try {
     lofNodes = new ArrayList<Node>();
     List<Renderable> components = displayedObject.getComponents();
     if (components == null || components.size() == 0) return;
     for (Renderable r : components) {
       if (r instanceof Node || r.getReactomeId() == null) continue;
       if (!diseaseIds.contains(r.getReactomeId())) continue;
       GKInstance inst = adaptor.fetchInstance(r.getReactomeId());
       if (!inst.getSchemClass().isa(ReactomeJavaConstants.ReactionlikeEvent)
           || !inst.getSchemClass().isValidAttribute(ReactomeJavaConstants.entityFunctionalStatus))
         continue;
       List<GKInstance> efs =
           inst.getAttributeValuesList(ReactomeJavaConstants.entityFunctionalStatus);
       Set<GKInstance> lofPEs = new HashSet<GKInstance>();
       for (GKInstance ef : efs) {
         GKInstance pe = (GKInstance) ef.getAttributeValue(ReactomeJavaConstants.physicalEntity);
         if (isLOFEntity(ef)) lofPEs.add(pe);
       }
       List<Node> nodes = ((HyperEdge) r).getConnectedNodes();
       for (Node node : nodes) {
         if (node.getReactomeId() == null) continue;
         GKInstance nodeInst = adaptor.fetchInstance(node.getReactomeId());
         Set<GKInstance> nodeRefEntities = getReferenceEntity(nodeInst);
         for (GKInstance lofPE : lofPEs) {
           Set<GKInstance> lofRefEntities = getReferenceEntity(lofPE);
           lofRefEntities.retainAll(nodeRefEntities);
           if (lofRefEntities.size() > 0) {
             // A LOF node
             lofNodes.add(node);
             break;
           }
         }
       }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
 private Node replaceNormalNode(
     Node normalNode, GKInstance diseaseEntity, Boolean needDashedBorder) {
   Node diseaseNode = normalToDiseaseNode.get(normalNode);
   if (diseaseNode != null) return diseaseNode;
   try {
     // If a node exists already, it should use
     for (Renderable r : diseaseComps) {
       if (diseaseEntity.getDBID().equals(r.getReactomeId()) && r instanceof Node) {
         // This is rather arbitrary: if two nodes are very close,
         // use the existing one.
         int dx = Math.abs(r.getPosition().x - normalNode.getPosition().x);
         int dy = Math.abs(r.getPosition().y - normalNode.getPosition().y);
         if (dx < 10 && dy < 10) {
           // We don't need to create a new Node if it exists already
           normalToDiseaseNode.put(normalNode, (Node) r);
           overlaidObjects.add(r); // Add it to overlaid object to cover edges
           return (Node) r;
         }
       }
     }
     diseaseNode = normalNode.getClass().newInstance();
     RenderUtility.copyRenderInfo(normalNode, diseaseNode);
     // The following should NOT be called since NodeAttachment is
     // related to disease entity only.
     // TODO: Need to support this. Currently it is not supported!!! See example
     // in PI3/AKT cancer pathway.
     // diseaseNode.setNodeAttachmentsLocally(node.getNodeAttachments());
     diseaseNode.setDisplayName(diseaseEntity.getDisplayName());
     diseaseNode.setReactomeId(diseaseEntity.getDBID());
     diseaseNode.invalidateBounds();
     diseaseNode.setRenderer(normalNode.getRenderer());
     diseaseNode.setLineColor(DefaultRenderConstants.DEFAULT_DISEASE_BACKGROUND);
     diseaseNode.setNeedDashedBorder(needDashedBorder);
     RenderUtility.hideCompartmentInNodeName(diseaseNode);
     overlaidObjects.add(diseaseNode);
     displayedObject.addComponent(diseaseNode);
     normalToDiseaseNode.put(normalNode, diseaseNode);
     return diseaseNode;
   } catch (Exception e) {
     e.printStackTrace();
   }
   return null;
 }