JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / unused / com / stevesoft / pat / ReplaceRule.java
1 //
2 // This software is now distributed according to
3 // the Lesser Gnu Public License.  Please see
4 // http://www.gnu.org/copyleft/lesser.txt for
5 // the details.
6 //    -- Happy Computing!
7 //
8 package com.stevesoft.pat;
9
10 import java.util.Hashtable;
11
12 /**
13  * ReplaceRule is a singly linked list of Objects which describe how to replace
14  * the matched portion of a String. The only member method that you absolutely
15  * need to define to use this class is apply(StringBuffer,RegRes) -- although
16  * you may want define toString1() and clone1() (if you are unhappy with the
17  * default methods) that are needed by the clone() or toString() methods on this
18  * class. During the replacement process, each ReplaceRule tells the replacer
19  * what to add to javajs.util.SB and uses the contents of the Regular expression
20  * result to get the information it needs to do this. Here is an <a
21  * href="http://javaregex.com/code/fancy.java.html">example</a>
22  * 
23  * @see com.stevesoft.pat.NullRule
24  * @see com.stevesoft.pat.AmpersandRule
25  * @see com.stevesoft.pat.BackRefRule
26  * @see com.stevesoft.pat.LeftRule
27  * @see com.stevesoft.pat.RightRule
28  * @see com.stevesoft.pat.StringRule
29  */
30 public abstract class ReplaceRule
31 {
32   /** points to the next ReplaceRule in the linked list. */
33   protected ReplaceRule next = null;
34
35   /**
36    * This function appends to the StringBufferLike the text you want to replaced
37    * the portion of the String last matched.
38    */
39   public abstract void apply(StringBufferLike sb, RegRes r);
40
41   /**
42    * A rule describing how to clone only the current ReplaceRule, and none of
43    * the others in this linked list. It is called by clone() for each item in
44    * the list.
45    */
46   public Object clone1()
47   {
48     return new RuleHolder(this);
49   }
50
51   public final Object clone()
52   {
53     ReplaceRule x = (ReplaceRule) clone1();
54     ReplaceRule xsav = x;
55     ReplaceRule y = this;
56     while (y.next != null)
57     {
58       x.next = (ReplaceRule) y.next.clone1();
59       x.name = y.name;
60       x = x.next;
61       y = y.next;
62     }
63     return xsav;
64   }
65
66   static ReplaceRule add(ReplaceRule head, ReplaceRule adding)
67   {
68     if (head == null)
69     {
70       return head = adding;
71     }
72     head.addRule(adding);
73     return head;
74   }
75
76   public ReplaceRule add(ReplaceRule adding)
77   {
78     return add(this, adding);
79   }
80
81   /** Add another ReplaceRule to the linked list. */
82   public void addRule(ReplaceRule r)
83   {
84     if (next == null)
85     {
86       next = r;
87     }
88     else
89     {
90       next.addRule(r);
91     }
92   }
93
94   static Regex getvar = null;
95
96   final static Regex getv()
97   {
98     // Thanks to Michael Jimenez for pointing out the need
99     // to clone getvar rather than simply returning it.
100     // Previously this was not thread safe.
101     // if(getvar != null) return getvar;
102     if (getvar != null)
103     {
104       return (Regex) getvar.clone();
105     }
106     getvar = new Regex("(?:\\\\(\\d+)|" + // ref 1
107             "\\$(?:" + "(\\d+)|" + // ref 2
108             "(\\w+)|" + // ref 3
109             "([&'`])|" + // ref 4
110             "\\{(?:(\\d+)|" + // ref 5
111             "([^\n}\\\\]+))}" + // ref 6
112             ")|" + "\\\\([nrbtaef])|" + // ref 7
113             "\\\\c([\u0000-\uFFFF])|" + // ref 8
114             "\\\\x([A-Fa-f0-9]{2})|" + // ref 9
115             "\\\\([\u0000-\uFFFF])" + // ref 10
116             ")");
117     getvar.optimize();
118     return getvar;
119   }
120
121   static Hashtable defs = new Hashtable();
122
123   public static boolean isDefined(String s)
124   {
125     return defs.get(s) != null;
126   }
127
128   public static void define(String s, Regex r)
129   {
130     defs.put(s, r);
131   }
132
133   public static void define(String s, ReplaceRule r)
134   {
135     defs.put(s, r);
136     r.name = s;
137   }
138
139   String name = getClass().getName();
140
141   public static void define(String s, Transformer t)
142   {
143     defs.put(s, t);
144   }
145
146   public static void undefine(String s)
147   {
148     defs.remove(s);
149   }
150
151   /**
152    * This tells how to convert just the current element (and none of the other
153    * items in the linked list) to a String. This method is called by toString()
154    * for each item in the linked list.
155    */
156   public String toString1()
157   {
158     return "${" + name + "}";
159   }
160
161   /** Convert to a String. */
162   public final String toString()
163   {
164     javajs.util.SB sb = new javajs.util.SB();
165     sb.append(toString1());
166     ReplaceRule rr = this.next;
167     while (rr != null)
168     {
169       sb.append(rr.toString1());
170       rr = rr.next;
171     }
172     return sb.toString();
173   }
174
175   /**
176    * Modified the behavior of a ReplaceRule by supplying an argument. If a
177    * ReplaceRule named "foo" is defined and the pattern "s/x/${foo:5}/" is given
178    * to Regex.perlCode, then the "foo" the definition of "foo" will be retrieved
179    * and arg("5") will be called. If the result is non-null, that is the
180    * ReplaceRule that will be used. If the result is null, then the pattern
181    * works just as if it were "s/x/${foo}/".
182    * 
183    * @see com.stevesoft.pat.Validator#arg(java.lang.String)
184    */
185   public ReplaceRule arg(String s)
186   {
187     return null;
188   }
189
190   static int getHexDigit(char c)
191   {
192     if (c >= '0' && c <= '9')
193     {
194       return c - '0';
195     }
196     if (c >= 'a' && c <= 'f')
197     {
198       return c - 'a' + 10;
199     }
200     return c - 'A' + 10;
201   }
202 }