1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.host.test.composer;
17 
18 import java.lang.AssertionError;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.stream.Collectors;
23 
24 /**
25  * A {@link Compose} function base class for repeating objects a configurable number of times.
26  */
27 public abstract class IterateBase<T, U> implements Compose<T, U> {
28     protected static final String ITERATIONS_OPTION_NAME = "iterations";
29     protected static final int ITERATIONS_DEFAULT_VALUE = 1;
30 
31     /** Iteration ordering, i.e. cyclical (ABCABC) or sequential (AABBCC). */
32     protected enum OrderOptions { CYCLIC, SEQUENTIAL };
33     protected static final String ORDER_OPTION_NAME = "order";
34     protected static final OrderOptions ORDER_DEFAULT_VALUE = OrderOptions.CYCLIC;
35 
36     protected final int mDefaultValue;
37     protected String mOptionName = ITERATIONS_OPTION_NAME;
38 
IterateBase()39     public IterateBase() {
40         this(ITERATIONS_DEFAULT_VALUE);
41     }
42 
IterateBase(int defaultIterations)43     public IterateBase(int defaultIterations) {
44         mDefaultValue = defaultIterations;
45     }
46 
47     @Override
apply(T args, List<U> input)48     public List<U> apply(T args, List<U> input) {
49         int iterations = getIterationsArgument(args);
50         OrderOptions order = getOrdersArgument(args);
51         switch (order) {
52             case CYCLIC:
53                 return Collections.nCopies(iterations, input)
54                         .stream()
55                         .flatMap(Collection::stream)
56                         .collect(Collectors.toList());
57             case SEQUENTIAL:
58                 return input.stream()
59                         .map(u -> Collections.nCopies(iterations, u))
60                         .flatMap(Collection::stream)
61                         .collect(Collectors.toList());
62         }
63         // We should never get here as the switch statement should exhaust the order options.
64         throw new AssertionError(
65                 String.format("Order option \"%s\" is not supported", order));
66     }
67 
68     /** Returns the number of iterations to run from {@code args}. */
getIterationsArgument(T args)69     protected abstract int getIterationsArgument(T args);
70 
71     /** Returns the order that the iteration should happen in from {@code args}. */
getOrdersArgument(T args)72     protected abstract OrderOptions getOrdersArgument(T args);
73 
74     /** Returns the option name to supply values to this iterator. */
getOptionName()75     protected String getOptionName() {
76         return mOptionName;
77     }
78 
79     /** Sets the option name for supply values to this iterator. */
setOptionName(String name)80     public void setOptionName(String name) {
81         mOptionName = name;
82     }
83 }
84