1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.transform.copiers;
17
18 import java.util.Enumeration;
19 import java.util.Locale;
20
21 import net.sf.morph.Defaults;
22 import net.sf.morph.transform.Converter;
23 import net.sf.morph.transform.Copier;
24 import net.sf.morph.transform.DecoratedConverter;
25 import net.sf.morph.transform.DecoratedCopier;
26 import net.sf.morph.transform.transformers.BaseTransformer;
27 import net.sf.morph.util.MorphStringTokenizer;
28
29 /**
30 * Parses text into multiple parts for storage in a container. For example, the
31 * text <code>{ 1, 2, 3 }</code> code be converted into an
32 * <code>Integer[]</code> array like this:
33 *
34 * <pre>
35 * String str = "{ 1, 2, 3 }";
36 *
37 * TextToContainerCopier copier = new TextToContainerCopier();
38 *
39 * Integer[] array = (Integer[]) copier.convert(Integer[].class, str);
40 * </pre>
41 *
42 * <b>Configuration parameters</b>
43 * <ul>
44 * <li><code>ignoredCharacters</code> characters that are completely ignored
45 * in the source. The default characters (specified by
46 * {@link #DEFAULT_IGNORED_CHARACTERS}) are often used as grouping type
47 * characters and probably aren't part of the information to be extracted to the
48 * destination object.</li>
49 * <li><code>delimiter</code> characters that are used to separate the
50 * different elements to be copied to the container. The default characters are
51 * specified by {@link #DEFAULT_DELIMITERS}.
52 * </ul>
53 *
54 * @author Matt Sgarlata
55 * @since Apr 9, 2007
56 */
57 public class TextToContainerCopier extends BaseTransformer implements DecoratedConverter, DecoratedCopier {
58 /** Default delimiters */
59 public static final String DEFAULT_DELIMITERS = " ,|";
60
61 /** Default ignored characters */
62 public static final String DEFAULT_IGNORED_CHARACTERS = "()[]{}";
63
64 private String delimiters = DEFAULT_DELIMITERS;
65 private String ignoredCharacters = DEFAULT_IGNORED_CHARACTERS;
66
67 private Converter textConverter = Defaults.createTextConverter();
68 private Copier containerCopier = Defaults.createContainerCopier();
69
70 /**
71 * {@inheritDoc}
72 */
73 protected Object convertImpl(Class destinationClass, Object source, Locale locale) throws Exception {
74 Enumeration tokenizer = getTokenizer(source, locale);
75
76
77
78 Object destination = createNewInstance(destinationClass, tokenizer);
79 getContainerCopier().copy(destination, tokenizer, locale);
80 return destination;
81 }
82
83 /**
84 * {@inheritDoc}
85 */
86 protected void copyImpl(Object destination, Object source, Locale locale, Integer preferredTransformationType) throws Exception {
87 Enumeration tokenizer = getTokenizer(source, locale);
88 getContainerCopier().copy(destination, tokenizer, locale);
89 }
90
91 /**
92 * Constructs a StringTokenizer that can be passed directly to the
93 * <code>containerCopier</code> to complete the transformation.
94 *
95 * @param source
96 * the source, as passed in by the user
97 * @param locale
98 * the locale in which the transformation is to take place
99 * @return a StringTokenizer that can be passed directly to the
100 * <code>containerCopier</code> to complete the transformation
101 */
102 protected Enumeration getTokenizer(Object source, Locale locale) {
103
104 String sourceStr = (String) getTextConverter().convert(String.class, source, locale);
105 sourceStr = removeIgnoredCharacters(sourceStr, getIgnoredCharacters());
106
107 return new MorphStringTokenizer(sourceStr, getDelimiters());
108 }
109
110 /**
111 * Remove all characters contained in <code>ignoredCharacters</code> from
112 * <code>source</code>.
113 *
114 * @param source
115 * the String from which characters are to be removed
116 * @param ignoredCharacters
117 * the characters to be removed
118 * @return a copy of <code>source</code>, but with all characters
119 * contained in <code>ignoredCharacters</code> removed
120 */
121 protected String removeIgnoredCharacters(String source, String ignoredCharacters) {
122 if (source == null) {
123 return null;
124 }
125 if (ignoredCharacters == null || "".equals(ignoredCharacters)) {
126 return source;
127 }
128
129 StringBuffer buffer = new StringBuffer(source.length());
130 for (int i=0; i<source.length(); i++) {
131 for (int j=0; j<ignoredCharacters.length(); j++ ) {
132
133 if (source.charAt(i) == ignoredCharacters.charAt(j)) {
134 break;
135 }
136
137 if (j == ignoredCharacters.length() - 1) {
138 buffer.append(source.charAt(i));
139 }
140 }
141 }
142 return buffer.toString();
143 }
144
145 /**
146 * {@inheritDoc}
147 */
148 protected Class[] getDestinationClassesImpl() throws Exception {
149 return getContainerCopier().getDestinationClasses();
150 }
151
152 /**
153 * {@inheritDoc}
154 */
155 protected Class[] getSourceClassesImpl() throws Exception {
156 return getTextConverter().getSourceClasses();
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 protected boolean isWrappingRuntimeExceptions() {
163 return false;
164 }
165
166 /**
167 * Returns the characters that are used to separate the different elements
168 * to be copied to the container.
169 *
170 * @return the characters that are used to separate the different elements
171 * to be copied to the container.
172 */
173 public String getDelimiters() {
174 return delimiters;
175 }
176
177 /**
178 * Sets the characters that are used to separate the different elements to
179 * be copied to the container.
180 *
181 * @param delimiters
182 * the characters that are used to separate the different
183 * elements to be copied to the container
184 */
185 public void setDelimiters(String delimiters) {
186 this.delimiters = delimiters;
187 }
188
189 /**
190 * Returns characters that are completely ignored in the source.
191 *
192 * @return characters that are completely ignored in the source
193 */
194 public String getIgnoredCharacters() {
195 return ignoredCharacters;
196 }
197
198 /**
199 * Sets the characters that are completely ignored in the source.
200 *
201 * @param ignoredCharacters
202 * the characters that are completely ignored in the source
203 */
204 public void setIgnoredCharacters(String ignoredCharacters) {
205 this.ignoredCharacters = ignoredCharacters;
206 }
207
208 /**
209 * Get the text converter used by this TextToContainerCopier.
210 * @return Converter
211 */
212 public Converter getTextConverter() {
213 return textConverter;
214 }
215
216 /**
217 * Set the text converter used by this TextToContainerCopier.
218 * @param textConverter
219 */
220 public void setTextConverter(Converter textConverter) {
221 this.textConverter = textConverter;
222 }
223
224 /**
225 * Get the container copier used by this TextToContainerCopier.
226 * @return Copier
227 */
228 public Copier getContainerCopier() {
229 return containerCopier;
230 }
231
232 /**
233 * Set the container copier used by this TextToContainerCopier.
234 * @param containerCopier
235 */
236 public void setContainerCopier(Copier containerCopier) {
237 this.containerCopier = containerCopier;
238 }
239
240 }