gt:         Set postset = new HashSet();
context: /*
   * Copyright (c) 2004-2020 The YAWL Foundation. All rights reserved.
   * The YAWL Foundation is a collaboration of individuals and
   * organisations who are committed to improving workflow technology.
   *
   * This file is part of YAWL. YAWL 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.
   *
   * YAWL 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 YAWL. If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.yawlfoundation.yawl.elements.e2wfoj;
  
  import org.yawlfoundation.yawl.elements.*;
  import org.yawlfoundation.yawl.elements.state.YMarking;
  
  import java.util.*;
  
  /**
   *  A Reset net formalisation of a YAWL net.
   *
   **/
  public final class E2WFOJNet {
      private Map _Transitions = new HashMap(100);
      private Map _Places = new HashMap(100);
      private Map _OJ = new HashMap();
      private Map _YOJ = new HashMap();
      private YNet _yNet;
      //testing for optimisation  
      private Set alreadyConsideredMarkings = new HashSet(100);
      private Set _Conditions = new HashSet(100);
   
      
      /**
       * Constructor for Reset net.
       *
       */
      public E2WFOJNet(YNet yNet, YTask orJoin) {
          _yNet = yNet;
          ConvertToResetNet();
          OJRemove(orJoin);
          _OJ = null;
          _YOJ = null;
          _yNet = null;
      }
      
      private E2WFOJNet(){
      	//do nothing
      }
      
      /**
       * The method converts a YAWL net into a Reset net.
       *
       */
      private void ConvertToResetNet(){
      Map netElements = _yNet.getNetElements();
       
       //Generate places
      Iterator netEles = netElements.values().iterator();
      while (netEles.hasNext()) {
              YExternalNetElement nextElement = (YExternalNetElement) netEles.next();
              if (nextElement instanceof YCondition) {
              	RPlace p = new RPlace(nextElement.getID());
              	_Places.put(p.getID(),p);
              	_Conditions.add(nextElement);
          	}
              else if (nextElement instanceof YTask) {
              	RPlace p = new RPlace("p_"+nextElement.getID());
              	_Places.put(p.getID(),p);
              }
      }
   
        
      Map _StartTransitions = new HashMap();
      Map _EndTransitions = new HashMap();
      Iterator netEls = netElements.values().iterator();
      while (netEls.hasNext()) {
              YExternalNetElement next = (YExternalNetElement) netEls.next();
              if (next instanceof YTask){
                 YTask nextElement = (YTask) next;
             //  keepTrackOfTaskTypes(nextElement);
               if (nextElement.getJoinType() == nextElement._AND) 
              {    RTransition t = new RTransition(nextElement.getID()+"_start");
              	 _StartTransitions.put(t.getID(),t);
              	
              	Set pre = nextElement.getPresetElements();
              	Iterator preEls = pre.iterator();
              	while (preEls.hasNext()) {
              		
              	YExternalNetElement preElement = (YExternalNetElement) preEls.next();
              	RFlow inflow = new RFlow((RPlace)_Places.get(preElement.getID()),t);
                  t.setPreset(inflow);
                 
                  RFlow outflow = new RFlow(t,(RPlace)_Places.get("p_"+nextElement.getID()));
                  t.setPostset(outflow);        
   
              	} 
              	 
              }
              else if (nextElement.getJoinType() == nextElement._XOR) {
              	
                 	Set pre = nextElement.getPresetElements();
              	Iterator preEls = pre.iterator();
              	while (preEls.hasNext()) {
              	YExternalNetElement preElement = (YExternalNetElement) preEls.next();
              	RTransition t = new RTransition(nextElement.getID()+"_start^"+preElement.getID());	
              	_StartTransitions.put(t.getID(),t);
              
              	
              	RFlow inflow = new RFlow((RPlace)_Places.get(preElement.getID()),t);
                  t.setPreset(inflow);
                  
                  RFlow outflow = new RFlow(t,(RPlace)_Places.get("p_"+nextElement.getID()));
                  t.setPostset(outflow);        
                 
                 	}
              }	
              else if ( nextElement.getJoinType() == nextElement._OR) {
              	RTransition t = new RTransition(nextElement.getID() +"_start");
              	_StartTransitions.put(t.getID(),t);
              	_OJ.put(t.getID(),t);
              	_YOJ.put(nextElement.getID(),nextElement);
              }
                   
              //T_end            	
              if (nextElement.getSplitType() == nextElement._AND) {
              	RTransition t = new RTransition(nextElement.getID()+"_end");
              	_EndTransitions.put(t.getID(),t);
              	
              	Set post = nextElement.getPostsetElements();
              	Iterator postEls = post.iterator();
              	while (postEls.hasNext()) {
              	YExternalNetElement postElement = (YExternalNetElement) postEls.next();
              	          
              	RFlow inflow = new RFlow((RPlace)_Places.get("p_"+nextElement.getID()),t);
                  t.setPreset(inflow);
                              
                  RFlow outflow = new RFlow(t,(RPlace)_Places.get(postElement.getID()));
                  t.setPostset(outflow);   
              	
              	}
                 	             
                 Set removeSet = new HashSet(nextElement.getRemoveSet());
  	            if (!removeSet.isEmpty())
  	            {  addCancelSet(t,removeSet);
  	            }
           	
              }
                         
              else if (nextElement.getSplitType() == nextElement._XOR) {
              	Set post = nextElement.getPostsetElements();
              	Iterator postEls = post.iterator();
              	while (postEls.hasNext()) {
  	            	YExternalNetElement postElement = (YExternalNetElement) postEls.next();	
  	            	RTransition t = new RTransition(nextElement.getID()+"_end^"+postElement.getID());
  	            	_EndTransitions.put(t.getID(),t);
  	            	
  	         
              	RFlow inflow = new RFlow((RPlace)_Places.get("p_"+nextElement.getID()),t);
                  t.setPreset(inflow);
                  
     		       	RFlow outflow = new RFlow(t,(RPlace)_Places.get(postElement.getID()));
                  t.setPostset(outflow);
  	            	
  	           	Set removeSet = new HashSet(nextElement.getRemoveSet());
  	            if (!removeSet.isEmpty())
  	            {  addCancelSet(t,removeSet);
  	            }
              	}
                         	
          	}
          	
          	 else if (nextElement.getSplitType() == nextElement._OR) {
              	
  	           	 Set xSubSet = new HashSet();
  	        	 Set post = nextElement.getPostsetElements();
  	        	 for (int i=1; i <= post.size(); i++)
  	        	 {  Set subSet = generateCombination(post,i);
  	             	    xSubSet.addAll(subSet);
  	        	 }
  	              	
                 for (Iterator xSubSetEls = xSubSet.iterator(); xSubSetEls.hasNext();) 
                 	 
  	             { 	Set x = (Set) xSubSetEls.next();
  	            	String t_id = "";
  	            	for (Iterator i = x.iterator(); i.hasNext();) {
  	            	 	YExternalNetElement postElement = (YExternalNetElement) i.next();
  	            	  	t_id += postElement.getID()+" "; 
  	            	 }
  	            	             	 
  	            	 RTransition t = new RTransition(nextElement.getID()+"_end^{"+t_id+"}");
  		             _EndTransitions.put(t.getID(),t);
  		            
  		            RFlow inflow = new RFlow((RPlace)_Places.get("p_"+nextElement.getID()),t);
  	                t.setPreset(inflow);
  	           
  	                for (Iterator i = x.iterator(); i.hasNext();) {
  	            	 	YExternalNetElement postElement = (YExternalNetElement) i.next();
  	            	  	 RFlow outflow = new RFlow(t,(RPlace)_Places.get(postElement.getID()));
  	            	  	t.setPostset(outflow);
  	            	}
  	            	
  		            Set removeSet = new HashSet(nextElement.getRemoveSet());
  		            if (!removeSet.isEmpty())
  		            	{  addCancelSet(t,removeSet);
  		            	}
                	}
                	
         	     
             }//inner endif t_end
             
             
           }//endif
      } //endwhile
      _Transitions.putAll(_StartTransitions);
      _Transitions.putAll(_EndTransitions);
       	
      } //endMethod
      
      /**
       * This method is used to generate combinations of markings for 
       * comparison. 
       */
     	private Set generateCombination(Set netElements,int size){
      
      Set subSets = new HashSet();
  	Object[] elements = netElements.toArray();
  	int[] indices;
  	CombinationGenerator x = new CombinationGenerator(elements.length, size);
      while (x.hasMore ()) {
  	  Set combsubSet = new HashSet();
  	  indices = x.getNext ();
  	  for (int i = 0; i < indices.length; i++) { 
  	    combsubSet.add(elements[indices[i]]);
  	  }
  	  subSets.add(combsubSet);
  	}
  	return subSets;
  } 
  
      /**
       *This method is used to associate a cancellation set (RPlaces) with each RTransition.
       *This is the implementation of R.
       */	
      private void addCancelSet(RTransition rt,Set removeSet){
      	
   	  Set removeSetT = new HashSet(removeSet); 
  	  Set removeSetR = new HashSet();
  	  
  	  //For conditions in YAWL net
  	  removeSet.retainAll(_Conditions);
  	  for (Iterator i = removeSet.iterator(); i.hasNext();)
  	  { YExternalNetElement c = (YExternalNetElement) i.next();
  	     RPlace p = (RPlace) _Places.get(c.getID());
  	     if (p != null)
  	     { removeSetR.add(p);
  	     }
  	  }
  	  //For tasks in YAWL net, add p_t
  	  removeSetT.removeAll(_Conditions);
  	  for (Iterator i = removeSetT.iterator(); i.hasNext();)
  	  { YExternalNetElement t = (YExternalNetElement) i.next();
  	     RPlace p = (RPlace)_Places.get("p_"+t.getID());
  	     if (p != null)
  	     { removeSetR.add(p);
  	     }
  	  }   
        rt.setRemoveSet(removeSetR);
       }
      
      /**
       * This method is called with an OR-join task to 
       * prepare for OR-join enabling call.
       *
       **/
      private void OJRemove(YTask j) {
  	
  	//Need to keep track of YAWL net type OJs.
  	_YOJ.remove(j.getID());
  	
  	for (Iterator i = _OJ.values().iterator(); i.hasNext();)
      { RTransition rj = (RTransition) i.next();
        _Transitions.remove(rj.getID());
      }
      
  	//Similar to XOR join
  	for (Iterator i = _YOJ.values().iterator(); i.hasNext();){
  		YExternalNetElement otherOrjoin = (YExternalNetElement) i.next();	
  		Set pre = otherOrjoin.getPresetElements();
  	    Iterator preEls = pre.iterator();
  	    while (preEls.hasNext()) {
  		    YExternalNetElement preElement = (YExternalNetElement) preEls.next();
  		    RTransition t = new RTransition(otherOrjoin.getID()+"_start^"+preElement.getID());	
  		    _Transitions.put(t.getID(),t);
  		    	
  		    RFlow inflow = new RFlow((RPlace)_Places.get(preElement.getID()),t);
  		    t.setPreset(inflow);
  		 
  		    RFlow outflow = new RFlow(t,(RPlace)_Places.get("p_"+otherOrjoin.getID()));
  		    t.setPostset(outflow);        
  	    }
  	}    
         
      }
      
      /**
       * Perform structural restriction of a reset net.
       */
       public void restrictNet(YTask j)
      { 
      
       //All transitions that we are interested in
        Set restrictedTrans = new HashSet();
        Set restrictedPlaces = new HashSet();
        
        Set pre = new HashSet(); //YAWL to reset net conversion 
        Set Ypre = j.getPresetElements();
        for (Iterator iterPlace = Ypre.iterator();iterPlace.hasNext();)
        { YCondition condition = (YCondition) iterPlace.next();    
      	RPlace place = (RPlace) _Places.get(condition.getID());
        	if (place != null)
      	{ pre.add(place);
      	}
        }
       
        Set rk = new HashSet();
        Set trans = getPreset(pre);   
        restrictedTrans.addAll(trans);
        restrictedPlaces.addAll(pre);
        while (!rk.equals(restrictedTrans)){
         	rk = new HashSet(restrictedTrans);
          pre = getPreset(trans);
          trans = getPreset(pre);
          restrictedTrans.addAll(trans);
          restrictedPlaces.addAll(pre);   
        }
            
     performRestriction(restrictedTrans, restrictedPlaces);
           
    }
      
     /**
      * This method is used to perform active projection restriction.
      *
      */ 
    public void restrictNet(YMarking M)
    {   
        Set markedPlaces = new HashSet();
        Set Ymarked = new HashSet(M.getLocations()); 
  
        //Make sure that every condition in M is external
        for (Iterator iterPlace = Ymarked.iterator();iterPlace.hasNext();)
        { YNetElement nextElement = (YNetElement) iterPlace.next();
          if (nextElement instanceof YCondition) {
  	       	RPlace place = (RPlace) _Places.get(nextElement.getID());
  	       	if (place != null)
  	       	{ markedPlaces.add(place);
  	    	 }
  	    }	 
      	//Need to consider active tasks in a marking
      	if (nextElement instanceof YTask){
      	    String internalPlace = "p_"+ nextElement.getID();
           	RPlace place = (RPlace) _Places.get(internalPlace);
            	if (place != null)
            	{
            	 markedPlaces.add(place);
            	 }
      	}
        }	
        
        //Forward pass
        Set restrictedTrans = new HashSet();
        Set restrictedPlaces = new HashSet();
        Set post = new HashSet();
        Set fk = new HashSet();
        Set trans = getPostset(markedPlaces);
        restrictedTrans.addAll(trans);
        restrictedPlaces.addAll(markedPlaces);
        while (!fk.equals(restrictedTrans)){
        	fk = new HashSet(restrictedTrans);
          post = getPostset(trans);
          trans = getPostset(post);
          restrictedTrans.addAll(trans);
          restrictedPlaces.addAll(post);   
        }
                     
        Set TransToRemove = new HashSet(_Transitions.values());
        for (Iterator iterT =TransToRemove.iterator();iterT.hasNext();)
        { RElement tElement = (RElement) iterT.next(); 
          Set preSet = tElement.getPresetElements();
          if (!restrictedPlaces.containsAll(preSet))
          { restrictedTrans.remove(tElement);
          }
        }
           
        performRestriction(restrictedTrans, restrictedPlaces);
        
       }
   
     /**
      * Private method for removing tranisitions and places. Used for both
      * structural restriction and marking dependent restriction.
      *
      */
       private void performRestriction(Set restrictedTrans,Set restrictedPlaces)
     { 
        Set irrelevantTrans = new HashSet(_Transitions.values());
        irrelevantTrans.removeAll(restrictedTrans);	
        for (Iterator iterT = irrelevantTrans.iterator();iterT.hasNext();)
        { RTransition t = (RTransition) iterT.next(); 
          _Transitions.remove(t.getID());
     	
         }
   
        
        for (Iterator iterT = restrictedTrans.iterator();iterT.hasNext();)
        { RTransition t = (RTransition) iterT.next(); 
          if (t.isCancelTransition())
          {
              t.getRemoveSet().retainAll(restrictedPlaces);  // getRemoveSet() guaranteed not null
          }
           
       //Change F remove postset places that are not in P'
        RElement tElement = (RElement)t;
        Set postSetToRemove = new HashSet(tElement.getPostsetElements());
        postSetToRemove.removeAll(restrictedPlaces);
        if (postSetToRemove.size() > 0)
  	   {  Map postSetFlows = new HashMap(tElement.getPostsetFlows());
  	      for (Iterator iterP = postSetToRemove.iterator();iterP.hasNext();)
  		      { RPlace p = (RPlace) iterP.next(); 
  		        postSetFlows.remove(p.getID());
  		      }
  		   tElement.setPostsetFlows(postSetFlows);
  	      }
  	      
  	      
  	  //Change F remove postset places that are not in P'
        Set preSetToRemove = new HashSet(tElement.getPresetElements());
        preSetToRemove.removeAll(restrictedPlaces);
        if (preSetToRemove.size() > 0)
  	   {  Map preSetFlows = new HashMap(tElement.getPresetFlows());
  	      for (Iterator iterP = preSetToRemove.iterator();iterP.hasNext();)
  		      { RPlace p = (RPlace) iterP.next(); 
  		        preSetFlows.remove(p.getID());
  		      }
  		      	tElement.setPresetFlows(preSetFlows);
  	      }
        }
             
       //Remove places that are not part of restrictedNet
        Set irrelevantPlaces = new HashSet(_Places.values());
        irrelevantPlaces.removeAll(restrictedPlaces);	
        for (Iterator iterP = irrelevantPlaces.iterator();iterP.hasNext();)
        { RPlace p = (RPlace) iterP.next(); 
          _Places.remove(p.getID());
       
          
        //Change F - remove preset transitions that are not in T'
        RElement pElement = (RElement)p;
        Set preSetToRemove = new HashSet(pElement.getPresetElements());
        preSetToRemove.removeAll(restrictedTrans);
       if  (preSetToRemove.size() > 0)
  	      {  Map preSetFlows = new HashMap(pElement.getPresetFlows());
  	         for (Iterator iterT = preSetToRemove.iterator();iterT.hasNext();)
  		      { RTransition t = (RTransition) iterT.next(); 
  		        preSetFlows.remove(t.getID());
  		      }
  		      	pElement.setPresetFlows(preSetFlows);
  	      }
     	
     	
     	 Set postSetToRemove = new HashSet(pElement.getPostsetElements());
       postSetToRemove.removeAll(restrictedTrans);
       if  (postSetToRemove.size() > 0)
  	      {  Map postSetFlows = new HashMap(pElement.getPostsetFlows());
  	         for (Iterator iterT = postSetToRemove.iterator();iterT.hasNext();)
  		      { RTransition t = (RTransition) iterT.next(); 
  		        postSetFlows.remove(t.getID());
  		      }
  		      	pElement.setPostsetFlows(postSetFlows);
  	      }
        }
    
    
      }
    private static Set getPostset(Set elements) {
  