1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.databinding.tool.writer;
17
18import android.databinding.tool.Binding;
19import android.databinding.tool.BindingTarget;
20import android.databinding.tool.LayoutBinder;
21import android.databinding.tool.processing.ScopedException;
22
23import java.util.ArrayList;
24import java.util.HashMap;
25import java.util.List;
26import java.util.Map.Entry;
27
28public class ComponentWriter {
29    private static final String INDENT = "    ";
30    private final HashMap<String, ArrayList<String>> mBindingAdapters = new HashMap<>();
31
32    public ComponentWriter(List<LayoutBinder> binders) {
33        HashMap<Binding, ArrayList<String>> bindings = new HashMap<>();
34
35        for (LayoutBinder layoutBinder : binders) {
36            try {
37                android.databinding.tool.processing.Scope.enter(layoutBinder);
38                for (BindingTarget target : layoutBinder.getBindingTargets()) {
39                    try {
40                        android.databinding.tool.processing.Scope.enter(target);
41                        for (Binding binding : target.getBindings()) {
42                            try {
43                                android.databinding.tool.processing.Scope.enter(binding);
44                                final String bindingAdapter = binding
45                                        .getBindingAdapterInstanceClass();
46                                if (bindingAdapter != null) {
47                                    final String simpleName = simpleName(bindingAdapter);
48                                    ArrayList<String> classes = mBindingAdapters.get(simpleName);
49                                    if (classes == null) {
50                                        classes = new ArrayList<>();
51                                        mBindingAdapters.put(simpleName, classes);
52                                        classes.add(bindingAdapter);
53                                    } else if (!classes.contains(bindingAdapter)) {
54                                        classes.add(bindingAdapter);
55                                    }
56                                    bindings.put(binding, classes);
57                                }
58                            } catch (ScopedException ex) {
59                                android.databinding.tool.processing.Scope.defer(ex);
60                            } finally{
61                                android.databinding.tool.processing.Scope.exit();
62                            }
63                        }
64                    } finally {
65                        android.databinding.tool.processing.Scope.exit();
66                    }
67                }
68            } finally {
69                android.databinding.tool.processing.Scope.exit();
70            }
71        }
72
73        for (Entry<Binding, ArrayList<String>> entry : bindings.entrySet()) {
74            final Binding binding = entry.getKey();
75            final ArrayList<String> classes = entry.getValue();
76            final String call;
77            if (classes.size() == 1) {
78                call = "get" + simpleName(classes.get(0)) + "()";
79            } else {
80                int index = classes.indexOf(binding.getBindingAdapterInstanceClass());
81                call = "get" + simpleName(classes.get(index)) + (index + 1) + "()";
82            }
83            binding.setBindingAdapterCall(call);
84        }
85    }
86
87    public String createComponent() {
88        final StringBuilder builder = new StringBuilder();
89        builder.append("package android.databinding;\n\n");
90        builder.append("public interface DataBindingComponent {\n");
91        for (final String simpleName : mBindingAdapters.keySet()) {
92            final ArrayList<String> classes = mBindingAdapters.get(simpleName);
93            if (classes.size() > 1) {
94                int index = 1;
95                for (String className : classes) {
96                    addGetter(builder, simpleName, className, index++);
97                }
98            } else {
99                addGetter(builder, simpleName, classes.iterator().next(), 0);
100            }
101        }
102        builder.append("}\n");
103        return builder.toString();
104    }
105
106    private static String simpleName(String className) {
107        int dotIndex = className.lastIndexOf('.');
108        if (dotIndex < 0) {
109            return className;
110        } else {
111            return className.substring(dotIndex + 1);
112        }
113    }
114
115    private static void addGetter(StringBuilder builder, String simpleName, String className,
116            int index) {
117        builder.append(INDENT)
118                .append(className)
119                .append(" get")
120                .append(simpleName);
121        if (index > 0) {
122            builder.append(index);
123        }
124        builder.append("();\n");
125    }
126}
127