001: /*
002: * (c) Copyright 2007 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.wrapper;
028:
029: import org.databene.benerator.MultiGeneratorWrapper;
030: import org.databene.benerator.Generator;
031: import org.databene.benerator.IllegalGeneratorStateException;
032: import org.databene.benerator.InvalidGeneratorSetupException;
033: import org.databene.commons.ArrayUtil;
034: import org.databene.commons.NullSafeComparator;
035: import org.databene.commons.ArrayFormat;
036: import org.apache.commons.logging.LogFactory;
037: import org.apache.commons.logging.Log;
038:
039: import java.lang.reflect.Array;
040:
041: /**
042: * Creates arrays of unique combinations of the output of other generators.
043: * Each array element is filled from an own generator,
044: * each used generator is supposed to generate unique values itself.<br/>
045: * <br/>
046: * Created: 17.11.2007 13:37:37
047: */
048: public class UniqueCompositeGenerator<S> extends
049: MultiGeneratorWrapper<S, S[]> {
050:
051: private static final Log logger = LogFactory
052: .getLog(UniqueCompositeGenerator.class);
053:
054: private Class<S> componentType;
055: private Object[] products;
056: private boolean dirty;
057:
058: // constructors ----------------------------------------------------------------------------------------------------
059:
060: public UniqueCompositeGenerator() {
061: super ();
062: dirty = true;
063: }
064:
065: /**
066: * Initializes the generator to an array of source generators
067: */
068: public UniqueCompositeGenerator(Class<S> componentType,
069: Generator<S>... sources) {
070: super (sources);
071: this .componentType = componentType;
072: dirty = true;
073: }
074:
075: // Generator implementation ----------------------------------------------------------------------------------------
076:
077: public Class<S[]> getGeneratedType() {
078: return (Class<S[]>) Array.newInstance(componentType, 0)
079: .getClass();
080: }
081:
082: public void validate() {
083: if (dirty) {
084: super .validate();
085: if (sources.length == 0)
086: throw new InvalidGeneratorSetupException("source",
087: "is null");
088: products = new Object[sources.length];
089: for (int i = 0; i < products.length; i++)
090: if (sources[i].available())
091: products[i] = sources[i].generate();
092: else
093: throw new InvalidGeneratorSetupException(
094: "Sub generator not available: "
095: + sources[i]);
096: dirty = false;
097: }
098: }
099:
100: public boolean available() {
101: if (dirty)
102: validate();
103: return (products != null);
104: }
105:
106: /**
107: * @see org.databene.benerator.Generator#generate()
108: */
109: public S[] generate() {
110: if (!available())
111: throw new IllegalGeneratorStateException(
112: "Generator is not available");
113: S[] result = (S[]) ArrayUtil.copyOfRange(products, 0,
114: products.length);
115: fetchNext(0);
116: if (logger.isDebugEnabled())
117: logger.debug("generated: " + ArrayFormat.format(result));
118: return result;
119: }
120:
121: public void reset() {
122: super .reset();
123: dirty = true;
124: }
125:
126: private void fetchNext(int index) {
127: // check for overrun
128: if (index >= sources.length) {
129: products = null;
130: return;
131: }
132: // if available, fetch the digit's next value
133: boolean rep = false;
134: Generator<S> gen = sources[index];
135: if (gen.available()) {
136: Object tmp = gen.generate();
137: if (!NullSafeComparator.equals(products[index], tmp)) {
138: products[index] = tmp;
139: return;
140: } else
141: rep = true;
142: }
143: // the sorces[i] was not available or returned the same value as before
144: fetchNext(index + 1);
145: if (products != null && !rep) {
146: gen.reset();
147: products[index] = gen.generate();
148: }
149: }
150: }
|