law(L,authority(admin),language(java))

authority(admin,keyHash(DC54ACB9FDB939372ACEF66F739C94C5))

public class L extends Law{

     public static final String supervisor = "supervisor@192.168.10.1";
     public static final String auditor = "auditor@192.168.10.2";


     public void adopted(String arg, String[] issuer, String[] subject, String[] attributes) { 
      if (issuer.length != 0) {
            if (issuer[0].equals("admin") && subject[0].equals(Self) && attributes[0].equals("role(supervisor)")) {
                doAdd("role(supervisor)");
		doImposeObligation("failure", 600, "sec");
            }
	    if (issuer[0].equals("admin") && subject[0].equals(Self) && attributes[0].equals("role(leader)")) {
                doAdd("role(leader)");
		doForward(Self, "currentLeader", supervisor);
		doImposeObligation("report", 300, "sec");
            }
	    if (issuer[0].equals("admin") && subject[0].equals(Self) && attributes[0].equals("role(auditor)")) {
                doAdd("role(auditor)");
	    }
	    
	    if (issuer[0].equals("admin") && subject[0].equals(Self) && attributes[0].equals("role(device)")) {
                doAdd("role(device)");
	    }
	    if (issuer[0].equals("admin") && subject[0].equals(Self) && attributes[0].equals("role(officer)")) {
                doAdd("role(officer)");
		doAdd("budget(10)");
            }
        }
      else{
           doQuit();
          }
     }
    
   
    
     public void sent(String source, String message, String dest) {
        if (message.equals("getCS")){
		doDiscloseAllCS();
		return;
	}
	if (message.startsWith("incrementBudget") && CS.has("role(leader)")){
		doForward();	 	
		return;
	}
	if (message.startsWith("decrementBudget") && CS.has("role(leader)")){
		doForward();	 	
		return;
	}
	if (message.startsWith("grantAccess") && CS.has("role(leader)")){
		doForward();	 	
		return;
	}
	if (message.startsWith("repealAccess") && CS.has("role(leader)")){
		doForward();	 	
		return;
	}
	if (message.startsWith("requestInfo") && CS.has("role(leader)")){
		doForward();	 	
		return;
	}
	if (message.startsWith("replyInfo")) {
	 	
		if (CS.has("requestInfo("+dest+")")){
			doRepealObligation("requestInfo("+dest+")");
			doRemove("requestInfo("+dest+")");
			Term terms = CS.deep_clone();
			String newMsg ="reply("+ message + "," + "controlState("+terms.toString() + "))";
			doForward(Self,newMsg,dest);
		}
		else {
			doDeliver(Self,"infoNotRequestedByThisDestination",Self);
		}
		return;
	}
	if (message.equals("stop") && CS.has("role(leader)")) {
		doForward();
		return;
	}
	if (message.startsWith("operation") && CS.has("role(officer)")) {
		if(CS.has("permission("+dest+")")){
			doForward();
			String monitorMessage = "message("+source+","+ message + "," + dest + ")";
			doForward(source, monitorMessage, auditor);
		}
		else {
			doDeliver(Self,"doNotHavePermissionToAccessThisDevice",Self);
		}
		return;
	}
	if (message.startsWith("query") && CS.has("role(leader)") && dest.equals(auditor)) {
		doForward();
		return;
	}
	if (message.startsWith("queryResponse") && source.equals(auditor)) {
		doForward();
		return;
	}
	if (message.equals("appoint") && source.equals(supervisor)) {
		if (CS.has("readyToAppoint")) {
			doRemove("readyToAppoint");
			doAdd("leader("+dest+")");
			doForward();
			return;
		}
	}
	if ((CS.has("role(leader)") || CS.has("role(supervisor)") || CS.has("role(auditor)"))) {
		doForward();
	}
	if (CS.has("role(officer)")) {
		int b = CS.fetchInt("budget");
		if (b > 0) {
			doDecr("budget",1);
			doForward();
		}
		else {
			doDeliver(Self,"msgBlockedDueToInsufficientBudget",Self);
		}
	}
	
    }
	
     public void arrived(String source, String message, String dest) {
        String content = getContentFromMessage(message);
	if (message.startsWith("incrementBudget") && CS.has("role(officer)")) {
            int b = Integer.parseInt(content);
            doIncr("budget", b);
            doDeliver();
            return;
        }
	if (message.startsWith("decrementBudget") && CS.has("role(officer)")) {
            int b = Integer.parseInt(content);
            int b1 = CS.fetchInt("budget");
	    if(b1>b) {
		doDecr("budget", b);
	    }
            else {
	        doDecr("budget", b1);
	    }
            doDeliver();
            return;
        }
	if (message.startsWith("grantAccess") && CS.has("role(officer)")){
		doAdd("permission("+content+")");	 	
		doDeliver();
		return;
	}
	if (message.startsWith("repealAccess") && CS.has("role(officer)")){
		doRemove("permission("+content+")");	 	
		doDeliver();
		return;
	}
	if (message.startsWith("requestInfo") && CS.has("role(officer)")){
		doImposeObligation("requestInfo("+source+")", 60, "sec");
	 	doAdd("requestInfo("+source+")");
		doDeliver();
		return;
	}
	if (message.startsWith("reply")) {
		doDeliver();
		return;
	}
	if (message.startsWith("notResponding")) {
		doDeliver();
		return;
	}
	if (message.equals("stop")) {
		doDeliver();
		doQuit();
	}
	if (message.startsWith("operation")) {
		doDeliver();
		return;
	}
	if (message.startsWith("message")) {
		doDeliver();
		return;
	}
	if (message.startsWith("query")) {
		doDeliver();
		return;
	}
	if (message.startsWith("queryResponse")) {
		doDeliver();
		return;
	}
	if (message.equals("currentLeader") && CS.has("role(supervisor)")) {
		doRepealObligation("failure");
		Term leader = CS.findT("leader(%A)");
		if (leader != null) {
			doReplace(leader.toString(),"leader(" + source + ")");
		}
		else {
			doAdd("leader(" + source + ")");
		} 
		doImposeObligation("failure", 600, "sec");
		return;
	}
	if (message.equals("appoint") && CS.has("role(officer)")) {
		doRemove("role(officer)");
		Term budgetTerm = CS.findT("budget(%A)");
		doRemove(budgetTerm);
		doAdd("role(leader)");
		doImposeObligation("report", 300, "sec");
		doDeliver();
		return;
	}
		doDeliver();
	
    }

    public void obligationDue(Term obligationTerm) {
                
        if (obligationTerm.toString().startsWith("requestInfo")){
		UnifyResult request = CS.find("requestInfo(%S)");
		Term obligationSource = request.getTVar("S");
		doRemove("requestInfo("+obligationSource.toString()+")");
		Term terms = CS.deep_clone();
		String newMsg ="notResponding(controlState("+terms.toString() + "))";
		doForward(Self,newMsg,obligationSource.toString());
	}
	if (obligationTerm.toString().equals("report") && CS.has("role(leader)")) {
		doForward(Self, "currentLeader", supervisor);
		doImposeObligation("report", 300, "sec");
	}
        if (obligationTerm.toString().equals("failure")) {
		doDeliver(Self,"appoint",Self);
		doAdd("readyToAppoint");
		Term leader = CS.findT("leader(%A)");
		if (leader != null) {
			doRemove(leader);
		}
		doImposeObligation("failure", 600, "sec");
	}
    }

    
    public void disconnected() {
	doQuit();
    }
    
    public void exception(Message m, String diagnostic) {
        if ((m.type == Const.FWD) && m.source.equals(Self) && m.s_payload.startsWith("appoint")) {
            doRemove("leader(" + m.dest + ")");
	    doAdd("readyToAppoint");
            doDeliver("law", "exception(" + m.s_payload + ")", Self);
            return;
        }
        doDeliver("law", "exception(type(" + m.type + "),source(" + m.source + "),payload(" + m.s_payload 
            + "),dest(" + m.dest + "),diagnostic(" + diagnostic + "))", Self);
    }


    /**
        Helper method to parse the argument out of a regular expression
    */
    public String getContentFromMessage(String anyMessage) { 

        int index = anyMessage.indexOf("("); 

        if (index == -1) return ""; 
        else return anyMessage.substring(index+1, anyMessage.length()-1); 
    }
}


