001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.cfg;
017:
018: import java.util.Iterator;
019: import java.util.NoSuchElementException;
020:
021: /**
022: * Generates all possible permutations of properties in a module.
023: */
024: public class PropertyPermutations {
025:
026: private int currPermIndex;
027:
028: private final int lastProp;
029:
030: private final Property[] properties;
031:
032: private final String[][] values;
033:
034: public PropertyPermutations(Properties properties) {
035: this .properties = properties.toArray();
036: lastProp = this .properties.length - 1;
037: int permCount = countPermutations();
038: values = new String[permCount][];
039: if (this .properties.length > 0) {
040: permute(null, 0);
041: assert (permCount == currPermIndex);
042: } else {
043: values[0] = new String[0];
044: }
045: }
046:
047: public Property[] getOrderedProperties() {
048: return properties;
049: }
050:
051: /**
052: * Enumerates each permutation as an array of strings such that the index of
053: * each string in the array corresponds to the property at the same index in
054: * the array returned from {@link #getOrderedProperties()}.
055: */
056: public Iterator<String[]> iterator() {
057: return new Iterator<String[]>() {
058:
059: private int iterPermIndex;
060:
061: public boolean hasNext() {
062: return iterPermIndex < values.length;
063: }
064:
065: public String[] next() {
066: if (!hasNext()) {
067: throw new NoSuchElementException();
068: }
069: return values[iterPermIndex++];
070: }
071:
072: public void remove() {
073: throw new UnsupportedOperationException("remove");
074: }
075: };
076: }
077:
078: private int countPermutations() {
079: int count = 1;
080: for (int i = 0; i < properties.length; i++) {
081: Property prop = properties[i];
082: String[] options = getPossibilities(prop);
083: assert (options.length > 0);
084: count *= options.length;
085: }
086: return count;
087: }
088:
089: private String[] getPossibilities(Property prop) {
090: String activeValue = prop.getActiveValue();
091: if (activeValue != null) {
092: // This property is fixed.
093: //
094: return new String[] { activeValue };
095: } else {
096: // This property is determined on the client.
097: //
098: return prop.getKnownValues();
099: }
100: }
101:
102: private void permute(String[] soFar, int whichProp) {
103: Property prop = properties[whichProp];
104: String[] options = getPossibilities(prop);
105:
106: for (int i = 0; i < options.length; i++) {
107: String knownValue = options[i];
108:
109: String[] nextStep = new String[whichProp + 1];
110: if (whichProp > 0) {
111: System.arraycopy(soFar, 0, nextStep, 0, soFar.length);
112: }
113: nextStep[whichProp] = knownValue;
114:
115: if (whichProp < lastProp) {
116: permute(nextStep, whichProp + 1);
117: } else {
118: // Finished this permutation.
119: //
120: values[currPermIndex] = nextStep;
121: ++currPermIndex;
122: }
123: }
124: }
125: }
|