001: /*
002: * (c) Copyright 2006 by Volker Bergmann. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, is permitted under the terms of the
006: * GNU General Public License.
007: *
008: * For redistributing this software or a derivative work under a license other
009: * than the GPL-compatible Free Software License as defined by the Free
010: * Software Foundation or approved by OSI, you must first obtain a commercial
011: * license to this software product from Volker Bergmann.
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
014: * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
015: * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
016: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
017: * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
018: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
019: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
020: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
021: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
022: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
023: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGE.
025: */
026:
027: package org.databene.benerator.sample;
028:
029: import org.databene.benerator.IllegalGeneratorStateException;
030: import org.databene.benerator.InvalidGeneratorSetupException;
031: import org.databene.benerator.Generator;
032: import org.databene.commons.ConversionException;
033: import org.databene.commons.Converter;
034: import org.databene.commons.converter.NoOpConverter;
035: import org.databene.document.csv.CSVLineIterator;
036:
037: import java.io.IOException;
038: import java.io.FileNotFoundException;
039: import java.util.List;
040: import java.util.ArrayList;
041:
042: /**
043: * Sample Generator for values that are read from a CSV file.
044: * The CSV file needs to be comma-separated and has to contain the values
045: * in the first column. The second column optionally may have a weight value.
046: * Example:
047: * <pre>
048: * Alpha,1
049: * Bravo,4
050: * Charly,2
051: * </pre>
052: *
053: * @see WeightedSampleGenerator<br/>
054: * <br/>
055: * Created: 11.06.2006 20:49:33
056: */
057: public class WeightedCSVSampleGenerator<E> implements Generator<E> {
058:
059: /** The URL to read the samples from */
060: private String url;
061:
062: /** The converter to create instances from the CSV cell strings */
063: private Converter<String, E> converter;
064:
065: /** the SampleGenerator utilized for selecting among the samples */
066: private WeightedSampleGenerator<E> source;
067:
068: /** flag that indicates if the generator needs to be initialized */
069: private boolean dirty;
070:
071: // constructors ----------------------------------------------------------------------------------------------------
072:
073: public WeightedCSVSampleGenerator() {
074: this ((String) null);
075: }
076:
077: public WeightedCSVSampleGenerator(String url) {
078: this (url, new NoOpConverter());
079: }
080:
081: public WeightedCSVSampleGenerator(Converter<String, E> converter) {
082: this (null, converter);
083: }
084:
085: public WeightedCSVSampleGenerator(String url,
086: Converter<String, E> converter) {
087: this .source = new WeightedSampleGenerator<E>();
088: this .converter = converter;
089: if (url != null && url.trim().length() > 0)
090: setUrl(url);
091: }
092:
093: // configuration properties ----------------------------------------------------------------------------------------
094:
095: public void setUrl(String url) {
096: this .url = url;
097: this .dirty = true;
098: }
099:
100: public String getUrl() {
101: return url;
102: }
103:
104: // generator interface ---------------------------------------------------------------------------------------------
105:
106: public Class<E> getGeneratedType() {
107: return source.getGeneratedType();
108: }
109:
110: public E generate() {
111: if (dirty)
112: validate();
113: return source.generate();
114: }
115:
116: public void validate() {
117: if (dirty) {
118: try {
119: CSVLineIterator parser = new CSVLineIterator(url);
120: String[] tokens;
121: List<WeightedSample<E>> samples = new ArrayList<WeightedSample<E>>();
122: while ((tokens = parser.next()) != null
123: && tokens.length > 0) {
124: double weight = (tokens.length < 2 ? 1. : Double
125: .parseDouble(tokens[1]));
126: E value = converter.convert(tokens[0]);
127: WeightedSample<E> sample = new WeightedSample<E>(
128: value, weight);
129: samples.add(sample);
130: }
131: WeightedSample<E>[] sampleArray = new WeightedSample[samples
132: .size()];
133: source.setSamples((WeightedSample<E>[]) samples
134: .toArray(sampleArray));
135: dirty = false;
136: } catch (FileNotFoundException e) {
137: throw new InvalidGeneratorSetupException("url",
138: "not found: " + url);
139: } catch (IOException e) {
140: throw new IllegalGeneratorStateException(e); // file access was interrupted, no fail-over
141: } catch (ConversionException e) {
142: throw new InvalidGeneratorSetupException(
143: "URL content not valid", e);
144: }
145: }
146: }
147:
148: public void reset() {
149: source.reset();
150: }
151:
152: public void close() {
153: source.close();
154: }
155:
156: public boolean available() {
157: return source.available();
158: }
159:
160: // java.lang.Object overrides --------------------------------------------------------------------------------------
161:
162: public String toString() {
163: return getClass().getSimpleName() + "[source=" + source
164: + ", converter=" + converter + ']';
165: }
166: }
|