/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.stetho.inspector.elements; import com.facebook.stetho.common.Util; import java.util.IdentityHashMap; import java.util.Map; import javax.annotation.Nullable; public final class DescriptorMap implements DescriptorRegistrar { private final Map<Class<?>, Descriptor> mMap = new IdentityHashMap<>(); private boolean mIsInitializing; private Descriptor.Host mHost; public DescriptorMap beginInit() { Util.throwIf(mIsInitializing); mIsInitializing = true; return this; } @Override public DescriptorMap registerDescriptor(Class<?> elementClass, Descriptor descriptor) { Util.throwIfNull(elementClass); Util.throwIfNull(descriptor); Util.throwIf(descriptor.isInitialized()); Util.throwIfNot(mIsInitializing); // Cannot register two descriptors for one class if (mMap.containsKey(elementClass)) { throw new UnsupportedOperationException(); } // Cannot reuse one descriptor for two classes if (mMap.containsValue(descriptor)) { throw new UnsupportedOperationException(); } mMap.put(elementClass, descriptor); return this; } public DescriptorMap setHost(Descriptor.Host host) { Util.throwIfNull(host); Util.throwIfNot(mIsInitializing); Util.throwIfNotNull(mHost); mHost = host; return this; } public DescriptorMap endInit() { Util.throwIfNot(mIsInitializing); Util.throwIfNull(mHost); mIsInitializing = false; for (final Class<?> elementClass : mMap.keySet()) { final Descriptor descriptor = mMap.get(elementClass); if (descriptor instanceof ChainedDescriptor) { final ChainedDescriptor chainedDescriptor = (ChainedDescriptor) descriptor; Class<?> superClass = elementClass.getSuperclass(); Descriptor superDescriptor = getImpl(superClass); chainedDescriptor.setSuper(superDescriptor); } descriptor.initialize(mHost); } return this; } @Nullable public Descriptor get(Class<?> elementClass) { Util.throwIfNull(elementClass); Util.throwIf(mIsInitializing); return getImpl(elementClass); } @Nullable private Descriptor getImpl(final Class<?> elementClass) { Class<?> theClass = elementClass; while (theClass != null) { Descriptor descriptor = mMap.get(theClass); if (descriptor != null) { return descriptor; } theClass = theClass.getSuperclass(); } return null; } }