Config.java revision 3c6572b8953e3d636cdf4d8d26583873b2dd1f25
1cfb3d242306311ce27ec51bf511764377c173a7cKiran Ryali + Christian Williamspackage org.robolectric.annotation;
2dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao
39cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrishimport android.app.Application;
4f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport org.jetbrains.annotations.NotNull;
5f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
6f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.Annotation;
7f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.Documented;
8f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.ElementType;
9f6e6129091939d868f32182a3dbba7ca0188e515ChrisHennickAtGoogleimport java.lang.annotation.Inherited;
10f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.Retention;
11f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.RetentionPolicy;
12f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.lang.annotation.Target;
13f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williamsimport java.util.Arrays;
14c77f5791f081893a18f9db753bb5022269a7c5a6Simon Arlottimport java.util.HashSet;
1523a26cc3e5b33c0503a99847292ac99817f5af43Christian Williamsimport java.util.Properties;
16c77f5791f081893a18f9db753bb5022269a7c5a6Simon Arlottimport java.util.Set;
17f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
18dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao/**
19c7482da584ddaa03f91afa7b785ed17fa084aa47Erich Douglass * Configuration settings that can be used on a per-class or per-test basis.
20dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao */
21f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams@Documented
22f6e6129091939d868f32182a3dbba7ca0188e515ChrisHennickAtGoogle@Inherited
23f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams@Retention(RetentionPolicy.RUNTIME)
24f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams@Target({ElementType.TYPE, ElementType.METHOD})
257be4d2ba0e45483ad70cbd994955ae1b70afafdcKiran Ryali + Christian Williamspublic @interface Config {
260bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  String NONE = "--none";
270bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  String DEFAULT = "--default";
280bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  String DEFAULT_RES_FOLDER = "res";
290bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  String DEFAULT_ASSET_FOLDER = "assets";
30ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny  String DEFAULT_BUILD_FOLDER = "build";
3129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
3229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
33074a38a2ee8dd8cb1904853aebf2f30146d563a2Mike Grafton   * The Android SDK level to emulate. If not specified, Robolectric defaults to API 16.
348c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass   * This value will also be set as Build.VERSION.SDK_INT.
3583bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
3683bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The Android SDK level to emulate.
3729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
3881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish  int[] sdk() default {};
3929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
4029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
4129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * The Android manifest file to load; Robolectric will look relative to the current directory.
4229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * Resources and assets will be loaded relative to the manifest.
4329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
4429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * If not specified, Robolectric defaults to {@code AndroidManifest.xml}.
4529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
4629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * If your project has no manifest or resources, use {@link Config#NONE}.
4783bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
4883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The Android manifest file to load.
4929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
5029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  String manifest() default DEFAULT;
5129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
5229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
530bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   * Reference to the BuildConfig class created by the Gradle build system.
540bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   *
550bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   * @return Reference to BuildConfig class.
560bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   */
570bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  Class<?> constants() default Void.class;
580bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
590bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  /**
609cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   * The {@link android.app.Application} class to use in the test, this takes precedence over any application
619cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   * specified in the AndroidManifest.xml.
6283bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
6383bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The {@link android.app.Application} class to use in the test.
649cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   */
659cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish  Class<? extends Application> application() default Application.class;
669cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
679cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish  /**
68bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * Java package name where the "R.class" file is located. This only needs to be specified if you define
69bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * an {@code applicationId} associated with {@code productFlavors} or specify {@code applicationIdSuffix}
70bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * in your build.gradle.
71bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   *
72bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to the {@code applicationId}.</p>
73bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   *
74bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * @return The java package name for R.class.
75bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   */
76bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass  String packageName() default "";
77bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass
78bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass  /**
793c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   * The ABI split to use when locating resources and AndroidManifest.xml
803c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   *
813c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   * <p>You do not typically have to set this, unless you are utilizing the ABI split feature</p>
823c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   *
833c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   * @return The ABI split to test with
843c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai   */
853c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai  String abiSplit() default "";
863c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai
873c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai  /**
8829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * Qualifiers for the resource resolution, such as "fr-normal-port-hdpi".
8929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
9083bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Qualifiers used for resource resolution.
9129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
9229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  String qualifiers() default "";
9329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
9429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
956b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   * The directory from which to load resources.  This should be relative to the directory containing AndroidManifest.xml.
9683bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
97bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to {@code res}.</p>
9883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
9983bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Android resource directory.
1005277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John   */
1016b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  String resourceDir() default DEFAULT_RES_FOLDER;
1026b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass
1036b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  /**
1046b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   * The directory from which to load assets. This should be relative to the directory containing AndroidManifest.xml.
10583bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
106bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to {@code assets}.</p>
10783bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
10883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Android asset directory.
1096b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   */
1106b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  String assetDir() default DEFAULT_ASSET_FOLDER;
1115277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John
1125277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John  /**
113ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   * The directory where application files are created during the application build process.
114ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   *
115ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   * <p>If not specified, Robolectric defaults to {@code build}.</p>
116ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   *
117ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   * @return Android build directory.
118ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny   */
119ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny  String buildDir() default DEFAULT_BUILD_FOLDER;
120ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny
121ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny  /**
12229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * A list of shadow classes to enable, in addition to those that are already present.
12383bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
12483bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return A list of additional shadow classes to enable.
12529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
12629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  Class<?>[] shadows() default {};
127d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
128d6cef1bcc644c7152d0716b8d33eb25054894836David Sun  /**
129d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   * A list of instrumented packages, in addition to those that are already instrumented.
130d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   *
131d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   * @return A list of additional instrumented packages.
132d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   */
133d6cef1bcc644c7152d0716b8d33eb25054894836David Sun  String[] instrumentedPackages() default {};
13429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
135ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson  /**
136ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson   * A list of folders containing Android Libraries on which this project depends.
13783bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
13883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return A list of Android Libraries.
139ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson   */
140ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson  String[] libraries() default {};
141ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
1420bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  class Implementation implements Config {
14381a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private final int[] sdk;
14429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final String manifest;
14529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final String qualifiers;
1465277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    private final String resourceDir;
1476b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    private final String assetDir;
148ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny    private final String buildDir;
149bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    private final String packageName;
1503c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai    private final String abiSplit;
1510bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private final Class<?> constants;
15229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final Class<?>[] shadows;
153d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    private final String[] instrumentedPackages;
1549cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    private final Class<? extends Application> application;
155ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    private final String[] libraries;
15629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
1570bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    public static Config fromProperties(Properties properties) {
1580bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (properties == null || properties.size() == 0) return null;
15929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return new Implementation(
16081a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish          parseIntArrayProperty(properties.getProperty("sdk", "")),
1610bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("manifest", DEFAULT),
1620bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("qualifiers", ""),
163bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass          properties.getProperty("packageName", ""),
1643c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai          properties.getProperty("abiSplit", ""),
1650bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("resourceDir", Config.DEFAULT_RES_FOLDER),
1660bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("assetDir", Config.DEFAULT_ASSET_FOLDER),
167ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny          properties.getProperty("buildDir", Config.DEFAULT_BUILD_FOLDER),
1680bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseClasses(properties.getProperty("shadows", "")),
169d6cef1bcc644c7152d0716b8d33eb25054894836David Sun          parseStringArrayProperty(properties.getProperty("instrumentedPackages", "")),
1700bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseApplication(properties.getProperty("application", "android.app.Application")),
17181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish          parseStringArrayProperty(properties.getProperty("libraries", "")),
1720bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseClass(properties.getProperty("constants", ""))
17329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      );
17429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
17523a26cc3e5b33c0503a99847292ac99817f5af43Christian Williams
1760bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private static Class<?> parseClass(String className) {
1770bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (className.isEmpty()) return null;
1780bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      try {
1790bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        return Implementation.class.getClassLoader().loadClass(className);
1800bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      } catch (ClassNotFoundException e) {
1810bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        throw new RuntimeException("Could not load class: " + className);
1820bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      }
1830bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    }
1840bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
1850bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private static Class<?>[] parseClasses(String input) {
1860bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (input.isEmpty()) return new Class[0];
1870bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      final String[] classNames = input.split("[, ]+");
1880bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      final Class[] classes = new Class[classNames.length];
18929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      for (int i = 0; i < classNames.length; i++) {
1900bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        classes[i] = parseClass(classNames[i]);
19129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      }
19229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return classes;
19329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
19423a26cc3e5b33c0503a99847292ac99817f5af43Christian Williams
1950bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    @SuppressWarnings("unchecked")
1969cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    private static <T extends Application> Class<T> parseApplication(String className) {
1970bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return (Class<T>) parseClass(className);
1989cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    }
1999cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
20081a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private static String[] parseStringArrayProperty(String property) {
20181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      if (property.isEmpty()) return new String[0];
20281a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return property.split("[, ]+");
203ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    }
204ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
20581a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private static int[] parseIntArrayProperty(String property) {
20681a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      String[] parts = parseStringArrayProperty(property);
20781a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      int[] result = new int[parts.length];
20881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      for (int i = 0; i < parts.length; i++) {
20981a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish        result[i] = Integer.parseInt(parts[i]);
21081a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      }
21181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
21281a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return result;
21381a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    }
21481a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
2153c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai    public Implementation(int[] sdk, String manifest, String qualifiers, String packageName, String abiSplit, String resourceDir, String assetDir, String buildDir, Class<?>[] shadows, String[] instrumentedPackages, Class<? extends Application> application, String[] libraries, Class<?> constants) {
2168c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      this.sdk = sdk;
21729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.manifest = manifest;
21829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.qualifiers = qualifiers;
219bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = packageName;
2203c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai      this.abiSplit = abiSplit;
2215277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John      this.resourceDir = resourceDir;
2226b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.assetDir = assetDir;
223ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny      this.buildDir = buildDir;
22429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.shadows = shadows;
225d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = instrumentedPackages;
2269cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish      this.application = application;
227ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      this.libraries = libraries;
2280bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      this.constants = constants;
22929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
230f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
23128950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom    public Implementation(Config other) {
2328c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      this.sdk = other.sdk();
23328950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.manifest = other.manifest();
23428950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.qualifiers = other.qualifiers();
235bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = other.packageName();
2363c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai      this.abiSplit = other.abiSplit();
23728950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.resourceDir = other.resourceDir();
23828950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.assetDir = other.assetDir();
239ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny      this.buildDir = other.buildDir();
24028950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.constants = other.constants();
24128950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.shadows = other.shadows();
242d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = other.instrumentedPackages();
24328950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.application = other.application();
24428950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.libraries = other.libraries();
24528950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom    }
24628950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom
24729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    public Implementation(Config baseConfig, Config overlayConfig) {
24881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      this.sdk = pickSdk(baseConfig.sdk(), overlayConfig.sdk(), new int[0]);
24929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.manifest = pick(baseConfig.manifest(), overlayConfig.manifest(), DEFAULT);
25029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.qualifiers = pick(baseConfig.qualifiers(), overlayConfig.qualifiers(), "");
251bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = pick(baseConfig.packageName(), overlayConfig.packageName(), "");
2523c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai      this.abiSplit = pick(baseConfig.abiSplit(), overlayConfig.abiSplit(), "");
2536b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.resourceDir = pick(baseConfig.resourceDir(), overlayConfig.resourceDir(), Config.DEFAULT_RES_FOLDER);
2546b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.assetDir = pick(baseConfig.assetDir(), overlayConfig.assetDir(), Config.DEFAULT_ASSET_FOLDER);
255ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny      this.buildDir = pick(baseConfig.buildDir(), overlayConfig.buildDir(), Config.DEFAULT_BUILD_FOLDER);
256b3c13990ef697c1f25635529ff485760cb5cf644Jen Mendez      this.constants = pick(baseConfig.constants(), overlayConfig.constants(), Void.class);
257ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
2580bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      Set<Class<?>> shadows = new HashSet<>();
25929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      shadows.addAll(Arrays.asList(baseConfig.shadows()));
26029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      shadows.addAll(Arrays.asList(overlayConfig.shadows()));
26129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.shadows = shadows.toArray(new Class[shadows.size()]);
262ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
263d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      Set<String> instrumentedPackages = new HashSet<>();
264d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      instrumentedPackages.addAll(Arrays.asList(baseConfig.instrumentedPackages()));
265d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      instrumentedPackages.addAll(Arrays.asList(overlayConfig.instrumentedPackages()));
266d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = instrumentedPackages.toArray(new String[instrumentedPackages.size()]);
267d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
2683af772e6f01a3da6c2eff85c100a30cc2ea33909Ibraheem Zaman      this.application = pick(baseConfig.application(), overlayConfig.application(), Application.class);
269ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
2700bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      Set<String> libraries = new HashSet<>();
271ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      libraries.addAll(Arrays.asList(baseConfig.libraries()));
272ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      libraries.addAll(Arrays.asList(overlayConfig.libraries()));
273ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      this.libraries = libraries.toArray(new String[libraries.size()]);
27429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
275f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
27629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private <T> T pick(T baseValue, T overlayValue, T nullValue) {
2770bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return overlayValue != null ? (overlayValue.equals(nullValue) ? baseValue : overlayValue) : null;
27829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
279f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
28081a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private int[] pickSdk(int[] baseValue, int[] overlayValue, int[] nullValue) {
28181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return Arrays.equals(overlayValue, nullValue) ? baseValue : overlayValue;
28281a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    }
28381a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
2846b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
28581a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    public int[] sdk() {
2868c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      return sdk;
28729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
288f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
2896b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
2906b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String manifest() {
29129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return manifest;
29229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
29348f95f3e0955035946f7c416dec56219a9b19886Christian Williams
2949cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    @Override
2950bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    public Class<?> constants() {
2960bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return constants;
2970bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    }
2980bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
2990bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    @Override
3009cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    public Class<? extends Application> application() {
3019cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish      return application;
3029cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    }
3039cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
3046b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
3056b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String qualifiers() {
30629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return qualifiers;
30729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
308f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
3095277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    @Override
310bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    public String packageName() {
311bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      return packageName;
312bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    }
313bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass
314bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    @Override
3153c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai    public String abiSplit() {
3163c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai      return abiSplit;
3173c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai    }
3183c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai
3193c6572b8953e3d636cdf4d8d26583873b2dd1f25Hilal Alsibai    @Override
3205277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    public String resourceDir() {
3215277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John      return resourceDir;
3225277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    }
3235277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John
3246b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
3256b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String assetDir() {
3266b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      return assetDir;
3276b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    }
3286b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass
3296b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
330ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny    public String buildDir() {
331ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny      return buildDir;
332ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny    }
333ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny
334ed249b15fa2ff94708d5f079f94284356a96c2a4Sean Kenny    @Override
3356b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public Class<?>[] shadows() {
33629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return shadows;
33729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
338f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
3396b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
340d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    public String[] instrumentedPackages() {
341d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      return instrumentedPackages;
342d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    }
343d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
344d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    @Override
3456b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String[] libraries() {
346ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      return libraries;
347ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    }
348ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
3496b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @NotNull @Override
3506b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public Class<? extends Annotation> annotationType() {
35129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return Config.class;
35229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
35329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  }
354dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao}
355