requests-simulator

fixed getStoreValue from an array by replacing positions to

4/10/2021 10:01:48 PM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Executor.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Executor.java
index d431c5c..6a7c443 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Executor.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Executor.java
@@ -5,30 +5,27 @@
  */
 package br.ufrgs.inf.prosoft.requestssimulator;
 
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.List;
 import java.util.stream.Collectors;
 
 /**
- *
  * @author romulo
  */
 public class Executor {
 
-    private static final Logger LOGGER = Logger.getLogger(Executor.class.getName());
+  private static final Logger LOGGER = Logger.getLogger(Executor.class.getName());
 
-    public static final void execute(List<Profile> profiles) {
-        List<Thread> threads = profiles.stream().map(profile -> new Thread(() -> {
-            profile.execute();
-        })).collect(Collectors.toList());
-        threads.forEach(Thread::start);
-        threads.forEach(thread -> {
-            try {
-                thread.join();
-            } catch (InterruptedException ex) {
-                LOGGER.log(Level.SEVERE, null, ex);
-            }
-        });
-    }
+  public static void execute(List<Profile> profiles) {
+    List<Thread> threads = profiles.stream().map(profile -> new Thread(profile::execute)).collect(Collectors.toList());
+    threads.forEach(Thread::start);
+    threads.forEach(thread -> {
+      try {
+        thread.join();
+      } catch (InterruptedException ex) {
+        LOGGER.log(Level.SEVERE, null, ex);
+      }
+    });
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
index 0eda719..0cca9c0 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Main.java
@@ -6,95 +6,91 @@
 package br.ufrgs.inf.prosoft.requestssimulator;
 
 import br.ufrgs.inf.prosoft.requestssimulator.requests.Request;
+
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 /**
- *
  * @author romulo
  */
 public class Main {
 
-    public static void main(String[] args) {
-        System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [RequestsSimulator] %5$s %n");
+  public static void main(String[] args) {
+    System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [RequestsSimulator] %5$s %n");
 
-        if (args.length < 2) {
-            System.err.println("--profile=<ProfilePath> --time=<time> [--users=<users>] [--log=<LogPath>] [--throughput=<ThroughputPath>] [--host=<host>] [--home=<homePath>]");
-            System.err.println("--profile=<ProfilePath> --execute=<LogPath> [--throughput=<ThroughputPath>] [--host=<host>] [--home=<homePath>]");
-            System.err.println("--throughput=<ThroughputPath> --reduce=<ReducePath> --prefix=<prefix>");
-            System.exit(1);
-        }
+    if (args.length < 2) {
+      System.err.println("--profile=<ProfilePath> --time=<time> [--users=<users>] [--log=<LogPath>] [--throughput=<ThroughputPath>] [--host=<host>] [--home=<homePath>]");
+      System.err.println("--profile=<ProfilePath> --execute=<LogPath> [--throughput=<ThroughputPath>] [--host=<host>] [--home=<homePath>]");
+      System.err.println("--throughput=<ThroughputPath> --reduce=<ReducePath> --prefix=<prefix>");
+      System.exit(1);
+    }
 
-        Map<String, String> arguments = Stream.of(args).map(arg -> {
-            arg = arg.replaceFirst("--", "");
-            int indexOf = arg.indexOf("=");
-            if (indexOf == -1) {
-                return new String[]{arg, ""};
-            }
-            return new String[]{arg.substring(0, indexOf), arg.substring(indexOf + 1)};
-        }).collect(Collectors.toMap(array -> {
-            return array[0];
-        }, array -> {
-            return array[1];
-        }));
+    Map<String, String> arguments = Stream.of(args).map(arg -> {
+      arg = arg.replaceFirst("--", "");
+      int indexOf = arg.indexOf("=");
+      if (indexOf == -1) {
+        return new String[]{arg, ""};
+      }
+      return new String[]{arg.substring(0, indexOf), arg.substring(indexOf + 1)};
+    }).collect(Collectors.toMap(array -> array[0], array -> array[1]));
 
-        String reducePath = arguments.get("reduce");
-        String throughputPath = arguments.get("throughput");
-        String prefix = arguments.get("prefix");
-        if (reducePath != null) {
-            if (throughputPath == null) {
-                System.err.println("<ThroughputPath> is required");
-                System.exit(1);
-            }
-            if (prefix == null) {
-                System.err.println("<prefix> is required");
-                System.exit(1);
-            }
-            Reducer.reduce(throughputPath, reducePath, prefix);
-            System.exit(0);
-        }
+    String reducePath = arguments.get("reduce");
+    String throughputPath = arguments.get("throughput");
+    String prefix = arguments.get("prefix");
+    if (reducePath != null) {
+      if (throughputPath == null) {
+        System.err.println("<ThroughputPath> is required");
+        System.exit(1);
+      }
+      if (prefix == null) {
+        System.err.println("<prefix> is required");
+        System.exit(1);
+      }
+      Reducer.reduce(throughputPath, reducePath, prefix);
+      System.exit(0);
+    }
 
-        String host = arguments.get("host");
-        if (host == null) {
-            host = "localhost";
-        }
+    String host = arguments.get("host");
+    if (host == null) {
+      host = "localhost";
+    }
 
-        String profilePath = arguments.get("profile");
-        if (profilePath == null) {
-            System.err.println("<profile> is required");
-            System.exit(1);
-        }
-        Profile profile = ProfileReader.parseFile(profilePath, host);
+    String profilePath = arguments.get("profile");
+    if (profilePath == null) {
+      System.err.println("<profile> is required");
+      System.exit(1);
+    }
+    Profile profile = ProfileReader.parseFile(profilePath, host);
 
-        String homePath = arguments.get("home");
-        if (homePath != null) {
-            Request.HOME_PATH = homePath;
-        }
+    String homePath = arguments.get("home");
+    if (homePath != null) {
+      Request.HOME_PATH = homePath;
+    }
 
-        Request.REQUESTS_LOG = throughputPath;
-        String logPath = arguments.get("execute");
-        if (logPath != null) {
-            List<Profile> profiles = LogReader.parseFile(logPath, profile);
-            Executor.execute(profiles);
-            System.exit(0);
-        }
+    Request.REQUESTS_LOG = throughputPath;
+    String logPath = arguments.get("execute");
+    if (logPath != null) {
+      List<Profile> profiles = LogReader.parseFile(logPath, profile);
+      Executor.execute(profiles);
+      System.exit(0);
+    }
 
-        long time = 0;
-        try {
-            time = Long.valueOf(arguments.get("time"));
-        } catch (NumberFormatException ex) {
-            System.err.println("<time> must be a number");
-            System.exit(1);
-        }
-        int users = 1;
-        try {
-            users = Integer.valueOf(arguments.get("users"));
-        } catch (NumberFormatException ex) {
-            System.out.println("<users> not informed. Using default " + users);
-        }
-        logPath = arguments.get("log");
-        Simulator.simulate(profile, time, users, logPath);
+    long time = 0;
+    try {
+      time = Long.parseLong(arguments.get("time"));
+    } catch (NumberFormatException ex) {
+      System.err.println("<time> must be a number");
+      System.exit(1);
+    }
+    int users = 1;
+    try {
+      users = Integer.parseInt(arguments.get("users"));
+    } catch (NumberFormatException ex) {
+      System.out.println("<users> not informed. Using default " + users);
     }
+    logPath = arguments.get("log");
+    Simulator.simulate(profile, time, users, logPath);
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
index 8ab43c2..90c04d0 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
@@ -6,81 +6,72 @@
 package br.ufrgs.inf.prosoft.requestssimulator;
 
 import br.ufrgs.inf.prosoft.requestssimulator.requests.RequestPlan;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+
+import java.util.*;
 import java.util.stream.Stream;
 
 /**
- *
  * @author romulo
  */
 public class Profile {
 
-    private final Collection<RequestPlan> roots;
-    private final Map<String, RequestPlan> urlHasRequestPlan;
-    private final List<Session> sessions;
+  private final Collection<RequestPlan> roots;
+  private final Map<String, RequestPlan> urlHasRequestPlan;
+  private final List<Session> sessions;
 
-    public Profile(Map<String, RequestPlan> urlHasRequestPlan) {
-        this.urlHasRequestPlan = urlHasRequestPlan;
-        Map<String, RequestPlan> rootsReferences = new HashMap<>(this.urlHasRequestPlan);
-        this.urlHasRequestPlan.forEach((reference, requestPlan) -> {
-            if (reference.charAt(0) == '*') {
-                rootsReferences.remove(reference);
-                return;
-            }
-            if (requestPlan.links().count() == 0) {
-                rootsReferences.remove(reference);
-                return;
-            }
-            requestPlan.links().forEach(linkReference -> {
-                rootsReferences.remove(linkReference.getReference());
-            });
-        });
-        this.roots = rootsReferences.values();
-        this.sessions = new ArrayList<>();
-    }
+  public Profile(Map<String, RequestPlan> urlHasRequestPlan) {
+    this.urlHasRequestPlan = urlHasRequestPlan;
+    Map<String, RequestPlan> rootsReferences = new HashMap<>(this.urlHasRequestPlan);
+    this.urlHasRequestPlan.forEach((reference, requestPlan) -> {
+      if (reference.charAt(0) == '*') {
+        rootsReferences.remove(reference);
+        return;
+      }
+      if (requestPlan.links().count() == 0) {
+        rootsReferences.remove(reference);
+        return;
+      }
+      requestPlan.links().forEach(linkReference -> rootsReferences.remove(linkReference.getReference()));
+    });
+    this.roots = rootsReferences.values();
+    this.sessions = new ArrayList<>();
+  }
 
-    public Profile(List<Session> sessions) {
-        this.sessions = sessions;
-        this.roots = null;
-        this.urlHasRequestPlan = null;
-    }
+  public Profile(List<Session> sessions) {
+    this.sessions = sessions;
+    this.roots = null;
+    this.urlHasRequestPlan = null;
+  }
 
-    public Stream<Session> sessions() {
-        return this.sessions.stream();
-    }
+  public Stream<Session> sessions() {
+    return this.sessions.stream();
+  }
 
-    public Session newSession() {
-        Session session = new Session(this.roots);
-        this.sessions.add(session);
-        return session;
-    }
+  public Session newSession() {
+    Session session = new Session(this.roots);
+    this.sessions.add(session);
+    return session;
+  }
 
-    public RequestPlan getRequestPlan(String requestPlanReference) {
-        return this.urlHasRequestPlan.get(requestPlanReference);
-    }
+  public RequestPlan getRequestPlan(String requestPlanReference) {
+    return this.urlHasRequestPlan.get(requestPlanReference);
+  }
 
-    public void simulate(long time) {
-        long end = System.currentTimeMillis() + time;
-        while (System.currentTimeMillis() < end) {
-            newSession().simulate();
-        }
-    }
+  public void simulate(long time) {
+    long end = System.currentTimeMillis() + time;
+    while (System.currentTimeMillis() < end) newSession().simulate();
+  }
 
-    public void execute() {
-        for (Iterator<Session> iterator = this.sessions.iterator(); iterator.hasNext();) {
-            Session session = iterator.next();
-            session.execute();
-            iterator.remove();
-        }
+  public void execute() {
+    for (Iterator<Session> iterator = this.sessions.iterator(); iterator.hasNext(); ) {
+      Session session = iterator.next();
+      session.execute();
+      iterator.remove();
     }
+  }
 
-    @Override
-    protected Profile clone() {
-        return new Profile(this.urlHasRequestPlan);
-    }
+  @Override
+  protected Profile clone() {
+    return new Profile(this.urlHasRequestPlan);
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
index 6af14e1..2b1b6fd 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
@@ -10,9 +10,9 @@ import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+
 import java.io.FileWriter;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -25,317 +25,272 @@ import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 /**
- *
  * @author romulo
  */
 public abstract class Request {
 
-    private final RequestPlan requestPlan;
-    private final String URL;
-    private final String headers;
-    private final Collection<String> storeFields;
-    private final Session session;
-    public static String REQUESTS_LOG = null;
-    public static String HOME_PATH = "";
-
-    protected Request(RequestPlan requestPlan, Session session, String URL) {
-        this.requestPlan = requestPlan;
-        this.session = session;
-        this.URL = URL;
-        this.headers = null;
-        this.storeFields = null;
-    }
-
-    protected Request(RequestPlan requestPlan, Session session, String URL, Collection<String> storeFields) {
-        this.requestPlan = requestPlan;
-        this.session = session;
-        this.URL = URL;
-        this.headers = null;
-        this.storeFields = storeFields;
-    }
-
-    protected Request(RequestPlan requestPlan, Session session, String URL, String headers) {
-        this.requestPlan = requestPlan;
-        this.session = session;
-        this.URL = URL;
-        this.headers = headers;
-        this.storeFields = null;
-    }
-
-    protected Request(RequestPlan requestPlan, Session session, String URL, String headers, Collection<String> storeFields) {
-        this.requestPlan = requestPlan;
-        this.session = session;
-        this.URL = URL;
-        this.headers = headers;
-        this.storeFields = storeFields;
+  public static String REQUESTS_LOG = null;
+  public static String HOME_PATH = "";
+  private final RequestPlan requestPlan;
+  private final String URL;
+  private final String headers;
+  private final Collection<String> storeFields;
+  private final Session session;
+
+  protected Request(RequestPlan requestPlan, Session session, String URL) {
+    this.requestPlan = requestPlan;
+    this.session = session;
+    this.URL = URL;
+    this.headers = null;
+    this.storeFields = null;
+  }
+
+  protected Request(RequestPlan requestPlan, Session session, String URL, Collection<String> storeFields) {
+    this.requestPlan = requestPlan;
+    this.session = session;
+    this.URL = URL;
+    this.headers = null;
+    this.storeFields = storeFields;
+  }
+
+  protected Request(RequestPlan requestPlan, Session session, String URL, String headers) {
+    this.requestPlan = requestPlan;
+    this.session = session;
+    this.URL = URL;
+    this.headers = headers;
+    this.storeFields = null;
+  }
+
+  protected Request(RequestPlan requestPlan, Session session, String URL, String headers, Collection<String> storeFields) {
+    this.requestPlan = requestPlan;
+    this.session = session;
+    this.URL = URL;
+    this.headers = headers;
+    this.storeFields = storeFields;
+  }
+
+  public String getMethod() {
+    return this.requestPlan.getMethod();
+  }
+
+  public String getURL() {
+    return this.URL;
+  }
+
+  protected String getHeaders() {
+    return this.headers;
+  }
+
+  public Stream<Map.Entry<String, String>> headers() {
+    Map<String, String> headers = new HashMap<>();
+    if (this.headers != null && !this.headers.isEmpty()) {
+      String[] headerPairs = this.headers.split("; ");
+      for (String headerPair : headerPairs) {
+        String[] pair = headerPair.split(": ");
+        if (pair.length > 1) headers.put(pair[0], pair[1]);
+        else Logger.getGlobal().log(Level.SEVERE, "invalid header pair {0}", headerPair);
+      }
     }
-
-    public String getMethod() {
-        return this.requestPlan.getMethod();
-    }
-
-    public String getURL() {
-        return this.URL;
+    return headers.entrySet().stream();
+  }
+
+  protected Collection<String> getStoreFields() {
+    return storeFields;
+  }
+
+  private Stream<String> storeFields() {
+    if (this.storeFields == null || this.storeFields.isEmpty()) return Stream.empty();
+    return this.storeFields.stream();
+  }
+
+  private Stream<String> storeCookies() {
+    return this.requestPlan.storeCookies();
+  }
+
+  public Request pickNextRequest(Session session) {
+    return this.requestPlan.pickNextRequest(session);
+  }
+
+  protected void storeCookies(List<String> cookies) {
+    if (storeCookies().count() == 0) return;
+    Map<String, String> map = new HashMap<>();
+    cookies.forEach(cookieGroup -> {
+      String[] cookiePairs = cookieGroup.split("; ");
+      for (String cookiePair : cookiePairs) {
+        String[] pair = cookiePair.split("=");
+        if (pair.length > 1) map.put(pair[0], pair[1]);
+      }
+    });
+    storeCookies().forEach(storeCookie -> storeValue(storeCookie, map.get(storeCookie)));
+  }
+
+  protected void processResponse(String response) {
+    if (response == null || response.isEmpty()) {
+      Logger.getGlobal().log(Level.SEVERE, "empty response");
+      return;
     }
-
-    protected String getHeaders() {
-        return this.headers;
-    }
-
-    public Stream<Map.Entry<String, String>> headers() {
-        Map<String, String> headers = new HashMap<>();
-        if (this.headers != null && !this.headers.isEmpty()) {
-            String[] headerPairs = this.headers.split("; ");
-            for (String headerPair : headerPairs) {
-                String[] pair = headerPair.split(": ");
-                if (pair.length > 1) {
-                    headers.put(pair[0], pair[1]);
-                } else {
-                    Logger.getGlobal().log(Level.SEVERE, "invalid header pair {0}", headerPair);
-                }
+    if (storeFields().count() == 0) return;
+    storeFields().forEach(new Consumer<String>() {
+
+      private final JsonParser jsonParser;
+      private final JsonElement jsonElement;
+
+      {
+        this.jsonParser = new JsonParser();
+        this.jsonElement = this.jsonParser.parse(response);
+      }
+
+      @Override
+      public void accept(String storeField) {
+        String tokenVariable;
+        if (storeField.contains("@")) tokenVariable = storeField.split("@")[1];
+        else tokenVariable = storeField;
+        Tokenizer tokenizer = new Tokenizer(tokenVariable);
+        JsonElement jsonElement = this.jsonElement;
+        while (tokenizer.hasMoreTokens()) {
+          String nextToken = tokenizer.getNextToken();
+          if (nextToken.charAt(0) == '[') {
+            try {
+              Integer index = Integer.valueOf(nextToken.substring(1, nextToken.length() - 1));
+              JsonArray jsonArray = jsonElement.getAsJsonArray();
+              if (index >= jsonArray.size()) {
+                Logger.getGlobal().log(Level.SEVERE, "index error {0}", storeField);
+                return;
+              }
+              jsonElement = jsonArray.get(index);
+            } catch (NumberFormatException ex) {
+              Logger.getGlobal().log(Level.SEVERE, "NumberFormatException {0}", storeField);
+              return;
             }
+          } else {
+            if (nextToken.charAt(0) == '#') nextToken = nextToken.substring(1);
+            JsonObject jsonObject = jsonElement.getAsJsonObject();
+            jsonElement = jsonObject.get(nextToken);
+          }
+          if (jsonElement == null) {
+            Logger.getGlobal().log(Level.SEVERE, "field {0} not present", storeField);
+            return;
+          }
         }
-        return headers.entrySet().stream();
-    }
-
-    protected Collection<String> getStoreFields() {
-        return storeFields;
-    }
-
-    private Stream<String> storeFields() {
-        if (this.storeFields == null || this.storeFields.isEmpty()) {
-            return Stream.empty();
+        Pattern pattern = Pattern.compile("\\[(.*?)\\]");
+        Matcher matcher = pattern.matcher(storeField);
+        while (matcher.find()) {
+          String found = matcher.group();
+          storeField = storeField.replace(found, "[$]");
         }
-        return this.storeFields.stream();
-    }
+        String storedValue = jsonElement.getAsString();
+        storeValue(storeField, storedValue);
+      }
 
-    private Stream<String> storeCookies() {
-        return this.requestPlan.storeCookies();
-    }
+      class Tokenizer {
 
-    public Request pickNextRequest(Session session) {
-        return this.requestPlan.pickNextRequest(session);
-    }
+        private final String string;
+        private int index;
 
-    protected void storeCookies(List<String> cookies) {
-        if (storeCookies().count() == 0) {
-            return;
+        public Tokenizer(String string) {
+          this.index = 0;
+          this.string = string;
         }
-        Map<String, String> map = new HashMap<>();
-        cookies.stream().forEach(cookieGroup -> {
-            String[] cookiePairs = cookieGroup.split("; ");
-            for (String cookiePair : cookiePairs) {
-                String[] pair = cookiePair.split("=");
-                if (pair.length > 1) {
-                    map.put(pair[0], pair[1]);
-                }
-            }
-        });
-        storeCookies().forEach(storeCookie -> {
-            storeValue(storeCookie, map.get(storeCookie));
-        });
-    }
 
-    protected void processResponse(String response) {
-        if (response == null || response.isEmpty()) {
-            Logger.getGlobal().log(Level.SEVERE, "empty response");
-            return;
+        private String getNextToken() {
+          if (!hasMoreTokens()) return null;
+          StringBuilder nextToken = new StringBuilder();
+          while (true) {
+            char nextChar = this.string.charAt(this.index);
+            this.index++;
+            nextToken.append(nextChar);
+            if (nextChar == ']') break;
+            if (this.index == this.string.length()) break;
+            char futureChar = this.string.charAt(this.index);
+            if (futureChar == '#' || futureChar == '[') break;
+          }
+          return nextToken.toString();
         }
-        if (storeFields().count() == 0) {
-            return;
-        }
-        storeFields().forEach(new Consumer<String>() {
-
-            private final JsonParser jsonParser;
-            private final JsonElement jsonElement;
 
-            {
-                this.jsonParser = new JsonParser();
-                this.jsonElement = this.jsonParser.parse(response);
-            }
-
-            class Tokenizer {
-
-                private int index;
-                private final String string;
-
-                public Tokenizer(String string) {
-                    this.index = 0;
-                    this.string = string;
-                }
-
-                private String getNextToken() {
-                    if (!hasMoreTokens()) {
-                        return null;
-                    }
-                    StringBuilder nextToken = new StringBuilder();
-                    while (true) {
-                        char nextChar = this.string.charAt(this.index);
-                        this.index++;
-                        nextToken.append(nextChar);
-                        if (nextChar == ']') {
-                            break;
-                        }
-                        if (this.index == this.string.length()) {
-                            break;
-                        }
-                        char futureChar = this.string.charAt(this.index);
-                        if (futureChar == '#' || futureChar == '[') {
-                            break;
-                        }
-                    }
-                    return nextToken.toString();
-                }
-
-                protected boolean hasMoreTokens() {
-                    if (this.string == null) {
-                        return false;
-                    }
-                    if (this.string.isEmpty()) {
-                        return false;
-                    }
-                    return this.index < string.length();
-                }
-            }
-
-            @Override
-            public void accept(String storeField) {
-                String tokenVariable;
-                if (storeField.contains("@")) {
-                    tokenVariable = storeField.split("@")[1];
-                } else {
-                    tokenVariable = storeField;
-                }
-                Tokenizer tokenizer = new Tokenizer(tokenVariable);
-                JsonElement jsonElement = this.jsonElement;
-                while (tokenizer.hasMoreTokens()) {
-                    String nextToken = tokenizer.getNextToken();
-                    if (nextToken.charAt(0) == '[') {
-                        try {
-                            Integer index = Integer.valueOf(nextToken.substring(1, nextToken.length() - 1));
-                            JsonArray jsonArray = jsonElement.getAsJsonArray();
-                            if (index >= jsonArray.size()) {
-                                Logger.getGlobal().log(Level.SEVERE, "index error {0}", storeField);
-                                return;
-                            }
-                            jsonElement = jsonArray.get(index);
-                        } catch (NumberFormatException ex) {
-                            Logger.getGlobal().log(Level.SEVERE, "NumberFormatException {0}", storeField);
-                            return;
-                        }
-                    } else {
-                        if (nextToken.charAt(0) == '#') {
-                            nextToken = nextToken.substring(1, nextToken.length());
-                        }
-                        JsonObject jsonObject = jsonElement.getAsJsonObject();
-                        jsonElement = jsonObject.get(nextToken);
-                    }
-                    if (jsonElement == null) {
-                        Logger.getGlobal().log(Level.SEVERE, "field {0} not present", storeField);
-                        return;
-                    }
-                }
-                Pattern pattern = Pattern.compile("\\[(.*?)\\]");
-                Matcher matcher = pattern.matcher(storeField);
-                while (matcher.find()) {
-                    String found = matcher.group();
-                    storeField = storeField.replace(found, "[$]");
-                }
-                String storedValue = jsonElement.getAsString();
-                storeValue(storeField, storedValue);
-            }
-        });
-    }
-
-    protected Request storeValue(String field, String value) {
-        this.session.storeValue(field, value);
-        return this;
-    }
-
-    protected String fillPropertyVariable(String property) {
-        String filledProperty = property;
-        if (filledProperty.contains("#{")) {
-            Collection<String> matches = new ArrayList<>();
-            Pattern pattern = Pattern.compile("#\\{(.*?)\\}");
-            Matcher matcher = pattern.matcher(property);
-            while (matcher.find()) {
-                matches.add(matcher.group());
-            }
-            for (String storedField : matches) {
-                String fieldName = storedField.substring(2, storedField.length() - 1);
-                String storedValue = this.session.getStoredValue(fieldName);
-                if (storedValue == null) {
-                    Logger.getGlobal().log(Level.SEVERE, "variable {0} not stored", storedField);
-                    continue;
-                }
-                filledProperty = filledProperty.replace(storedField, storedValue);
-            }
+        protected boolean hasMoreTokens() {
+          if (this.string == null) return false;
+          if (this.string.isEmpty()) return false;
+          return this.index < string.length();
         }
-        return filledProperty;
+      }
+    });
+  }
+
+  protected Request storeValue(String field, String value) {
+    this.session.storeValue(field, value);
+    return this;
+  }
+
+  protected String fillPropertyVariable(String property) {
+    String filledProperty = property;
+    if (filledProperty.contains("#{")) {
+      Pattern pattern = Pattern.compile("#\\{(.*?)}");
+      Matcher matcher = pattern.matcher(property);
+      while (matcher.find()) {
+        String storedField = matcher.group();
+        String fieldName = storedField.substring(2, storedField.length() - 1);
+        String storedValue = this.session.getStoredValue(fieldName);
+        if (storedValue == null) {
+          Logger.getGlobal().log(Level.SEVERE, "variable {0} not stored", storedField);
+          continue;
+        }
+        filledProperty = filledProperty.replace(storedField, storedValue);
+      }
     }
-
-    public void fire() {
-        this.requestPlan.requirements().forEach(requirement -> {
-            boolean unfired = Stream.concat(requirement.storeFields(), requirement.storeCookies())
-                    .anyMatch(field -> this.session.getStoredValue(field) == null);
-            if (unfired) {
-                requirement.build(this.session).fire();
-            }
-        });
-        fireRequest();
+    return filledProperty;
+  }
+
+  public void fire() {
+    this.requestPlan.requirements().forEach(requirement -> {
+      boolean unfired = Stream.concat(requirement.storeFields(), requirement.storeCookies()).anyMatch(field -> this.session.getStoredValue(field) == null);
+      if (unfired) requirement.build(this.session).fire();
+    });
+    fireRequest();
+  }
+
+  protected abstract void fireRequest();
+
+  protected void log(int statusCode) {
+    if (REQUESTS_LOG == null) return;
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("time", System.currentTimeMillis());
+    jsonObject.addProperty("code", statusCode);
+    jsonObject.addProperty("method", getMethod());
+    jsonObject.addProperty("url", getURL());
+    log(jsonObject.toString());
+  }
+
+  private void log(String message) {
+    if (REQUESTS_LOG == null) return;
+    try (FileWriter fileWriter = new FileWriter(REQUESTS_LOG, true)) {
+      fileWriter.write(message + "\n");
+    } catch (IOException ignored) {
     }
-
-    protected abstract void fireRequest();
-
-    protected void log(int statusCode) {
-        if (REQUESTS_LOG == null) {
-            return;
-        }
-        JsonObject jsonObject = new JsonObject();
-        jsonObject.addProperty("time", System.currentTimeMillis());
-        jsonObject.addProperty("code", statusCode);
-        jsonObject.addProperty("method", getMethod());
-        jsonObject.addProperty("url", getURL());
-        log(jsonObject.toString());
+  }
+
+  public final JsonObject toJsonObject() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("reference", this.requestPlan.getReference());
+    jsonObject.addProperty("URL", getURL());
+    jsonObject.addProperty("headers", getHeaders());
+    if (storeFields().count() > 0) {
+      JsonArray storeFields = new JsonArray();
+      storeFields().forEach(storeFields::add);
+      jsonObject.add("storeFields", storeFields);
     }
-
-    private void log(String message) {
-        if (REQUESTS_LOG == null) {
-            return;
-        }
-        try (FileWriter fileWriter = new FileWriter(REQUESTS_LOG, true)) {
-            fileWriter.write(message + "\n");
-        } catch (IOException ex) {
-        }
+    if (storeCookies().count() > 0) {
+      JsonArray storeCookies = new JsonArray();
+      storeCookies().forEach(storeCookies::add);
+      jsonObject.add("storeCookies", storeCookies);
     }
-
-    public final JsonObject toJsonObject() {
-        JsonObject jsonObject = new JsonObject();
-        jsonObject.addProperty("reference", this.requestPlan.getReference());
-        jsonObject.addProperty("URL", getURL());
-        jsonObject.addProperty("headers", getHeaders());
-        if (storeFields().count() > 0) {
-            JsonArray storeFields = new JsonArray();
-            storeFields().forEach(storeField -> {
-                storeFields.add(storeField);
-            });
-            jsonObject.add("storeFields", storeFields);
-        }
-        if (storeCookies().count() > 0) {
-            JsonArray storeCookies = new JsonArray();
-            storeCookies().forEach(storeCookie -> {
-                storeCookies.add(storeCookie);
-            });
-            jsonObject.add("storeCookies", storeCookies);
-        }
-        if (this instanceof PostRequest) {
-            PostRequest postRequest = (PostRequest) this;
-            jsonObject.addProperty("data", postRequest.getData());
-        }
-        if (this instanceof MultipartRequest) {
-            MultipartRequest multipartRequest = (MultipartRequest) this;
-            jsonObject.addProperty("forms", multipartRequest.getForms());
-        }
-        return jsonObject;
+    if (this instanceof PostRequest) {
+      PostRequest postRequest = (PostRequest) this;
+      jsonObject.addProperty("data", postRequest.getData());
+    }
+    if (this instanceof MultipartRequest) {
+      MultipartRequest multipartRequest = (MultipartRequest) this;
+      jsonObject.addProperty("forms", multipartRequest.getForms());
     }
+    return jsonObject;
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
index 14fa202..2bbcc9b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
@@ -6,328 +6,273 @@
 package br.ufrgs.inf.prosoft.requestssimulator.requests;
 
 import br.ufrgs.inf.prosoft.requestssimulator.Session;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Random;
+
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 /**
- *
  * @author romulo
  */
 public class RequestPlan {
 
-    private final String method;
-    private final String URL;
-    private final String data;
-    private String reference;
-    private List<RequestPlan> readLinks;
-    private List<RequestPlan> writeLinks;
-    private Collection<String> storeFields;
-    private Collection<String> storeCookies;
-    private Collection<RequestPlan> requirements;
-    private String headers;
-    private String forms;
-
-    private RequestPlan(String method, String URL, String data) {
-        this.method = method;
-        this.URL = URL;
-        this.data = data;
-    }
-
-    public static RequestPlan get(String URL) {
-        return new RequestPlan("GET", URL, null);
+  private final String method;
+  private final String URL;
+  private final String data;
+  private String reference;
+  private List<RequestPlan> readLinks;
+  private List<RequestPlan> writeLinks;
+  private Collection<String> storeFields;
+  private Collection<String> storeCookies;
+  private Collection<RequestPlan> requirements;
+  private String headers;
+  private String forms;
+
+  private RequestPlan(String method, String URL, String data) {
+    this.method = method;
+    this.URL = URL;
+    this.data = data;
+  }
+
+  public static RequestPlan get(String URL) {
+    return new RequestPlan("GET", URL, null);
+  }
+
+  public static RequestPlan post(String URL, String data) {
+    return new RequestPlan("POST", URL, data);
+  }
+
+  public static RequestPlan put(String URL, String data) {
+    return new RequestPlan("PUT", URL, data);
+  }
+
+  public static RequestPlan put(String URL) {
+    return put(URL, null);
+  }
+
+  public static RequestPlan delete(String URL, String data) {
+    return new RequestPlan("DELETE", URL, data);
+  }
+
+  public static RequestPlan delete(String URL) {
+    return delete(URL, null);
+  }
+
+  public String getMethod() {
+    return this.method;
+  }
+
+  public String getReference() {
+    if (this.reference == null) return method + "@" + this.URL;
+    return this.reference;
+  }
+
+  public RequestPlan setReference(String reference) {
+    this.reference = reference;
+    return this;
+  }
+
+  public RequestPlan addHeader(String header) {
+    if (this.headers == null || this.headers.isEmpty()) this.headers = header;
+    else this.headers += "; " + header;
+    return this;
+  }
+
+  public RequestPlan setHeaders(String headers) {
+    this.headers = headers;
+    return this;
+  }
+
+  public RequestPlan addForm(String form) {
+    if (this.method.equals("GET")) throw new RuntimeException("Adding form to GET request");
+    if (this.forms == null) this.forms = form;
+    else this.forms += "; " + form;
+    return this;
+  }
+
+  public RequestPlan setForms(String forms) {
+    if (this.method.equals("GET")) throw new RuntimeException("Adding form to GET request");
+    this.forms = forms;
+    return this;
+  }
+
+  public Stream<RequestPlan> links() {
+    if (this.readLinks == null && this.writeLinks == null) return Stream.empty();
+    if (this.readLinks != null && this.writeLinks != null) return Stream.concat(this.readLinks.stream(), this.writeLinks.stream());
+    if (this.readLinks != null) return this.readLinks.stream();
+    return this.writeLinks.stream();
+  }
+
+  public RequestPlan addLink(RequestPlan requestPlan) {
+    if (requestPlan.getMethod().equals("GET")) {
+      if (this.readLinks == null) this.readLinks = new ArrayList<>();
+      this.readLinks.add(requestPlan);
+    } else {
+      if (this.writeLinks == null) this.writeLinks = new ArrayList<>();
+      this.writeLinks.add(requestPlan);
     }
-
-    public static RequestPlan post(String URL, String data) {
-        return new RequestPlan("POST", URL, data);
+    return this;
+  }
+
+  public RequestPlan addLinks(Collection<RequestPlan> requestPlans) {
+    requestPlans.forEach(this::addLink);
+    return this;
+  }
+
+  public RequestPlan addRequirement(RequestPlan requestPlan) {
+    if (this.requirements == null) this.requirements = new ArrayList<>();
+    this.requirements.add(requestPlan);
+    return this;
+  }
+
+  protected Stream<RequestPlan> requirements() {
+    if (this.requirements == null || this.requirements.isEmpty()) return Stream.empty();
+    return this.requirements.stream();
+  }
+
+  protected Stream<String> storeFields() {
+    if (this.storeFields == null || this.storeFields.isEmpty()) return Stream.empty();
+    return this.storeFields.stream();
+  }
+
+  protected Stream<String> storeCookies() {
+    if (this.storeCookies == null || this.storeCookies.isEmpty()) return Stream.empty();
+    return this.storeCookies.stream();
+  }
+
+  public Request pickNextRequest(Session session) {
+    Random random = new Random();
+    if ((this.readLinks == null || this.readLinks.isEmpty()) && (this.writeLinks == null || this.writeLinks.isEmpty())) {
+      throw new RuntimeException("GET and POST links empty: " + this.URL);
     }
-
-    public static RequestPlan put(String URL, String data) {
-        return new RequestPlan("PUT", URL, data);
+    int probability = random.nextInt(100);
+    RequestPlan chosen;
+    if (this.readLinks == null || this.readLinks.isEmpty()) probability = 100;
+    else if (this.writeLinks == null || this.writeLinks.isEmpty()) probability = 0;
+    if (probability < 80) {
+      int chosenIndex = random.nextInt(this.readLinks.size());
+      chosen = this.readLinks.get(chosenIndex);
+    } else {
+      int chosenIndex = random.nextInt(this.writeLinks.size());
+      chosen = this.writeLinks.get(chosenIndex);
     }
-
-    public static RequestPlan put(String URL) {
-        return put(URL, null);
+    return chosen.build(session);
+  }
+
+  public Request build(Session session) {
+    if (this.URL == null || this.URL.isEmpty()) throw new RuntimeException("URL is empty");
+    String URL = replaceOptionals(this.URL);
+    HashMap<String, Integer> map = new HashMap<>();
+    URL = replaceRandoms(URL, map);
+    Collection<String> storeFields = storeFields()
+      .map(storeField -> replaceRandoms(storeField, map))
+      .collect(Collectors.toList());
+    String headers = null;
+    if (this.headers != null) {
+      headers = replaceOptionals(this.headers);
+      headers = replaceRandoms(headers, map);
+      if (this.headers.contains("multipart")) {
+        String forms = replaceOptionals(this.forms);
+        return new MultipartRequest(this, session, URL, headers, forms, storeFields);
+      }
     }
-
-    public static RequestPlan delete(String URL, String data) {
-        return new RequestPlan("DELETE", URL, data);
+    if (this.method.equals("DELETE")) return new DeleteRequest(this, session, URL, headers, storeFields);
+    if (this.method.equals("GET")) return new GetRequest(this, session, URL, headers, storeFields);
+    String data = null;
+    if (this.data != null) data = replaceOptionals(this.data);
+    if (this.method.equals("PUT")) return new PutRequest(this, session, URL, data, headers, storeFields);
+    data = replaceRandoms(data, map);
+    return new PostRequest(this, session, URL, data, headers, storeFields);
+  }
+
+  private String replaceRandoms(String data) {
+    return replaceRandoms(data, new HashMap<>());
+  }
+
+  private String replaceRandoms(String data, Map<String, Integer> map) {
+    Random random = new Random();
+    Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
+    Matcher randomMatcher = pattern.matcher(data);
+    while (randomMatcher.find()) {
+      String randomFound = randomMatcher.group();
+      String randomTrimmed = randomFound.substring(2, randomFound.length() - 1);
+      int randomInt;
+      if (map.containsKey(randomFound)) {
+        randomInt = map.get(randomFound);
+      } else {
+        String[] split = randomTrimmed.split("-");
+        int from = Integer.valueOf(split[0]);
+        int to = Integer.valueOf(split[1]);
+        randomInt = random.nextInt(to - from + 1) + from;
+        map.put(randomFound, randomInt);
+      }
+      data = data.replace(randomFound, String.valueOf(randomInt));
     }
-
-    public static RequestPlan delete(String URL) {
-        return delete(URL, null);
+    int randomInt;
+    if (map.containsKey("$")) {
+      randomInt = map.get("$");
+    } else {
+      randomInt = random.nextInt() & Integer.MAX_VALUE;
+      map.put("$", randomInt);
     }
-
-    public String getMethod() {
-        return this.method;
+    pattern = Pattern.compile("#\\{(.*?)\\}");
+    String[] split = pattern.split(data);
+    for (String around : split) {
+      String newAround = around.replace("$", String.valueOf(randomInt));
+      data = data.replace(around, newAround);
     }
-
-    public RequestPlan setReference(String reference) {
-        this.reference = reference;
-        return this;
+    return data;
+  }
+
+  private String replaceOptionals(String data) {
+    Pattern pattern = Pattern.compile("<(.*?)>");
+    Matcher matcher = pattern.matcher(data);
+    Random random = new Random();
+    while (matcher.find()) {
+      String options = matcher.group();
+      String optionsTrimmed = options.substring(1, options.length() - 1);
+      String[] split = optionsTrimmed.split("\\|");
+      int nextInt = random.nextInt(split.length);
+      String choice = split[nextInt];
+      data = data.replace(options, choice);
     }
+    return data;
+  }
 
-    public String getReference() {
-        if (this.reference == null) {
-            return method + "@" + this.URL;
-        }
-        return this.reference;
+  public Request bind(Request request, Session session) {
+    if (request instanceof DeleteRequest) {
+      DeleteRequest deleteRequest = (DeleteRequest) request;
+      return new DeleteRequest(this, session, deleteRequest.getURL(), deleteRequest.getHeaders(), deleteRequest.getStoreFields());
     }
-
-    public RequestPlan addHeader(String header) {
-        if (this.headers == null || this.headers.isEmpty()) {
-            this.headers = header;
-        } else {
-            this.headers += "; " + header;
-        }
-        return this;
+    if (request instanceof GetRequest) {
+      GetRequest getRequest = (GetRequest) request;
+      return new GetRequest(this, session, getRequest.getURL(), getRequest.getHeaders(), getRequest.getStoreFields());
     }
-
-    public RequestPlan setHeaders(String headers) {
-        this.headers = headers;
-        return this;
+    if (request instanceof PostRequest) {
+      PostRequest postRequest = (PostRequest) request;
+      return new PostRequest(this, session, postRequest.getURL(), postRequest.getData(), postRequest.getHeaders(), postRequest.getStoreFields());
     }
-
-    public RequestPlan addForm(String form) {
-        if (this.method.equals("GET")) {
-            throw new RuntimeException("Adding form to GET request");
-        }
-        if (this.forms == null) {
-            this.forms = form;
-        } else {
-            this.forms += "; " + form;
-        }
-        return this;
-    }
-
-    public RequestPlan setForms(String forms) {
-        if (this.method.equals("GET")) {
-            throw new RuntimeException("Adding form to GET request");
-        }
-        this.forms = forms;
-        return this;
-    }
-
-    public Stream<RequestPlan> links() {
-        if (this.readLinks == null && this.writeLinks == null) {
-            return Stream.empty();
-        }
-        if (this.readLinks != null && this.writeLinks != null) {
-            return Stream.concat(this.readLinks.stream(), this.writeLinks.stream());
-        }
-        if (this.readLinks != null) {
-            return this.readLinks.stream();
-        }
-        return this.writeLinks.stream();
-    }
-
-    public RequestPlan addLink(RequestPlan requestPlan) {
-        if (requestPlan.getMethod().equals("GET")) {
-            if (this.readLinks == null) {
-                this.readLinks = new ArrayList<>();
-            }
-            this.readLinks.add(requestPlan);
-        } else {
-            if (this.writeLinks == null) {
-                this.writeLinks = new ArrayList<>();
-            }
-            this.writeLinks.add(requestPlan);
-        }
-        return this;
-    }
-
-    public RequestPlan addLinks(Collection<RequestPlan> requestPlans) {
-        requestPlans.forEach(requestPlan -> addLink(requestPlan));
-        return this;
-    }
-
-    public RequestPlan addRequirement(RequestPlan requestPlan) {
-        if (this.requirements == null) {
-            this.requirements = new ArrayList<>();
-        }
-        this.requirements.add(requestPlan);
-        return this;
-    }
-
-    protected Stream<RequestPlan> requirements() {
-        if (this.requirements == null || this.requirements.isEmpty()) {
-            return Stream.empty();
-        }
-        return this.requirements.stream();
-    }
-
-    protected Stream<String> storeFields() {
-        if (this.storeFields == null || this.storeFields.isEmpty()) {
-            return Stream.empty();
-        }
-        return this.storeFields.stream();
-    }
-
-    protected Stream<String> storeCookies() {
-        if (this.storeCookies == null || this.storeCookies.isEmpty()) {
-            return Stream.empty();
-        }
-        return this.storeCookies.stream();
-    }
-
-    public Request pickNextRequest(Session session) {
-        Random random = new Random();
-        if ((this.readLinks == null || this.readLinks.isEmpty()) && (this.writeLinks == null || this.writeLinks.isEmpty())) {
-            throw new RuntimeException("GET and POST links empty: " + this.URL);
-        }
-        int probability = random.nextInt(100);
-        RequestPlan chosen;
-        if (this.readLinks == null || this.readLinks.isEmpty()) {
-            probability = 100;
-        } else if (this.writeLinks == null || this.writeLinks.isEmpty()) {
-            probability = 0;
-        }
-        if (probability < 80) {
-            int chosenIndex = random.nextInt(this.readLinks.size());
-            chosen = this.readLinks.get(chosenIndex);
-        } else {
-            int chosenIndex = random.nextInt(this.writeLinks.size());
-            chosen = this.writeLinks.get(chosenIndex);
-        }
-        return chosen.build(session);
-    }
-
-    public Request build(Session session) {
-        if (this.URL == null || this.URL.isEmpty()) {
-            throw new RuntimeException("URL is empty");
-        }
-        String URL = replaceOptionals(this.URL);
-        HashMap<String, Integer> map = new HashMap<>();
-        URL = replaceRandoms(URL, map);
-        Collection<String> storeFields = storeFields()
-                .map(storeField -> replaceRandoms(storeField, map))
-                .collect(Collectors.toList());
-        String headers = null;
-        if (this.headers != null) {
-            headers = replaceOptionals(this.headers);
-            headers = replaceRandoms(headers, map);
-            if (this.headers.contains("multipart")) {
-                String forms = replaceOptionals(this.forms);
-                return new MultipartRequest(this, session, URL, headers, forms, storeFields);
-            }
-        }
-        if (this.method.equals("DELETE")) {
-            return new DeleteRequest(this, session, URL, headers, storeFields);
-        }
-        if (this.method.equals("GET")) {
-            return new GetRequest(this, session, URL, headers, storeFields);
-        }
-        String data = null;
-        if (this.data != null) {
-            data = replaceOptionals(this.data);
-        }
-        if (this.method.equals("PUT")) {
-            return new PutRequest(this, session, URL, data, headers, storeFields);
-        }
-        data = replaceRandoms(data, map);
-        return new PostRequest(this, session, URL, data, headers, storeFields);
-    }
-
-    private String replaceRandoms(String data) {
-        return replaceRandoms(data, new HashMap<>());
-    }
-
-    private String replaceRandoms(String data, Map<String, Integer> map) {
-        Random random = new Random();
-        Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
-        Matcher randomMatcher = pattern.matcher(data);
-        while (randomMatcher.find()) {
-            String randomFound = randomMatcher.group();
-            String randomTrimmed = randomFound.substring(2, randomFound.length() - 1);
-            int randomInt;
-            if (map.containsKey(randomFound)) {
-                randomInt = map.get(randomFound);
-            } else {
-                String[] split = randomTrimmed.split("-");
-                int from = Integer.valueOf(split[0]);
-                int to = Integer.valueOf(split[1]);
-                randomInt = random.nextInt(to - from + 1) + from;
-                map.put(randomFound, randomInt);
-            }
-            data = data.replace(randomFound, String.valueOf(randomInt));
-        }
-        int randomInt;
-        if (map.containsKey("$")) {
-            randomInt = map.get("$");
-        } else {
-            randomInt = random.nextInt() & Integer.MAX_VALUE;
-            map.put("$", randomInt);
-        }
-        pattern = Pattern.compile("#\\{(.*?)\\}");
-        String[] split = pattern.split(data);
-        for (String around : split) {
-            String newAround = around.replace("$", String.valueOf(randomInt));
-            data = data.replace(around, newAround);
-        }
-        return data;
-    }
-
-    private String replaceOptionals(String data) {
-        Pattern pattern = Pattern.compile("<(.*?)>");
-        Matcher matcher = pattern.matcher(data);
-        Random random = new Random();
-        while (matcher.find()) {
-            String options = matcher.group();
-            String optionsTrimmed = options.substring(1, options.length() - 1);
-            String[] split = optionsTrimmed.split("\\|");
-            int nextInt = random.nextInt(split.length);
-            String choice = split[nextInt];
-            data = data.replace(options, choice);
-        }
-        return data;
-    }
-
-    public Request bind(Request request, Session session) {
-        if (request instanceof DeleteRequest) {
-            DeleteRequest deleteRequest = (DeleteRequest) request;
-            return new DeleteRequest(this, session, deleteRequest.getURL(), deleteRequest.getHeaders(), deleteRequest.getStoreFields());
-        }
-        if (request instanceof GetRequest) {
-            GetRequest getRequest = (GetRequest) request;
-            return new GetRequest(this, session, getRequest.getURL(), getRequest.getHeaders(), getRequest.getStoreFields());
-        }
-        if (request instanceof PostRequest) {
-            PostRequest postRequest = (PostRequest) request;
-            return new PostRequest(this, session, postRequest.getURL(), postRequest.getData(), postRequest.getHeaders(), postRequest.getStoreFields());
-        }
-        if (request instanceof PutRequest) {
-            PutRequest putRequest = (PutRequest) request;
-            return new PutRequest(this, session, putRequest.getURL(), putRequest.getData(), putRequest.getHeaders(), putRequest.getStoreFields());
-        }
-        MultipartRequest multipartRequest = (MultipartRequest) request;
-        return new MultipartRequest(this, session, multipartRequest.getURL(), multipartRequest.getHeaders(), multipartRequest.getForms(), multipartRequest.getStoreFields());
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(this.method, this.URL);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof RequestPlan)) {
-            return false;
-        }
-        RequestPlan other = (RequestPlan) obj;
-        return this.method.equals(other.method) && this.URL.equals(other.URL);
+    if (request instanceof PutRequest) {
+      PutRequest putRequest = (PutRequest) request;
+      return new PutRequest(this, session, putRequest.getURL(), putRequest.getData(), putRequest.getHeaders(), putRequest.getStoreFields());
     }
+    MultipartRequest multipartRequest = (MultipartRequest) request;
+    return new MultipartRequest(this, session, multipartRequest.getURL(), multipartRequest.getHeaders(), multipartRequest.getForms(), multipartRequest.getStoreFields());
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(this.method, this.URL);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) return true;
+    if (obj == null) return false;
+    if (!(obj instanceof RequestPlan)) return false;
+    RequestPlan other = (RequestPlan) obj;
+    return this.method.equals(other.method) && this.URL.equals(other.URL);
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
index c283703..5871349 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
@@ -7,96 +7,96 @@ package br.ufrgs.inf.prosoft.requestssimulator;
 
 import br.ufrgs.inf.prosoft.requestssimulator.requests.Request;
 import br.ufrgs.inf.prosoft.requestssimulator.requests.RequestPlan;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
+
+import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 /**
- *
  * @author romulo
  */
 public class Session {
 
-    private static final Logger LOGGER = Logger.getLogger(Session.class.getName());
+  private static final Logger LOGGER = Logger.getLogger(Session.class.getName());
 
-    private final Collection<RequestPlan> roots;
-    private final Map<String, String> storedValues;
-    private final List<Request> requests;
+  private final Collection<RequestPlan> roots;
+  private final Map<String, String> storedValues;
+  private final List<Request> requests;
 
-    public Session(Collection<RequestPlan> roots) {
-        this.roots = roots;
-        this.storedValues = new HashMap<>();
-        this.requests = new ArrayList<>();
-    }
+  public Session(Collection<RequestPlan> roots) {
+    this.roots = roots;
+    this.storedValues = new HashMap<>();
+    this.requests = new ArrayList<>();
+  }
 
-    public Session(List<Request> requests) {
-        this.roots = null;
-        this.storedValues = new HashMap<>();
-        this.requests = requests;
-    }
+  public Session(List<Request> requests) {
+    this.roots = null;
+    this.storedValues = new HashMap<>();
+    this.requests = requests;
+  }
 
-    public Session storeValue(String field, String value) {
-        this.storedValues.put(field, value);
-        return this;
-    }
+  public Session storeValue(String field, String value) {
+    this.storedValues.put(field, value);
+    return this;
+  }
 
-    public String getStoredValue(String storedField) {
-        return this.storedValues.get(storedField);
+  public String getStoredValue(String storedField) {
+    Pattern pattern = Pattern.compile("\\[(.*?)]");
+    Matcher matcher = pattern.matcher(storedField);
+    while (matcher.find()) {
+      String found = matcher.group();
+      storedField = storedField.replace(found, "[$]");
     }
+    return this.storedValues.get(storedField);
+  }
 
-    public Stream<Request> requests() {
-        return this.requests.stream();
-    }
+  public Stream<Request> requests() {
+    return this.requests.stream();
+  }
 
-    public void simulate() {
-        Random random = new Random();
-        Request request = null;
-        int probability = 0;
-        while (probability < 70) {
-            try {
-                request = pickNextRequest(request);
-            } catch (RuntimeException ex) {
-                LOGGER.log(Level.SEVERE, ex.getMessage());
-                break;
-            }
-            request.fire();
-            this.requests.add(request);
-            probability = random.nextInt(100);
-        }
+  public void simulate() {
+    Random random = new Random();
+    Request request = null;
+    int probability = 0;
+    while (probability < 70) {
+      try {
+        request = pickNextRequest(request);
+      } catch (RuntimeException ex) {
+        LOGGER.log(Level.SEVERE, ex.getMessage());
+        break;
+      }
+      request.fire();
+      this.requests.add(request);
+      probability = random.nextInt(100);
     }
+  }
 
-    public void execute() {
-        for (Iterator<Request> iterator = this.requests.iterator(); iterator.hasNext();) {
-            Request request = iterator.next();
-            request.fire();
-            iterator.remove();
-        }
+  public void execute() {
+    for (Iterator<Request> iterator = this.requests.iterator(); iterator.hasNext(); ) {
+      Request request = iterator.next();
+      request.fire();
+      iterator.remove();
     }
+  }
 
-    public Request pickNextRequest(Request currentRequest) {
-        if (currentRequest == null) {
-            if (this.roots == null || this.roots.isEmpty()) {
-                throw new RuntimeException("root within cycle");
-            }
-            if (this.roots.size() == 1) {
-                RequestPlan requestPlan = this.roots.stream().findAny().get();
-                try {
-                    return requestPlan.build(this);
-                } catch (RuntimeException ex) {
-                    return requestPlan.pickNextRequest(this);
-                }
-            }
-            currentRequest = RequestPlan.get("root")
-                    .addLinks(this.roots)
-                    .build(this);
+  public Request pickNextRequest(Request currentRequest) {
+    if (currentRequest == null) {
+      if (this.roots == null || this.roots.isEmpty()) throw new RuntimeException("root within cycle");
+      if (this.roots.size() == 1) {
+        RequestPlan requestPlan = this.roots.stream().findAny().get();
+        try {
+          return requestPlan.build(this);
+        } catch (RuntimeException ex) {
+          return requestPlan.pickNextRequest(this);
         }
-        return currentRequest.pickNextRequest(this);
+      }
+      currentRequest = RequestPlan.get("root")
+        .addLinks(this.roots)
+        .build(this);
     }
+    return currentRequest.pickNextRequest(this);
+  }
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java
index be0cee0..b304029 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Simulator.java
@@ -9,6 +9,7 @@ import br.ufrgs.inf.prosoft.requestssimulator.requests.Request;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
+
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.Writer;
@@ -20,71 +21,63 @@ import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
 /**
- *
  * @author romulo
  */
 public class Simulator {
 
-    private static final Logger LOGGER = Logger.getLogger(Simulator.class.getName());
+  private static final Logger LOGGER = Logger.getLogger(Simulator.class.getName());
 
-    public static final void simulate(Profile profile, long time) {
-        simulate(profile, time, 1);
-    }
+  public static final void simulate(Profile profile, long time) {
+    simulate(profile, time, 1);
+  }
 
-    public static final void simulate(Profile profile, long time, int users) {
-        simulate(profile, time, users, null);
-    }
+  public static final void simulate(Profile profile, long time, int users) {
+    simulate(profile, time, users, null);
+  }
 
-    public static final void simulate(Profile profile, long time, String logPath) {
-        simulate(profile, time, 1, logPath);
-    }
+  public static final void simulate(Profile profile, long time, String logPath) {
+    simulate(profile, time, 1, logPath);
+  }
 
-    public static final void simulate(Profile profile, long time, int users, String logPath) {
-        LOGGER.log(Level.INFO, "simulating with {0} users for {1} millis", new Object[]{users, time});
-        Collection<Thread> threads = new ArrayList<>();
-        List<Profile> profiles = new ArrayList<>();
-        Runtime.getRuntime().addShutdownHook(new Thread() {
-            @Override
-            public void run() {
-                writeLog(logPath, profiles);
-            }
-        });
-        for (int i = 0; i < users; i++) {
-            Profile clone = profile.clone();
-            profiles.add(clone);
-            Thread thread = new Thread(() -> {
-                clone.simulate(time);
-            });
-            threads.add(thread);
-        }
-        threads.forEach(Thread::start);
-        threads.forEach(thread -> {
-            try {
-                thread.join();
-            } catch (InterruptedException ex) {
-                LOGGER.log(Level.SEVERE, null, ex);
-            }
-        });
+  public static final void simulate(Profile profile, long time, int users, String logPath) {
+    LOGGER.log(Level.INFO, "simulating with {0} users for {1} millis", new Object[]{users, time});
+    Collection<Thread> threads = new ArrayList<>();
+    List<Profile> profiles = new ArrayList<>();
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> writeLog(logPath, profiles)));
+    for (int i = 0; i < users; i++) {
+      Profile clone = profile.clone();
+      profiles.add(clone);
+      Thread thread = new Thread(() -> clone.simulate(time));
+      threads.add(thread);
     }
+    threads.forEach(Thread::start);
+    threads.forEach(thread -> {
+      try {
+        thread.join();
+      } catch (InterruptedException ex) {
+        LOGGER.log(Level.SEVERE, null, ex);
+      }
+    });
+  }
 
-    private static void writeLog(String logPath, List<Profile> profiles) {
-        if (logPath != null) {
-            LOGGER.log(Level.INFO, "writing log");
-            List<List<List<JsonObject>>> logs = profiles.stream()
-                    .map(profile
-                            -> profile.sessions()
-                            .map(session
-                                    -> session.requests()
-                                    .map(Request::toJsonObject)
-                                    .collect(Collectors.toList()))
-                            .collect(Collectors.toList()))
-                    .collect(Collectors.toList());
-            Gson gson = new GsonBuilder().setPrettyPrinting().create();
-            try (Writer writer = new FileWriter(logPath)) {
-                gson.toJson(logs, writer);
-            } catch (IOException ex) {
-                LOGGER.log(Level.SEVERE, "invalid log path");
-            }
-        }
+  private static void writeLog(String logPath, List<Profile> profiles) {
+    if (logPath != null) {
+      LOGGER.log(Level.INFO, "writing log");
+      List<List<List<JsonObject>>> logs = profiles.stream()
+        .map(profile
+          -> profile.sessions()
+          .map(session
+            -> session.requests()
+            .map(Request::toJsonObject)
+            .collect(Collectors.toList()))
+          .collect(Collectors.toList()))
+        .collect(Collectors.toList());
+      Gson gson = new GsonBuilder().setPrettyPrinting().create();
+      try (Writer writer = new FileWriter(logPath)) {
+        gson.toJson(logs, writer);
+      } catch (IOException ex) {
+        LOGGER.log(Level.SEVERE, "invalid log path");
+      }
     }
+  }
 }