001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.text;
019:
020: import java.io.Serializable;
021: import java.security.AccessController;
022: import java.security.PrivilegedAction;
023:
024: import org.apache.harmony.text.internal.nls.Messages;
025:
026: /**
027: * Format is the abstract superclass of classes which format and parse objects
028: * according to Locale specific rules.
029: */
030: public abstract class Format implements Serializable, Cloneable {
031:
032: private static final long serialVersionUID = -299282585814624189L;
033:
034: /**
035: * Constructs a new instance of Format.
036: *
037: */
038: public Format() {
039: }
040:
041: /**
042: * Answers a copy of this Format.
043: *
044: * @return a shallow copy of this Format
045: *
046: * @see java.lang.Cloneable
047: */
048: @Override
049: public Object clone() {
050: try {
051: return super .clone();
052: } catch (CloneNotSupportedException e) {
053: return null;
054: }
055: }
056:
057: String convertPattern(String template, String fromChars,
058: String toChars, boolean check) {
059: if (!check && fromChars.equals(toChars)) {
060: return template;
061: }
062: boolean quote = false;
063: StringBuilder output = new StringBuilder();
064: int length = template.length();
065: for (int i = 0; i < length; i++) {
066: int index;
067: char next = template.charAt(i);
068: if (next == '\'') {
069: quote = !quote;
070: }
071: if (!quote && (index = fromChars.indexOf(next)) != -1) {
072: output.append(toChars.charAt(index));
073: } else if (check
074: && !quote
075: && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
076: // text.05=Invalid pattern char {0} in {1}
077: throw new IllegalArgumentException(Messages.getString(
078: "text.05", String.valueOf(next), template)); //$NON-NLS-1$
079: } else {
080: output.append(next);
081: }
082: }
083: if (quote) {
084: // text.04=Unterminated quote
085: throw new IllegalArgumentException(Messages
086: .getString("text.04")); //$NON-NLS-1$
087: }
088: return output.toString();
089: }
090:
091: /**
092: * Formats the specified object using the rules of this Format.
093: *
094: *
095: * @param object
096: * the object to format
097: * @return the formatted String
098: *
099: * @exception IllegalArgumentException
100: * when the object cannot be formatted by this Format
101: */
102: public final String format(Object object) {
103: return format(object, new StringBuffer(), new FieldPosition(0))
104: .toString();
105: }
106:
107: /**
108: * Formats the specified object into the specified StringBuffer using the
109: * rules of this Format. If the field specified by the FieldPosition is
110: * formatted, set the begin and end index of the formatted field in the
111: * FieldPosition.
112: *
113: * @param object
114: * the object to format
115: * @param buffer
116: * the StringBuffer
117: * @param field
118: * the FieldPosition
119: * @return the StringBuffer parameter <code>buffer</code>
120: *
121: * @exception IllegalArgumentException
122: * when the object cannot be formatted by this Format
123: */
124: public abstract StringBuffer format(Object object,
125: StringBuffer buffer, FieldPosition field);
126:
127: /**
128: * Formats the specified object using the rules of this format and returns
129: * an AttributedCharacterIterator with the formatted String and no
130: * attributes.
131: * <p>
132: * Subclasses should return an AttributedCharacterIterator with the
133: * appropriate attributes.
134: *
135: * @param object
136: * the object to format
137: * @return an AttributedCharacterIterator with the formatted object and
138: * attributes
139: *
140: * @exception IllegalArgumentException
141: * when the object cannot be formatted by this Format
142: */
143: public AttributedCharacterIterator formatToCharacterIterator(
144: Object object) {
145: return new AttributedString(format(object)).getIterator();
146: }
147:
148: /**
149: * Parse the specified String using the rules of this Format.
150: *
151: * @param string
152: * the String to parse
153: * @return the object resulting from the parse
154: *
155: * @exception ParseException
156: * when an error occurs during parsing
157: */
158: public Object parseObject(String string) throws ParseException {
159: ParsePosition position = new ParsePosition(0);
160: Object result = parseObject(string, position);
161: if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
162: throw new ParseException(null, position.getErrorIndex());
163: }
164: return result;
165: }
166:
167: /**
168: * Parse the specified String starting at the index specified by the
169: * ParsePosition. If the string is successfully parsed, the index of the
170: * ParsePosition is updated to the index following the parsed text.
171: *
172: * @param string
173: * the String to parse
174: * @param position
175: * the ParsePosition, updated on return with the index following
176: * the parsed text, or on error the index is unchanged and the
177: * error index is set to the index where the error occurred
178: * @return the object resulting from the parse, or null if there is an error
179: */
180: public abstract Object parseObject(String string,
181: ParsePosition position);
182:
183: /*
184: * Gets private field value by reflection.
185: *
186: * @param fieldName the field name to be set @param target the object which
187: * field to be gotten
188: */
189: static Object getInternalField(final String fieldName,
190: final Object target) {
191: Object value = AccessController
192: .doPrivileged(new PrivilegedAction<Object>() {
193: public Object run() {
194: Object result = null;
195: java.lang.reflect.Field field = null;
196: try {
197: field = target.getClass().getDeclaredField(
198: fieldName);
199: field.setAccessible(true);
200: result = field.get(target);
201: } catch (Exception e1) {
202: return null;
203: }
204: return result;
205: }
206: });
207: return value;
208: }
209:
210: static boolean upTo(String string, ParsePosition position,
211: StringBuffer buffer, char stop) {
212: int index = position.getIndex(), length = string.length();
213: boolean lastQuote = false, quote = false;
214: while (index < length) {
215: char ch = string.charAt(index++);
216: if (ch == '\'') {
217: if (lastQuote) {
218: buffer.append('\'');
219: }
220: quote = !quote;
221: lastQuote = true;
222: } else if (ch == stop && !quote) {
223: position.setIndex(index);
224: return true;
225: } else {
226: lastQuote = false;
227: buffer.append(ch);
228: }
229: }
230: position.setIndex(index);
231: return false;
232: }
233:
234: static boolean upToWithQuotes(String string,
235: ParsePosition position, StringBuffer buffer, char stop,
236: char start) {
237: int index = position.getIndex(), length = string.length(), count = 1;
238: boolean quote = false;
239: while (index < length) {
240: char ch = string.charAt(index++);
241: if (ch == '\'') {
242: quote = !quote;
243: }
244: if (!quote) {
245: if (ch == stop) {
246: count--;
247: }
248: if (count == 0) {
249: position.setIndex(index);
250: return true;
251: }
252: if (ch == start) {
253: count++;
254: }
255: }
256: buffer.append(ch);
257: }
258: // text.07=Unmatched braces in the pattern
259: throw new IllegalArgumentException(Messages
260: .getString("text.07")); //$NON-NLS-1$
261: }
262:
263: /**
264: * This inner class is used to represent Format attributes in the
265: * AttributedCharacterIterator that formatToCharacterIterator() method
266: * returns in the Format subclasses.
267: */
268: public static class Field extends
269: AttributedCharacterIterator.Attribute {
270:
271: private static final long serialVersionUID = 276966692217360283L;
272:
273: /**
274: * Constructs a new instance of Field with the given fieldName.
275: */
276: protected Field(String fieldName) {
277: super(fieldName);
278: }
279: }
280: }
|