All Downloads are FREE. Search and download functionalities are using the official Maven repository.

android.databinding.tool.BindingTarget Maven / Gradle / Ivy

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.databinding.tool;

import android.databinding.tool.expr.Expr;
import android.databinding.tool.expr.ExprModel;
import android.databinding.tool.processing.ErrorMessages;
import android.databinding.tool.processing.Scope;
import android.databinding.tool.processing.scopes.LocationScopeProvider;
import android.databinding.tool.reflection.ModelAnalyzer;
import android.databinding.tool.reflection.ModelClass;
import android.databinding.tool.store.Location;
import android.databinding.tool.store.ResourceBundle;
import android.databinding.tool.store.SetterStore;
import android.databinding.tool.store.SetterStore.BindingGetterCall;
import android.databinding.tool.util.L;
import android.databinding.tool.util.Preconditions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BindingTarget implements LocationScopeProvider {
    List mBindings = new ArrayList();
    List mInverseBindings = new ArrayList();
    ExprModel mModel;
    ModelClass mResolvedClass;

    // if this target presents itself in multiple layout files with different view types,
    // it receives an interface type and should use it in the getter instead.
    ResourceBundle.BindingTargetBundle mBundle;

    public BindingTarget(ResourceBundle.BindingTargetBundle bundle) {
        mBundle = bundle;
    }

    public boolean isUsed() {
        return mBundle.isUsed();
    }

    public void addBinding(String name, Expr expr) {
        if (SetterStore.get(ModelAnalyzer.getInstance()).isTwoWayEventAttribute(name)) {
            L.e(ErrorMessages.TWO_WAY_EVENT_ATTRIBUTE, name);
        }
        mBindings.add(new Binding(this, name, expr));
    }

    public String getInterfaceType() {
        return mBundle.getInterfaceType() == null ? mBundle.getFullClassName() : mBundle.getInterfaceType();
    }

    public InverseBinding addInverseBinding(String name, Expr expr, String bindingClass) {
        expr.assertIsInvertible();
        final InverseBinding inverseBinding = new InverseBinding(this, name, expr, bindingClass);
        mInverseBindings.add(inverseBinding);
        mBindings.add(new Binding(this, inverseBinding.getEventAttribute(),
                mModel.twoWayListenerExpr(inverseBinding),
                inverseBinding.getEventSetter()));
        return inverseBinding;
    }

    public InverseBinding addInverseBinding(String name, BindingGetterCall call) {
        final InverseBinding inverseBinding = new InverseBinding(this, name, call);
        mInverseBindings.add(inverseBinding);
        mBindings.add(new Binding(this, inverseBinding.getEventAttribute(),
                mModel.twoWayListenerExpr(inverseBinding)));
        return inverseBinding;
    }

    @Override
    public List provideScopeLocation() {
        return mBundle.provideScopeLocation();
    }

    public String getId() {
        return mBundle.getId();
    }

    public String getTag() {
        return mBundle.getTag();
    }

    public String getOriginalTag() {
        return mBundle.getOriginalTag();
    }

    public String getViewClass() {
        return mBundle.getFullClassName();
    }

    public ModelClass getResolvedType() {
        if (mResolvedClass == null) {
            if (mBundle.isBinder()) {
                mResolvedClass = ModelAnalyzer.getInstance().
                        findClass(mBundle.getInterfaceType(), mModel.getImports());
            } else {
                mResolvedClass = ModelAnalyzer.getInstance().findClass(mBundle.getFullClassName(),
                        mModel.getImports());
            }
        }
        return mResolvedClass;
    }

    public String getIncludedLayout() {
        return mBundle.getIncludedLayout();
    }

    public boolean isBinder() {
        return getIncludedLayout() != null;
    }

    public boolean supportsTag() {
        return !SetterStore.get(ModelAnalyzer.getInstance())
                .isUntaggable(mBundle.getFullClassName());
    }

    public List getBindings() {
        return mBindings;
    }

    public List getInverseBindings() {
        return mInverseBindings;
    }

    public ExprModel getModel() {
        return mModel;
    }

    public void setModel(ExprModel model) {
        mModel = model;
    }

    public void resolveListeners() {
        for (Binding binding : mBindings) {
            try {
                Scope.enter(binding);
                binding.resolveListeners();
            } finally {
                Scope.exit();
            }
        }
    }

    public void resolveCallbackParams() {
        for (Binding binding : mBindings) {
            try {
                Scope.enter(binding);
                binding.resolveCallbackParams();
            } finally {
                Scope.exit();
            }
        }
    }

    public void resolveTwoWayExpressions() {
        for (Binding binding : mBindings) {
            try {
                Scope.enter(binding);
                binding.resolveTwoWayExpressions();
            } finally {
                Scope.exit();
            }
        }
    }

    /**
     * Called after BindingTarget is finalized.
     * 

* We traverse all bindings and ask SetterStore to figure out if any can be combined. * When N bindings are combined, they are demoted from being a binding expression and a new * ArgList expression is added as the new binding expression that depends on others. */ public void resolveMultiSetters() { L.d("resolving multi setters for %s", getId()); final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); final String[] attributes = new String[mBindings.size()]; final ModelClass[] types = new ModelClass[mBindings.size()]; for (int i = 0; i < mBindings.size(); i ++) { Binding binding = mBindings.get(i); try { Scope.enter(binding); attributes[i] = binding.getName(); types[i] = binding.getExpr().getResolvedType(); } finally { Scope.exit(); } } final List multiAttributeSetterCalls = setterStore .getMultiAttributeSetterCalls(attributes, getResolvedType(), types); if (multiAttributeSetterCalls.isEmpty()) { return; } final Map lookup = new HashMap(); for (Binding binding : mBindings) { String name = binding.getName(); if (name.startsWith("android:")) { lookup.put(name, binding); } else { int ind = name.indexOf(":"); if (ind == -1) { lookup.put(name, binding); } else { lookup.put(name.substring(ind + 1), binding); } } } List mergeBindings = new ArrayList(); for (final SetterStore.MultiAttributeSetter setter : multiAttributeSetterCalls) { L.d("resolved %s", setter); final List mergedBindings = new ArrayList(); for (String attribute : setter.attributes) { Binding binding = lookup.get(attribute); Preconditions.checkNotNull(binding, "cannot find binding for %s", attribute); mergedBindings.add(binding); } for (Binding binding : mergedBindings) { binding.getExpr().setBindingExpression(false); mBindings.remove(binding); } MergedBinding mergedBinding = new MergedBinding(getModel(), setter, this, mergedBindings); mergeBindings.add(mergedBinding); } for (MergedBinding binding : mergeBindings) { mBindings.add(binding); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy