1 /*
2  * Copyright (C) 2010 The Libphonenumber Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.i18n.phonenumbers;
18 
19 import java.util.Iterator;
20 
21 /**
22  * A sequence of elements representing a JavaScript Array. The principal operation on a
23  * JSArrayBuilder is the append method that appends an element to the array. To facilitate nesting
24  * beginArray and endArray are also supported. Example of a JSArray: ["a", ["b', "c"]].
25  *
26  * @author Nikolaos Trogkanis
27  */
28 public class JSArrayBuilder implements CharSequence {
29   // Internal representation.
30   private StringBuilder data = new StringBuilder();
31   // Flag that keeps track whether the element being added to the array is the first element.
32   private boolean isFirstElement = true;
33 
34   /**
35    * Begin a new element.
36    */
beginElement()37   private void beginElement() {
38     if (!isFirstElement) {
39       data.append(',');
40     }
41     isFirstElement = false;
42   }
43 
44   /**
45    * Begin a new array.
46    */
beginArray()47   public JSArrayBuilder beginArray() {
48     beginElement();
49     data.append('[');
50     isFirstElement = true;
51     return this;
52   }
53 
54   /**
55    * End an array.
56    */
endArray()57   public JSArrayBuilder endArray() {
58     trimTrailingCommas();
59     data.append("]\n");
60     isFirstElement = false;
61     return this;
62   }
63 
64   /**
65    * Add a number to the array.
66    */
append(int number)67   public JSArrayBuilder append(int number) {
68     return append(Integer.toString(number), false);
69   }
70 
71   /**
72    * Add a string to the array.
73    */
append(String string)74   public JSArrayBuilder append(String string) {
75     return append(string, true);
76   }
77 
78   /**
79    * Add a boolean to the array.
80    */
append(boolean b)81   public JSArrayBuilder append(boolean b) {
82     return append(b ? 1 : 0);
83   }
84 
85   /**
86    * Add a collection of strings to the array.
87    */
appendIterator(Iterator<String> iterator)88   public final JSArrayBuilder appendIterator(Iterator<String> iterator) {
89     while (iterator.hasNext()) {
90       append(iterator.next());
91     }
92     return this;
93   }
94 
95   // Adds a string to the array with an option to escape the string or not.
append(String string, boolean escapeString)96   private JSArrayBuilder append(String string, boolean escapeString) {
97     beginElement();
98     if (string != null) {
99       if (escapeString) {
100         escape(string, data);
101       } else {
102         data.append(string);
103       }
104     }
105     return this;
106   }
107 
108   // Returns a string representing the data in this JSArray.
toString()109   @Override public String toString() {
110     return data.toString();
111   }
112 
113   // Double quotes a string and replaces "\" with "\\".
escape(String str, StringBuilder out)114   private static void escape(String str, StringBuilder out) {
115     out.append('"');
116     out.append(str.replaceAll("\\\\", "\\\\\\\\"));
117     out.append('"');
118   }
119 
120   // Trims trailing commas.
trimTrailingCommas()121   private void trimTrailingCommas() {
122     int i = data.length();
123     while (i > 0 && data.charAt(i - 1) == ',') {
124       i--;
125     }
126     if (i < data.length()) {
127       data.delete(i, data.length());
128     }
129   }
130 
charAt(int index)131   public char charAt(int index) {
132     return data.charAt(index);
133   }
134 
length()135   public int length() {
136     return data.length();
137   }
138 
subSequence(int start, int end)139   public CharSequence subSequence(int start, int end) {
140     return data.subSequence(start, end);
141   }
142 }
143