root/trunk/src/java/org/jcoderz/commons/logging/CollectionFormat.java

Revision 1011, 11.8 kB (checked in by amandel, 4 years ago)

Aligned svn keyword settings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.logging;
34
35import java.nio.CharBuffer;
36import java.text.FieldPosition;
37import java.text.Format;
38import java.text.ParsePosition;
39import java.util.ArrayList;
40import java.util.Collection;
41import java.util.Iterator;
42import java.util.List;
43
44/**
45 * This format is used for formatting a collection. The begin/end pair can be
46 * set as well as the separator for the collection items and the formatter for
47 * the items.
48 *
49 */
50public class CollectionFormat
51      extends Format
52{
53   private static final long serialVersionUID = 3258126947170400564L;
54
55   /** The separator character between collection items. */
56   private static final String SEPARATOR = ",";
57
58   private static final String LIST_BEGIN = "[";
59   private static final String LIST_END = "]";
60
61   private final String mListBegin;
62   private final String mListEnd;
63   private final Format mListElementFormat;
64   private final String mSeparator;
65
66   private final int mLengthListBegin;
67   private final int mLengthListEnd;
68   private final int mLengthSeparator;
69
70
71   /**
72    * Creates a new instance of this and sets default values for the Strings
73    * denoting the begin or end of the collection as well as the separator for
74    * the collection items.
75    *
76    * @param elementFormat the Format to use for formatting each collection
77    * element.
78    */
79   public CollectionFormat (final Format elementFormat)
80   {
81      this(elementFormat, LIST_BEGIN, LIST_END, SEPARATOR);
82   }
83
84   /**
85    * Creates a new instance of this and configures values for the Strings
86    * denoting the begin or end of the collection as well as the separator for
87    * the collection items. If teh begin and empty markers are both empty or
88    * null, then this might fail to parse empty lists.
89    *
90    * @param elementFormat the Format to use for formatting each collection
91    * element. Must not be null.
92    * @param begin The string to set as start of the collection, might be null,
93    * then there will be no marker for the start of the collection.
94    * @param end The string to set as end of the collection, might be null,
95    * then there will be no marker for the end of the collection.
96    * @param separator The string to set as separator between collection
97    * elements, might be null, then ther will be no separator between the
98    * elements.
99    */
100   public CollectionFormat (
101         final Format elementFormat,
102         final String begin,
103         final String end,
104         final String separator)
105   {
106      super();
107      mListBegin = (begin != null) ? begin : "";
108      mListEnd = (end != null) ? end : "";
109      mListElementFormat = elementFormat;
110      mSeparator = (separator != null) ? separator : "";
111      mLengthListBegin = mListBegin.length();
112      mLengthListEnd = mListEnd.length();
113      mLengthSeparator = mSeparator.length();
114   }
115
116   /**
117    * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
118    *
119    * Parses the supplied string for creating a list of object. If an error
120    * occurs the position is unchanged, the error position is set to the
121    * position where it occurred and null is returrned.
122    * This expects the configured list begin sequence to start at the current
123    * position, the list item to be delimited with the configured delimiter,
124    * the latter not being parsed by the list item parser, and the list being
125    * terminated by the list end sequence. If the list end sequence is set
126    * to null or empty string, then empty lists are not detected.
127    *
128    * @param source The string to parse.
129    * @param pos The current position within <code>source</code>
130    *
131    * @return null if an error occurs, the collection being parsed from the
132    * source string else.
133    */
134   public Object parseObject (String source, ParsePosition pos)
135   {
136      List rc = null;
137      final int len = source.length();
138      boolean errorOccurred = false;
139
140      final CharBuffer sourceBuffer
141            = CharBuffer.wrap(source, pos.getIndex(), source.length());
142
143      final int currentPos = pos.getIndex();
144
145      // the string has to start with the configured list begin char, if it is
146      // set
147      if (beginOfList(sourceBuffer, pos))
148      {
149         rc = new ArrayList();
150
151         if (! (mLengthListEnd != 0 && endOfList(sourceBuffer, pos)))
152         {
153            errorOccurred = parseListElements(
154                  sourceBuffer, source, pos, len, rc);
155
156            if (! (errorOccurred || endOfList(sourceBuffer, pos)))
157            {
158               pos.setErrorIndex(pos.getIndex());
159               errorOccurred = true;
160            }
161         }
162         if (errorOccurred)
163         {
164            rc.clear();
165            rc = null;
166            pos.setIndex(currentPos);
167         }
168      }
169      else
170      {
171         pos.setErrorIndex(pos.getIndex());
172      }
173      return rc;
174   }
175
176   private boolean parseListElements (
177         final CharBuffer sourceBuffer,
178         final String source,
179         final ParsePosition pos,
180         final int len,
181         final List elements)
182   {
183      boolean rc = false;
184
185      // not an empty list
186      do
187      {
188         final Object obj = mListElementFormat.parseObject(source, pos);
189         if (obj == null)
190         {
191            rc = true;
192         }
193         else
194         {
195            elements.add(obj);
196         }
197      }
198      while (separator(sourceBuffer, pos)
199            && (pos.getIndex() < len)
200            && ! rc);
201
202      return rc;
203   }
204
205   /**
206    * Formats a collection of strings.
207    *
208    * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
209    *
210    * @param obj the Object to format. Must be a Collection
211    * @param toAppendTo the StringBuffer where to append to the formatted
212    * Collection.
213    * @param pos the field position.
214    *
215    * @return StringBuffer where the formatted collection has been appended to.
216    *
217    * @throws IllegalArgumentException if <code>obj</code> is not a Collection.
218    */
219   public StringBuffer format (
220         Object obj,
221         StringBuffer toAppendTo,
222         FieldPosition pos)
223   {
224      if (! (obj instanceof Collection))
225      {
226         throw new IllegalArgumentException("The object to format must be "
227               + " a java.util.Collection, but is: " + obj);
228      }
229      pos.setBeginIndex(0);
230      pos.setEndIndex(0);
231
232      final Collection elements = (Collection) obj;
233      final StringBuffer tempBuffer = new StringBuffer(mListBegin);
234      boolean first = true;
235      for (final Iterator iter = elements.iterator(); iter.hasNext(); )
236      {
237         if (first)
238         {
239            first = false;
240         }
241         else
242         {
243            tempBuffer.append(mSeparator);
244         }
245         mListElementFormat.format(iter.next(), tempBuffer, pos);
246      }
247      tempBuffer.append(mListEnd);
248      toAppendTo.append(tempBuffer);
249
250      return toAppendTo;
251   }
252
253   /**
254    * Sets the buffers position to the current parse position and checks whether
255    * the buffer contains an begin-of-list at the current position and if so
256    * updates its position and the index of the supplied parse position.
257    *
258    * @param buffer The buffer storing the line to parse.
259    * @param pos The current parse postion.
260    *
261    * @return true if at end of list or no end of list specifier set;
262    * false, else.
263    */
264   private boolean beginOfList (
265         final CharBuffer buffer,
266         final ParsePosition pos)
267   {
268      boolean rc = false;
269      buffer.position(pos.getIndex());
270      if (mLengthListBegin == 0)
271      {
272         rc = true;
273      }
274      else
275      {
276         if (buffer.remaining() >= mLengthListBegin)
277         {
278            boolean allOk = true;
279            for (int i = 0; i < mLengthListBegin && allOk; ++i)
280            {
281               if (buffer.charAt(i) != mListBegin.charAt(i))
282               {
283                  allOk = false;
284               }
285            }
286            rc = allOk;
287            if (rc)
288            {
289               pos.setIndex(pos.getIndex() + mLengthListBegin);
290               buffer.position(pos.getIndex());
291            }
292         }
293      }
294      return rc;
295   }
296
297   /**
298    * Sets the buffers position to the current parse position and checks whether
299    * the buffer contains an end-of-list at the current position and if so
300    * updates its position and the index of the supplied parse position.
301    *
302    * @param buffer The buffer storing the line to parse.
303    * @param pos The current parse postion.
304    *
305    * @return true if at end of list or no end of list specifier set;
306    * false, else.
307    */
308   private boolean endOfList (
309         final CharBuffer buffer,
310         final ParsePosition pos)
311   {
312      boolean rc = false;
313      buffer.position(pos.getIndex());
314      if (mLengthListEnd == 0)
315      {
316         rc = true;
317      }
318      else
319      {
320         if (buffer.remaining() >= mLengthListEnd)
321         {
322            boolean allOk = true;
323            for (int i = 0; i < mLengthListEnd && allOk; ++i)
324            {
325               if (buffer.charAt(i) != mListEnd.charAt(i))
326               {
327                  allOk = false;
328               }
329            }
330            rc = allOk;
331            if (rc)
332            {
333               pos.setIndex(pos.getIndex() + mLengthListEnd);
334               buffer.position(pos.getIndex());
335            }
336         }
337      }
338      return rc;
339   }
340
341   /**
342    * Sets the buffers position to the current parse position and checks whether
343    * the buffer contains a separator at the current position and if so updates
344    * its position and the index of the supplied parse position.
345    *
346    * @param buffer The buffer storing the line to parse.
347    * @param pos The current parse postion.
348    *
349    * @return true if a separator exists at the current position; false, else.
350    */
351   private boolean separator (final CharBuffer buffer, final ParsePosition pos)
352   {
353      boolean rc = false;
354      boolean allOk = true;
355
356      buffer.position(pos.getIndex());
357
358      if (buffer.remaining() >= mLengthSeparator)
359      {
360         for (int i = 0; i < mLengthSeparator && allOk; ++i)
361         {
362            if (buffer.charAt(i) != mSeparator.charAt(i))
363            {
364               allOk = false;
365            }
366         }
367         rc = allOk;
368         if (rc)
369         {
370            pos.setIndex(pos.getIndex() + mLengthSeparator);
371            buffer.position(pos.getIndex());
372         }
373      }
374      return rc;
375   }
376}
Note: See TracBrowser for help on using the browser.