S { /* this traversal goes to all the url addresses , it has three visitors Visitor is the main visitor that does all the interpretation and the two other visitors keep track of the repeat and timouts that exists */ traversal Traverse( RepeatCheckingVisitor rv, LimitCheckingVisitor lv, Visitor v){ { S -> { Address , Stall } }; } /*-----------------------------------*/ /* this traversal checks all the time limitations at the begining to see that they are in decending order if they are then interpretation can be done otherwise there could be no interpretation */ traversal TimeTraverse(TimeCheckingVisitor tv) { to Time ; } /*-----------------------------------*/ /* this function is the main function that does the interpretation */ public void run() (@{ Visitor v= new Visitor(); RepeatCheckingVisitor rv = new RepeatCheckingVisitor(); LimitCheckingVisitor lv = new LimitCheckingVisitor(); /* in order to be a comunication between the visitors */ v.set_rv(rv); v.set_lv(lv); rv.set_lv(lv); rv.set_v(v); lv.set_v(v); this.Traverse(rv,lv,v); }@) /*-----------------------------------*/ // this function is responsible to ckeck the decending order of the time //limitations (@ boolean check(){ TimeCheckingVisitor tv = new TimeCheckingVisitor(); this.TimeTraverse(tv); /* depending on what value is returned the interpretation is made or not */ return tv.get_return_val(); }@) } /*---------------------------------------------------------------------*/ // this visitor goes to all the Time_Limit classes and keeps track of the // decending order of time limitations by its two variable "time " and // "pretime" TimeCheckingVisitor{ init (@ flag = 0; // I wanted to give the bigest value to pretime at the // begining but as it is not possible I used a flag for // the first time limitation time = 0; pretime = 0; //if the time limitation is in decending order //then the condition value is true otherwise //it is false condition = true; @) before Time_Limit (@ if (flag == 0) { pretime = host.get_time().get_l() ; flag = 1; } else { time = host.get_time().get_l() ; if ( time > pretime ) condition = false; pretime = time; } @) return boolean (@ condition @) } /*---------------------------------------------------------------------*/ // this visitor controls the repeatitions RepeatCheckingVisitor{ after Repeatition (@ if( v.get_active() && !v.get_concurrent() ) { date = System.currentTimeMillis(); while ( v.get_urlConn() == null && lv.get_limitFlag() && date < ((Long)lv.limitStack.peek()).longValue()) // while url hasn't been accessed yet // while there is a time limitation // while there is still time // run this part again { System.out.println("acording to condition repeations is going to be active in this thread " + Thread.currentThread() ) ; host.get_repeat().run(); date = System.currentTimeMillis(); } if ( v.get_urlConn() == null && ! lv.get_limitFlag() ) // if there is not a time limitation System.out.println("Do not use repeatiton with out time limit in this thread : " + Thread.currentThread() ) ; System.out.println("according to condition repeatition ended in this thread : " + Thread.currentThread()); } @) } /*---------------------------------------------------------------------*/ // this visitor controls the time limitations LimitCheckingVisitor { init (@ limitFlag = false; // a flag that is used to control limitStack // to stop the stack from being used in case it is empty limitStack = new Stack(); // the stack that is used to keep track of time limitations @) before Time_Limit // it gets the time right now and adds it up with the time limit and puts it in the stack // it turns on the flag (@ if( v.get_active() && !v.get_concurrent()) { limitFlag = true; limit = host.get_time().get_l() + System.currentTimeMillis() ; date = new Long(limit); limitStack.push(date); } @) after Time_Limit //it pops one time limit from the stack // it turns off the flag in case the stack becomes empty (@ if( v.get_active() && !v.get_concurrent() ) { limitStack.pop(); if (limitStack.empty()) limitFlag = false; } @) } /*-----------------------------------------------------------------------*/ Visitor { /*-----------------------------------*/ init (@ urlConn = null ; active = true; // a flag that keeps track of the execution of the right branches // because if we have something like S | S then if we get to result // on the left branch there is no need to execute the right branch concurrent = false; // a flag that shows that a branch has been executed by another // thread and there for there is no need for it to be executed again sequentialStack = new Stack(); sequentialStack.push(new Boolean(true)); // it doesn't let the stack to become empty // instead of using a flag for controlling // the condition of the stack concurrentStack = new Stack(); concurrentStack.push(new Boolean(false)); @) /*-----------------------------------*/ //the procedure that reads what the url points to (@ void read(URL urlConn){ try{ // page = new StringBuffer(""); stream = urlConn.openStream(); while (( next = stream.read()) != -1) { System.out.print((char)next); // page.append((char)next); } System.out.println(); } // catch(MalformedURLException e) // {;} catch(IOException e) { // if I/O goes wrong e.printStackTrace(); // complain System.exit(1); // and die } } @) /*-----------------------------------*/ before Basic_Service (@ if (active && !concurrent){ // if there is a need for this part to be executed and if it hasn't been // executed by another thread yet try{ urlConn = new URL(host.get_address().get_string()); } catch(MalformedURLException e) {;} date = System.currentTimeMillis(); if ( urlConn != null ) // if the url pointer has been accessed if ( lv.get_limitFlag() ) // if there is a time limitation // if there is still time if ( date < ((Long)lv.limitStack.peek()).longValue() ) { System.out.println(" this is the content of the following address " +host.get_address().get_string()); read(urlConn); // read the content of the url } else System.out.println(" there is no time left to read the content of the following address in this thread : " + Thread.currentThread() + host.get_address().get_string() ); else // if there is no time limitation { System.out.println(" this is the content of the following address " + host.get_address().get_string()); read(urlConn); // read the content of the url } }@) /*-----------------------------------*/ after Basic_Service (@ if(active && !concurrent) System.out.println("trying to fetch a url pointer ended in this thread :" + Thread.currentThread()); @) /*-----------------------------------*/ before Stall (@ if(active && !concurrent){ System.out.println("waiting for the stall in this thread :" + Thread.currentThread()); date = System.currentTimeMillis(); while (lv.get_limitFlag() && date < ((Long)lv.limitStack.peek()).longValue() ) date = System.currentTimeMillis(); } @) /*-----------------------------------*/ after ->*,first,* (@ if( !concurrent){ if (urlConn == null) // if the url hasn't been fetched yet then the right branch also should // be activated sequentialStack.push(new Boolean(true)); else // if the url has been fetched then there is no need for the right // to be activated sequentialStack.push(new Boolean(false)); } @) /*-----------------------------------*/ before ->*,second,* (@ if( !concurrent) active = ((Boolean)sequentialStack.peek()).booleanValue(); @) /*-----------------------------------*/ after -> *,second,* (@ if( !concurrent) { sequentialStack.pop(); active = ((Boolean)sequentialStack.peek()).booleanValue(); } @) /*-----------------------------------*/ before Concurrent_Execution (@ if(active && !concurrent) { s = new Thread(host.get_thread()); s.start(); } @) /*-----------------------------------*/ after ->*,main,* (@ concurrentStack.push(new Boolean(true)); @) /*-----------------------------------*/ before ->*,thread,* (@ if(active) concurrent = ((Boolean)concurrentStack.peek()).booleanValue(); @) /*-----------------------------------*/ after ->*,thread,* (@ if (active) { concurrentStack.pop(); concurrent =((Boolean)concurrentStack.peek()).booleanValue() ; } @) } /*-----------------------------------------------------------------------*/ Main { (@ static public void main(String args[]) throws Exception { S service = S.parse(System.in); if( service.check() ) { service.run(); System.out.println( " This thread is done : "+ Thread.currentThread() ); } else System.out.println( " Time limitation must be in decending order and Current thread is : " + Thread.currentThread() ); }@)}