/* * Copyright (c) 2007 Design Maximum - http://www.designmaximum.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package er.selenium.filters; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSMutableArray; import com.webobjects.foundation.NSMutableDictionary; import er.selenium.SeleniumTest; import er.selenium.SeleniumTest.Element; public class SeleniumRepeatExpanderTestFilter extends SeleniumTestFilterHelper implements SeleniumTestFilter { protected static class LoopData { enum PlacementType { Target, Value }; NSArray<String> values; int targetOffset; PlacementType placement; LoopData(NSArray<String> aValues, int aTargetOffset, PlacementType aPlacement) { values = aValues; targetOffset = aTargetOffset; placement = aPlacement; } } protected void generateIterations(NSMutableArray<SeleniumTest.Element> elements, int repeatIndex, int doneIndex) { NSMutableDictionary<Integer, LoopData> loopData = new NSMutableDictionary<Integer, LoopData>(); int repetitionCount = -1; for (int i = repeatIndex + 1; i < doneIndex; ++i) { SeleniumTest.Element element = elements.get(i); if (element instanceof SeleniumTest.MetaCommand) { SeleniumTest.MetaCommand metaCommand = (SeleniumTest.MetaCommand)element; String mcName = metaCommand.getName(); if (mcName.equals("values") || mcName.equals("targets")) { if (!(elements.get(i + 1) instanceof SeleniumTest.Command)) { throw new RuntimeException("There must be a valid command immediately after 'values' or 'targets' metacommand"); } int relTargetIndex = i + 1 - repeatIndex; loopData.setObjectForKey(new LoopData(metaCommand.arguments(), relTargetIndex, mcName.equals("values") ? LoopData.PlacementType.Value : LoopData.PlacementType.Target), Integer.valueOf(relTargetIndex)); repetitionCount = metaCommand.arguments().count(); elements.set(i, new SeleniumTest.Comment('#' + mcName)); } } } if (loopData.count() == 0) { throw new RuntimeException("No 'values' or 'targets' metacommands specified between 'repeat' and 'done'"); } for (LoopData ld : loopData.allValues()) { if (ld.values.count() != repetitionCount) { throw new RuntimeException("All 'values' and 'targets' metacommands inside 'repeat'-'done' repetition must have equal number of arguments"); } } elements.set(repeatIndex, new SeleniumTest.Comment("#repeat")); elements.set(doneIndex, new SeleniumTest.Comment("#done")); int insertIndex = doneIndex; for (int j = 0; j < repetitionCount; ++j) { elements.insertObjectAtIndex(new SeleniumTest.Comment("#iteration"), insertIndex++); for (int i = repeatIndex + 1; i < doneIndex; ++i) { LoopData data = loopData.objectForKey(Integer.valueOf(i - repeatIndex)); if (data != null) { SeleniumTest.Command newCommand = ((SeleniumTest.Command)elements.objectAtIndex(i)).clone(); switch (data.placement) { case Target: elements.insertObjectAtIndex(new SeleniumTest.Comment("#target " + data.values.get(j)), insertIndex++); newCommand.setTarget(data.values.get(j)); break; case Value: elements.insertObjectAtIndex(new SeleniumTest.Comment("#value " + data.values.get(j)), insertIndex++); newCommand.setValue(data.values.get(j)); break; default: break; } elements.insertObjectAtIndex(newCommand, insertIndex++); } else { elements.insertObjectAtIndex(elements.get(i).clone(), insertIndex++); } } } } @Override protected void processTestElements(NSMutableArray<Element> elements) { int repeatIndex = -1; boolean shouldProcess; do { shouldProcess = false; for (int i = 0; i < elements.count(); ++ i) { SeleniumTest.Element element = elements.get(i); if (element instanceof SeleniumTest.MetaCommand) { SeleniumTest.MetaCommand metaCommand = (SeleniumTest.MetaCommand)element; if (metaCommand.getName().equals("repeat")) { repeatIndex = i; } else if (metaCommand.getName().equals("done")) { generateIterations(elements, repeatIndex, i); shouldProcess = true; } } } } while (shouldProcess); } }