View Javadoc
1   package com.exsoinn.util.epf;
2   
3   
4   import net.jcip.annotations.Immutable;
5   
6   import java.util.regex.Pattern;
7   
8   /**
9    * Encapsulates a all te information necessary to find data in a {@link Context}. You can build {@link SelectionCriteria}
10   * objects by passing a properly formatted String, and then invoking factory method
11   * {@link SelectionCriteria#valueOf(String)}. The format is a pipe delimited string with exacty 3 tokens, one each corresponding
12   * to, and in the same order, to a: {@link SearchPath}, {@link Filter} and {@link TargetElements}.
13   * Refer to each individual class for details on the format for each.
14   *
15   * Created by QuijadaJ on 5/18/2017.
16   */
17  @Immutable
18  public final class SelectionCriteria {
19      private final SearchPath searchPath;
20      private final Filter filter;
21      private final TargetElements targetElements;
22      private static final String sampleFormat = "node1.node2.node3[1]|key1=val1;key2=val2|elem1,elem2";
23      public final static String SEARCH_CRITERIA_DELIM = "||";
24      public final static String SEARCH_CRITERIA_NULL = "null";
25  
26  
27      private SelectionCriteria(String pStr) {
28          String[] tokens = pStr.split(Pattern.quote(SEARCH_CRITERIA_DELIM));
29          if (null == tokens || tokens.length != 3) {
30              throw new IllegalArgumentException(this.getClass().getName() + " string " + pStr
31                      + " could not be parsed, check format and try again. Sample format is " + sampleFormat
32                      + ". Selection criteria must contain 3 tokens. You can pass "
33                      + SEARCH_CRITERIA_NULL + " for blank tokens.");
34          }
35  
36          try {
37              if (tokenIsNull(tokens[0])) {
38                  throw new IllegalArgumentException("At least search path must be provided: " + pStr);
39              }
40              searchPath = SearchPath.valueOf(tokens[0]);
41              filter = tokenIsNull(tokens[1]) ? null : Filter.valueOf(tokens[1]);
42              targetElements = tokenIsNull(tokens[2]) ? null : TargetElements.valueOf(tokens[2]);
43          } catch (Exception e) {
44              throw new IllegalArgumentException("SearchCriteria string " + pStr
45                      + " could not be parsed, check format and try again. Sample format is " + sampleFormat, e);
46          }
47      }
48  
49  
50      private SelectionCriteria(SearchPath pSearchPath, Filter pFilter, TargetElements pTargeElems) {
51          searchPath = pSearchPath;
52          filter = pFilter;
53          targetElements = pTargeElems;
54      }
55  
56      private boolean tokenIsNull(String pToken) {
57          return SEARCH_CRITERIA_NULL.equalsIgnoreCase(pToken);
58      }
59  
60      public static SelectionCriteria valueOf(String pStr) {
61          return new SelectionCriteria(pStr);
62      }
63  
64      public static SelectionCriteria fromObjects(SearchPath pSearchPath, Filter pFilter, TargetElements pTargeElems) {
65          return new SelectionCriteria(pSearchPath, pFilter, pTargeElems);
66      }
67  
68  
69      /**
70       * Replaces special characters with string parse-friendly substitutes. By parse-friendly, it means removing
71       * characters that may have special meaning depending on who the consumer is, for example a regular expression
72       * engine, a JSON/XML parser, etc... These special characters if not escape or removed will error out
73       * when processed by some consumers. This convenience method attempts to take care of that conversion
74       * for you.
75       *
76       * @return - {@code SelectionCriteria} string with special characters converted to some string substitute.
77       */
78      public String specialCharactersConverted() {
79          String sc = toString();
80          sc = sc.replaceAll(Pattern.quote("||"), "__DP__");
81          sc = sc.replaceAll(Pattern.quote(";"), "__SC__");
82          sc = sc.replaceAll(Pattern.quote("="), "__EQ__");
83          sc = sc.replaceAll(Pattern.quote("["), "__SBO__");
84          sc = sc.replaceAll(Pattern.quote("]"), "__SBC__");
85  
86          return sc;
87      }
88  
89  
90      public SearchPath getSearchPath() {
91          return searchPath;
92      }
93  
94      public TargetElements getTargetElements() {
95          return targetElements;
96      }
97  
98      public Filter getFilter() {
99          return filter;
100     }
101 
102     @Override
103     public String toString() {
104         StringBuilder sb = new StringBuilder();
105         sb.append(getSearchPath());
106         sb.append(SEARCH_CRITERIA_DELIM);
107         sb.append(null == getFilter() ? "NULL" : getFilter());
108         sb.append(SEARCH_CRITERIA_DELIM);
109         sb.append(null == getTargetElements() ? "NULL" : getTargetElements());
110 
111         return sb.toString();
112     }
113 
114 }