/** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.react; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; /** * {@code CompositeReactPackage} allows to create a single package composed of views and modules * from several other packages. */ public class CompositeReactPackage extends ReactInstancePackage implements ViewManagerOnDemandReactPackage { private final List mChildReactPackages = new ArrayList<>(); /** * The order in which packages are passed matters. It may happen that a NativeModule or * or a ViewManager exists in two or more ReactPackages. In that case the latter will win * i.e. the latter will overwrite the former. This re-occurrence is detected by * comparing a name of a module. */ public CompositeReactPackage(ReactPackage arg1, ReactPackage arg2, ReactPackage... args) { mChildReactPackages.add(arg1); mChildReactPackages.add(arg2); Collections.addAll(mChildReactPackages, args); } /** * {@inheritDoc} */ @Override public List createNativeModules(ReactApplicationContext reactContext) { // This is for backward compatibility. final Map moduleMap = new HashMap<>(); for (ReactPackage reactPackage: mChildReactPackages) { for (NativeModule nativeModule: reactPackage.createNativeModules(reactContext)) { moduleMap.put(nativeModule.getName(), nativeModule); } } return new ArrayList<>(moduleMap.values()); } /** * {@inheritDoc} */ @Override public List createNativeModules( ReactApplicationContext reactContext, ReactInstanceManager reactInstanceManager) { final Map moduleMap = new HashMap<>(); for (ReactPackage reactPackage: mChildReactPackages) { List nativeModules; if (reactPackage instanceof ReactInstancePackage) { ReactInstancePackage reactInstancePackage = (ReactInstancePackage) reactPackage; nativeModules = reactInstancePackage.createNativeModules( reactContext, reactInstanceManager); } else { nativeModules = reactPackage.createNativeModules(reactContext); } for (NativeModule nativeModule: nativeModules) { moduleMap.put(nativeModule.getName(), nativeModule); } } return new ArrayList<>(moduleMap.values()); } /** * {@inheritDoc} */ @Override public List createViewManagers(ReactApplicationContext reactContext) { final Map viewManagerMap = new HashMap<>(); for (ReactPackage reactPackage: mChildReactPackages) { for (ViewManager viewManager: reactPackage.createViewManagers(reactContext)) { viewManagerMap.put(viewManager.getName(), viewManager); } } return new ArrayList<>(viewManagerMap.values()); } /** {@inheritDoc} */ @Override public List getViewManagerNames(ReactApplicationContext reactContext) { Set uniqueNames = new HashSet<>(); for (ReactPackage reactPackage : mChildReactPackages) { if (reactPackage instanceof ViewManagerOnDemandReactPackage) { List names = ((ViewManagerOnDemandReactPackage) reactPackage) .getViewManagerNames(reactContext); if (names != null) { uniqueNames.addAll(names); } } } return new ArrayList<>(uniqueNames); } /** {@inheritDoc} */ @Override public @Nullable ViewManager createViewManager(ReactApplicationContext reactContext, String viewManagerName) { ListIterator iterator = mChildReactPackages.listIterator(mChildReactPackages.size()); while (iterator.hasPrevious()) { ReactPackage reactPackage = iterator.previous(); if (reactPackage instanceof ViewManagerOnDemandReactPackage) { ViewManager viewManager = ((ViewManagerOnDemandReactPackage) reactPackage) .createViewManager(reactContext, viewManagerName); if (viewManager != null) { return viewManager; } } } return null; } }