package com.lyft.scoop; import android.content.Context; import android.content.ContextWrapper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; public final class Scoop { private String name; private Scoop parent; private Map<String, Object> services; private Map<String, Scoop> children = new LinkedHashMap<>(); private boolean destroyed; private Scoop(String name, Scoop parent, Map<String, Object> services) { this.name = name; this.parent = parent; this.services = services; if (parent != null) { parent.children.put(name, this); } } public void destroy() { final Set<Map.Entry<String, Scoop>> entries = this.children.entrySet(); final Set<Map.Entry<String, Scoop>> entriesCopy = new HashSet<>(entries); for (Map.Entry<String, Scoop> entry : entriesCopy) { entry.getValue().destroy(); } this.destroyed = true; if (parent != null) { parent.children.remove(this.getName()); } } boolean isDestroyed() { return destroyed; } public <T> T findService(String serviceName) { return findService(this, serviceName); } private <T> T findService(Scoop scoop, String serviceName) { Object service = scoop.services.get(serviceName); if (service != null) { return (T) service; } else { if (scoop.parent != null) { return findService(scoop.parent, serviceName); } } return null; } public String getName() { return name; } public Scoop getParent() { return parent; } public Scoop findChild(String childName) { return children.get(childName); } public static class Builder { private final Scoop parent; private final Map<String, Object> services = new LinkedHashMap<String, Object>(); private String name; public Builder(String name, Scoop scoop) { this.name = name; parent = scoop; } public Builder(String name) { this.name = name; parent = null; } public Builder service(String name, Object service) { services.put(name, service); return this; } public Scoop build() { return new Scoop(name, parent, services); } } public static Scoop fromView(View view) { if (view == null) { return null; } return fromContext(view.getContext()); } public static Scoop fromContext(Context context) { if (!(context instanceof HaveScoop)) { throw new RuntimeException("View does not implement interface: HaveScoop"); } HaveScoop haveScoop = (HaveScoop) context; return haveScoop.getScoop(); } public LayoutInflater inflater(Context context) { return LayoutInflater.from(context).cloneInContext(createContext(context)); } public Context createContext(Context context) { return new ScoopContextWrapper(context, this); } public View inflate(int layoutId, ViewGroup viewGroup, boolean attachToRoot) { return inflater(viewGroup.getContext()).inflate(layoutId, viewGroup, attachToRoot); } protected interface HaveScoop { Scoop getScoop(); } private static class ScoopContextWrapper extends ContextWrapper implements HaveScoop { private final Scoop scoop; public ScoopContextWrapper(Context context, Scoop scoop) { super(context); this.scoop = scoop; } public Scoop getScoop() { return this.scoop; } } }