Config.java revision f6e6129091939d868f32182a3dbba7ca0188e515
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";
3029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
3129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
32074a38a2ee8dd8cb1904853aebf2f30146d563a2Mike Grafton   * The Android SDK level to emulate. If not specified, Robolectric defaults to API 16.
338c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass   * This value will also be set as Build.VERSION.SDK_INT.
3483bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
3583bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The Android SDK level to emulate.
3629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
3781a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish  int[] sdk() default {};
3829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
3929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
4029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * The Android manifest file to load; Robolectric will look relative to the current directory.
4129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * Resources and assets will be loaded relative to the manifest.
4229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
4329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * If not specified, Robolectric defaults to {@code AndroidManifest.xml}.
4429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
4529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * If your project has no manifest or resources, use {@link Config#NONE}.
4683bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
4783bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The Android manifest file to load.
4829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
4929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  String manifest() default DEFAULT;
5029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
5129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
520bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   * Reference to the BuildConfig class created by the Gradle build system.
530bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   *
540bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   * @return Reference to BuildConfig class.
550bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass   */
560bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  Class<?> constants() default Void.class;
570bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
580bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  /**
599cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   * The {@link android.app.Application} class to use in the test, this takes precedence over any application
609cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   * specified in the AndroidManifest.xml.
6183bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
6283bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return The {@link android.app.Application} class to use in the test.
639cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish   */
649cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish  Class<? extends Application> application() default Application.class;
659cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
669cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish  /**
67bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * Java package name where the "R.class" file is located. This only needs to be specified if you define
68bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * an {@code applicationId} associated with {@code productFlavors} or specify {@code applicationIdSuffix}
69bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * in your build.gradle.
70bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   *
71bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to the {@code applicationId}.</p>
72bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   *
73bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * @return The java package name for R.class.
74bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   */
75bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass  String packageName() default "";
76bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass
77bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass  /**
7829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * Qualifiers for the resource resolution, such as "fr-normal-port-hdpi".
7929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   *
8083bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Qualifiers used for resource resolution.
8129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
8229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  String qualifiers() default "";
8329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
8429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  /**
856b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   * The directory from which to load resources.  This should be relative to the directory containing AndroidManifest.xml.
8683bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
87bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to {@code res}.</p>
8883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
8983bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Android resource directory.
905277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John   */
916b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  String resourceDir() default DEFAULT_RES_FOLDER;
926b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass
936b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  /**
946b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   * The directory from which to load assets. This should be relative to the directory containing AndroidManifest.xml.
9583bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
96bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass   * <p>If not specified, Robolectric defaults to {@code assets}.</p>
9783bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
9883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return Android asset directory.
996b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass   */
1006b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass  String assetDir() default DEFAULT_ASSET_FOLDER;
1015277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John
1025277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John  /**
10329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   * A list of shadow classes to enable, in addition to those that are already present.
10483bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
10583bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return A list of additional shadow classes to enable.
10629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams   */
10729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  Class<?>[] shadows() default {};
108d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
109d6cef1bcc644c7152d0716b8d33eb25054894836David Sun  /**
110d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   * A list of instrumented packages, in addition to those that are already instrumented.
111d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   *
112d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   * @return A list of additional instrumented packages.
113d6cef1bcc644c7152d0716b8d33eb25054894836David Sun   */
114d6cef1bcc644c7152d0716b8d33eb25054894836David Sun  String[] instrumentedPackages() default {};
11529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
116ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson  /**
117ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson   * A list of folders containing Android Libraries on which this project depends.
11883bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   *
11983bcaf5aa4b64a2223cfada134ef02e5c8ff660aErich Douglass   * @return A list of Android Libraries.
120ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson   */
121ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson  String[] libraries() default {};
122ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
1230bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass  class Implementation implements Config {
12481a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private final int[] sdk;
12529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final String manifest;
12629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final String qualifiers;
1275277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    private final String resourceDir;
1286b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    private final String assetDir;
129bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    private final String packageName;
1300bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private final Class<?> constants;
13129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private final Class<?>[] shadows;
132d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    private final String[] instrumentedPackages;
1339cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    private final Class<? extends Application> application;
134ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    private final String[] libraries;
13529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams
1360bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    public static Config fromProperties(Properties properties) {
1370bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (properties == null || properties.size() == 0) return null;
13829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return new Implementation(
13981a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish          parseIntArrayProperty(properties.getProperty("sdk", "")),
1400bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("manifest", DEFAULT),
1410bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("qualifiers", ""),
142bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass          properties.getProperty("packageName", ""),
1430bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("resourceDir", Config.DEFAULT_RES_FOLDER),
1440bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          properties.getProperty("assetDir", Config.DEFAULT_ASSET_FOLDER),
1450bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseClasses(properties.getProperty("shadows", "")),
146d6cef1bcc644c7152d0716b8d33eb25054894836David Sun          parseStringArrayProperty(properties.getProperty("instrumentedPackages", "")),
1470bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseApplication(properties.getProperty("application", "android.app.Application")),
14881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish          parseStringArrayProperty(properties.getProperty("libraries", "")),
1490bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass          parseClass(properties.getProperty("constants", ""))
15029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      );
15129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
15223a26cc3e5b33c0503a99847292ac99817f5af43Christian Williams
1530bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private static Class<?> parseClass(String className) {
1540bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (className.isEmpty()) return null;
1550bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      try {
1560bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        return Implementation.class.getClassLoader().loadClass(className);
1570bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      } catch (ClassNotFoundException e) {
1580bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        throw new RuntimeException("Could not load class: " + className);
1590bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      }
1600bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    }
1610bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
1620bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    private static Class<?>[] parseClasses(String input) {
1630bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      if (input.isEmpty()) return new Class[0];
1640bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      final String[] classNames = input.split("[, ]+");
1650bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      final Class[] classes = new Class[classNames.length];
16629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      for (int i = 0; i < classNames.length; i++) {
1670bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass        classes[i] = parseClass(classNames[i]);
16829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      }
16929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return classes;
17029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
17123a26cc3e5b33c0503a99847292ac99817f5af43Christian Williams
1720bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    @SuppressWarnings("unchecked")
1739cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    private static <T extends Application> Class<T> parseApplication(String className) {
1740bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return (Class<T>) parseClass(className);
1759cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    }
1769cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
17781a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private static String[] parseStringArrayProperty(String property) {
17881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      if (property.isEmpty()) return new String[0];
17981a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return property.split("[, ]+");
180ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    }
181ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
18281a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private static int[] parseIntArrayProperty(String property) {
18381a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      String[] parts = parseStringArrayProperty(property);
18481a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      int[] result = new int[parts.length];
18581a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      for (int i = 0; i < parts.length; i++) {
18681a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish        result[i] = Integer.parseInt(parts[i]);
18781a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      }
18881a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
18981a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return result;
19081a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    }
19181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
192d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    public Implementation(int[] sdk, String manifest, String qualifiers, String packageName, String resourceDir, String assetDir, Class<?>[] shadows, String[] instrumentedPackages, Class<? extends Application> application, String[] libraries, Class<?> constants) {
1938c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      this.sdk = sdk;
19429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.manifest = manifest;
19529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.qualifiers = qualifiers;
196bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = packageName;
1975277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John      this.resourceDir = resourceDir;
1986b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.assetDir = assetDir;
19929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.shadows = shadows;
200d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = instrumentedPackages;
2019cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish      this.application = application;
202ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      this.libraries = libraries;
2030bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      this.constants = constants;
20429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
205f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
20628950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom    public Implementation(Config other) {
2078c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      this.sdk = other.sdk();
20828950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.manifest = other.manifest();
20928950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.qualifiers = other.qualifiers();
210bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = other.packageName();
21128950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.resourceDir = other.resourceDir();
21228950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.assetDir = other.assetDir();
21328950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.constants = other.constants();
21428950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.shadows = other.shadows();
215d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = other.instrumentedPackages();
21628950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.application = other.application();
21728950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom      this.libraries = other.libraries();
21828950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom    }
21928950f540f7c7bf50fbfb8d9bc8cbf7c2d14e1faAlexander Blom
22029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    public Implementation(Config baseConfig, Config overlayConfig) {
22181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      this.sdk = pickSdk(baseConfig.sdk(), overlayConfig.sdk(), new int[0]);
22229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.manifest = pick(baseConfig.manifest(), overlayConfig.manifest(), DEFAULT);
22329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.qualifiers = pick(baseConfig.qualifiers(), overlayConfig.qualifiers(), "");
224bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      this.packageName = pick(baseConfig.packageName(), overlayConfig.packageName(), "");
2256b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.resourceDir = pick(baseConfig.resourceDir(), overlayConfig.resourceDir(), Config.DEFAULT_RES_FOLDER);
2266b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      this.assetDir = pick(baseConfig.assetDir(), overlayConfig.assetDir(), Config.DEFAULT_ASSET_FOLDER);
227b3c13990ef697c1f25635529ff485760cb5cf644Jen Mendez      this.constants = pick(baseConfig.constants(), overlayConfig.constants(), Void.class);
228ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
2290bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      Set<Class<?>> shadows = new HashSet<>();
23029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      shadows.addAll(Arrays.asList(baseConfig.shadows()));
23129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      shadows.addAll(Arrays.asList(overlayConfig.shadows()));
23229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      this.shadows = shadows.toArray(new Class[shadows.size()]);
233ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
234d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      Set<String> instrumentedPackages = new HashSet<>();
235d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      instrumentedPackages.addAll(Arrays.asList(baseConfig.instrumentedPackages()));
236d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      instrumentedPackages.addAll(Arrays.asList(overlayConfig.instrumentedPackages()));
237d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      this.instrumentedPackages = instrumentedPackages.toArray(new String[instrumentedPackages.size()]);
238d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
2393af772e6f01a3da6c2eff85c100a30cc2ea33909Ibraheem Zaman      this.application = pick(baseConfig.application(), overlayConfig.application(), Application.class);
240ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
2410bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      Set<String> libraries = new HashSet<>();
242ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      libraries.addAll(Arrays.asList(baseConfig.libraries()));
243ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      libraries.addAll(Arrays.asList(overlayConfig.libraries()));
244ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      this.libraries = libraries.toArray(new String[libraries.size()]);
24529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
246f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
24729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    private <T> T pick(T baseValue, T overlayValue, T nullValue) {
2480bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return overlayValue != null ? (overlayValue.equals(nullValue) ? baseValue : overlayValue) : null;
24929a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
250f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
25181a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    private int[] pickSdk(int[] baseValue, int[] overlayValue, int[] nullValue) {
25281a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish      return Arrays.equals(overlayValue, nullValue) ? baseValue : overlayValue;
25381a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    }
25481a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish
2556b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
25681a928816f4cf068ff3fe636df2a25db269c73c8Jonathan Gerrish    public int[] sdk() {
2578c45d4a57fa380436885166f8e89b3e20d20290cErich Douglass      return sdk;
25829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
259f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
2606b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
2616b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String manifest() {
26229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return manifest;
26329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
26448f95f3e0955035946f7c416dec56219a9b19886Christian Williams
2659cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    @Override
2660bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    public Class<?> constants() {
2670bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass      return constants;
2680bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    }
2690bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass
2700bbbacc2633146b2725cce97c24dc121ffa0e89bErich Douglass    @Override
2719cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    public Class<? extends Application> application() {
2729cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish      return application;
2739cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish    }
2749cc9bde8928b83e5de9cd1c521e157e1a584b2fdJonathan Gerrish
2756b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
2766b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String qualifiers() {
27729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return qualifiers;
27829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
279f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
2805277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    @Override
281bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    public String packageName() {
282bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass      return packageName;
283bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    }
284bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass
285bbdc3ce45195e6896254a2c7aa24370f2c55d57cErich Douglass    @Override
2865277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    public String resourceDir() {
2875277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John      return resourceDir;
2885277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John    }
2895277f871bca2be31c657ace35ae305285b2e0c55Ryan Spore and Trevor John
2906b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
2916b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String assetDir() {
2926b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass      return assetDir;
2936b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    }
2946b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass
2956b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
2966b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public Class<?>[] shadows() {
29729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return shadows;
29829a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
299f6df8a55ac378dee35324bc865fb4d741dcb4824Christian Williams
3006b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @Override
301d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    public String[] instrumentedPackages() {
302d6cef1bcc644c7152d0716b8d33eb25054894836David Sun      return instrumentedPackages;
303d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    }
304d6cef1bcc644c7152d0716b8d33eb25054894836David Sun
305d6cef1bcc644c7152d0716b8d33eb25054894836David Sun    @Override
3066b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public String[] libraries() {
307ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson      return libraries;
308ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson    }
309ed898f2b5b7312af4779636638d081aa6ebd9e13Andrew Richardson
3106b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    @NotNull @Override
3116b00d4156e2e6bb2d262458a2650a109ddc76c76Erich Douglass    public Class<? extends Annotation> annotationType() {
31229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams      return Config.class;
31329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams    }
31429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams  }
315dd40f718cf785a56e63c0685feeb73d266c13e3fWenhui Yao}
316