001package com.ganteater.ae.processor;
002
003import java.io.BufferedReader;
004import java.io.File;
005import java.io.FileReader;
006import java.io.IOException;
007import java.util.ArrayList;
008import java.util.List;
009import java.util.StringTokenizer;
010
011import org.apache.commons.lang.StringUtils;
012
013public class ParameterIterator {
014        public static final String CONCURRENTLY = "[concurrently]";
015        public static final String MULTIPLE = "[multiple]";
016        public static final String SINGLE = "[single]";
017        public static final String INDEPENDENT = "[independent]";
018
019        private List<String> fValuesArray = new ArrayList<>();
020        private String fName;
021        private int fStartStep;
022        private ParameterIterator fChield;
023        private String fType;
024        private boolean fParent;
025        private Processor fTestUnit;
026
027        public ParameterIterator(Processor aTestUnit, String aName, int aStartStep) {
028                fName = aName;
029                fStartStep = aStartStep;
030                fTestUnit = aTestUnit;
031        }
032
033        public void addRule(String ruleName, String aRuleParameters) throws IOException {
034                ruleName = StringUtils.lowerCase(ruleName.trim());
035                aRuleParameters = fTestUnit.replaceProperties(aRuleParameters);
036                StringTokenizer paramTokenizer = new StringTokenizer(aRuleParameters, ";");
037
038                switch (ruleName) {
039                case "value":
040                        fValuesArray.add(paramTokenizer.nextToken());
041                        break;
042
043                case "file":
044                        List<String> values = loadFile(new File(fTestUnit.getBaseDir(), aRuleParameters));
045                        fValuesArray.addAll(values);
046                        break;
047
048                case "enum":
049                        while (paramTokenizer.hasMoreTokens()) {
050                                fValuesArray.add(paramTokenizer.nextToken());
051                        }
052                        break;
053
054                case "inc":
055                        String start = null;
056                        String numbers = null;
057
058                        start = paramTokenizer.nextToken();
059                        numbers = paramTokenizer.nextToken();
060
061                        if (start == null)
062                                start = "0";
063                        if (numbers == null)
064                                numbers = "1000";
065
066                        int theStartInt = Integer.parseInt(start);
067                        int theNumbersInt = Integer.parseInt(numbers);
068
069                        if (theNumbersInt > 0)
070                                for (int i = theStartInt; i < theStartInt + theNumbersInt; i++)
071                                        fValuesArray.add(Integer.toString(i));
072                        else
073                                for (int i = theStartInt; i > theStartInt + theNumbersInt; i--)
074                                        fValuesArray.add(Integer.toString(i));
075                        break;
076
077                default:
078                        throw new IllegalArgumentException(
079                                        "Incorrect rule for Iteration line: " + ruleName + ":" + aRuleParameters);
080                }
081
082        }
083
084        public int count() {
085                return fValuesArray.size();
086        }
087
088        public void applyValue(int aCurrentIteration, Processor taskProcessor, List<String> aPropertiesIsSet) {
089
090                if (SINGLE.equalsIgnoreCase(fType)) {
091                        int theCurr = aCurrentIteration - fStartStep;
092
093                        if (theCurr < 0) {
094                                applyDefaultValue(aPropertiesIsSet, taskProcessor);
095                        } else if (theCurr < fValuesArray.size()) {
096                                putValue(taskProcessor, theCurr, aPropertiesIsSet);
097                        } else {
098                                putValue(taskProcessor, 0, aPropertiesIsSet);
099                        }
100
101                } else if (INDEPENDENT.equalsIgnoreCase(fType)) {
102                        int theCurr = aCurrentIteration - fStartStep;
103
104                        if (theCurr < 0) {
105                                applyDefaultValue(aPropertiesIsSet, taskProcessor);
106                        } else if (theCurr < fValuesArray.size()) {
107                                putValue(taskProcessor, aCurrentIteration, aPropertiesIsSet);
108                        }
109
110                } else {
111                        int theCurr = aCurrentIteration - fStartStep;
112                        if (fParent) {
113                                applyChieldValue(aCurrentIteration - fStartStep, taskProcessor, 1, theCurr < 0, aPropertiesIsSet);
114                        }
115                }
116        }
117
118        private void putValue(Processor taskProcessor, int aCurr, List<String> aPropertiesIsSet) {
119                String theName = getName();
120
121                if (aCurr >= fValuesArray.size()) {
122                        aCurr = fValuesArray.size() - 1;
123                }
124                String theLine = fTestUnit.replaceProperties(fValuesArray.get(aCurr));
125                if (!"null".equals(theLine)) {
126                        taskProcessor.setVariableValue(theName, theLine);
127                } else {
128                        taskProcessor.setVariableValue(theName, null);
129                }
130
131                aPropertiesIsSet.add(theName);
132        }
133
134        private void applyDefaultValue(List<String> aPropertiesIsSet, Processor taskProcessor) {
135                String theName = getName();
136                if (aPropertiesIsSet.contains(theName))
137                        return;
138                aPropertiesIsSet.add(theName);
139                putValue(taskProcessor, 0, aPropertiesIsSet);
140        }
141
142        protected void applyChieldValue(int aCurrentIteration, Processor taskProcessor, int aInterval,
143                        boolean aDefaultValue, List<String> aPropertiesIsSet) {
144
145                if (MULTIPLE.equalsIgnoreCase(fType)) {
146                        if (!aDefaultValue) {
147                                int theIndex = (int) (((double) aCurrentIteration / aInterval) % fValuesArray.size());
148                                putValue(taskProcessor, theIndex, aPropertiesIsSet);
149                        } else {
150                                applyDefaultValue(aPropertiesIsSet, taskProcessor);
151                        }
152
153                        if (fChield != null) {
154                                fChield.applyChieldValue(aCurrentIteration, taskProcessor, aInterval * count(), aDefaultValue,
155                                                aPropertiesIsSet);
156                        }
157                } else if (CONCURRENTLY.equalsIgnoreCase(fType)) {
158                        if (!aDefaultValue) {
159                                putValue(taskProcessor, aCurrentIteration, aPropertiesIsSet);
160                        } else {
161                                applyDefaultValue(aPropertiesIsSet, taskProcessor);
162                        }
163
164                        if (fChield != null) {
165                                fChield.applyChieldValue(aCurrentIteration, taskProcessor, fValuesArray.size(), aDefaultValue,
166                                                aPropertiesIsSet);
167                        }
168                }
169
170        }
171
172        public void setChield(ParameterIterator aParameterIterator) {
173                fChield = aParameterIterator;
174        }
175
176        public void setType(String aType) {
177                fType = aType;
178        }
179
180        public String getName() {
181                return fName;
182        }
183
184        public void setParent(boolean aMultipleParent) {
185                fParent = aMultipleParent;
186        }
187
188        public List<String> loadFile(File aFile) throws IOException {
189                List<String> values = new ArrayList<>();
190                try (BufferedReader theFileReader = new BufferedReader(new FileReader(aFile))) {
191                        String line = null;
192                        while ((line = theFileReader.readLine()) != null) {
193                                values.add(line);
194                        }
195                }
196
197                return values;
198        }
199}