Merge "Revert "Added Bindable annotation processor.""
diff --git a/KDataBinder/.idea/uiDesigner.xml b/KDataBinder/.idea/uiDesigner.xml
deleted file mode 100644
index e96534f..0000000
--- a/KDataBinder/.idea/uiDesigner.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="Palette2">
-    <group name="Swing">
-      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
-      </item>
-      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
-      </item>
-      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
-        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
-        <initial-values>
-          <property name="text" value="Button" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="RadioButton" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="CheckBox" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="Label" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
-          <preferred-size width="200" height="200" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
-          <preferred-size width="200" height="200" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
-      </item>
-      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
-          <preferred-size width="-1" height="20" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
-      </item>
-      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
-      </item>
-    </group>
-  </component>
-</project>
\ No newline at end of file
diff --git a/annotationprocessor/build.gradle b/annotationprocessor/build.gradle
deleted file mode 100644
index 19c563d..0000000
--- a/annotationprocessor/build.gradle
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-apply plugin: 'java'
-apply plugin: 'maven'
-
-buildscript {
-    repositories {
-        mavenLocal()
-        mavenCentral()
-    }
-}
-
-repositories {
-    mavenCentral()
-}
-
-sourceSets {
-    main {
-        java {
-            srcDir 'src/main/java'
-        }
-    }
-}
-
-uploadArchives {
-    repositories {
-        mavenDeployer {
-            repository(url: mavenLocal().url)
-            pom.version = '0.1-SNAPSHOT'
-            pom.artifactId = 'annotationprocessor'
-            pom.groupId='com.android.databinding'
-        }
-    }
-}
diff --git a/library/src/main/java/com/android/databinding/library/AbsObservable.java b/library/src/main/java/com/android/databinding/library/AbsObservable.java
deleted file mode 100644
index 9a2f438..0000000
--- a/library/src/main/java/com/android/databinding/library/AbsObservable.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.databinding.library;
-
-public abstract class AbsObservable implements Observable {
-    private ChangeListenerRegistry mCallbacks;
-
-    public AbsObservable() {
-    }
-
-    @Override
-    public synchronized void addListener(OnPropertyChangedListener listener) {
-        if (mCallbacks == null) {
-            mCallbacks = new ChangeListenerRegistry();
-        }
-        mCallbacks.add(listener);
-    }
-
-    @Override
-    public synchronized void removeListener(OnPropertyChangedListener listener) {
-        if (mCallbacks != null) {
-            mCallbacks.remove(listener);
-        }
-    }
-
-    public synchronized void notifyChange() {
-        if (mCallbacks != null) {
-            mCallbacks.notifyCallbacks(this, 0);
-        }
-    }
-
-    public synchronized void notifyChange(int id) {
-        if (mCallbacks != null) {
-            mCallbacks.notifyCallbacks(this, id);
-        }
-    }
-}
diff --git a/library/src/main/java/com/android/databinding/library/BaseObservable.java b/library/src/main/java/com/android/databinding/library/BaseObservable.java
new file mode 100644
index 0000000..30c4a74
--- /dev/null
+++ b/library/src/main/java/com/android/databinding/library/BaseObservable.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 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 com.android.databinding.library;
+
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class BaseObservable implements Observable {
+    final ObservableHelper mHelper;
+
+    public BaseObservable() {
+        mHelper = new ObservableHelper(this);
+    }
+
+    @Override
+    public void register(ObservableListener listener) {
+        mHelper.register(listener);
+    }
+
+    @Override
+    public void unRegister(ObservableListener listener) {
+        mHelper.unRegister(listener);
+    }
+
+    public void fireChange() {
+        mHelper.fireChange();
+    }
+    public void fireChange(String fieldName) {
+        mHelper.fireChange(fieldName);
+    }
+    public void fireChange(int fieldId) {mHelper.fireChange(fieldId);}
+}
diff --git a/library/src/main/java/com/android/databinding/library/CallbackRegistry.java b/library/src/main/java/com/android/databinding/library/CallbackRegistry.java
deleted file mode 100644
index 820561f..0000000
--- a/library/src/main/java/com/android/databinding/library/CallbackRegistry.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.databinding.library;
-
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tracks callbacks for the event. This class supports reentrant modification
- * of the callbacks during notification without adversely disrupting notifications.
- * A common pattern for callbacks is to receive a notification and then remove
- * themselves. This class handles this behavior with constant memory under
- * most circumstances.
- *
- * <p>A subclass of {@link com.android.databinding.library.CallbackRegistry.NotifierCallback} must be passed to
- * the constructor to define how notifications should be called. That implementation
- * does the actual notification on the listener.</p>
- *
- * <p>This class supports only callbacks with at most two parameters.
- * Typically, these are the notification originator and a parameter, but these may
- * be used as required. If more than two parameters are required or primitive types
- * must be used, <code>A</code> should be some kind of containing structure that
- * the subclass may reuse between notifications.</p>
- *
- * @param <C> The callback type.
- * @param <T> The notification sender type. Typically this is the containing class.
- */
-public class CallbackRegistry<C, T> implements Cloneable {
-    private static final String TAG = "CallbackRegistry";
-
-    /** An ordered collection of listeners waiting to be notified. */
-    private List<C> mCallbacks = new ArrayList<C>();
-
-    /**
-     * A bit flag for the first 64 listeners that are removed during notification.
-     * The lowest significant bit corresponds to the 0th index into mCallbacks.
-     * For a small number of callbacks, no additional array of objects needs to
-     * be allocated.
-     */
-    private long mFirst64Removed = 0x0;
-
-    /**
-     * Bit flags for the remaining callbacks that are removed during notification.
-     * When there are more than 64 callbacks and one is marked for removal, a dynamic
-     * array of bits are allocated for the callbacks.
-     */
-    private long[] mRemainderRemoved;
-
-    /** The recursion level of the notification */
-    private int mNotificationLevel;
-
-    /** The notification mechanism for notifying an event. */
-    private final NotifierCallback<C, T> mNotifier;
-
-    /**
-     * Creates an EventRegistry that notifies the event with notifier.
-     * @param notifier The class to use to notify events.
-     */
-    public CallbackRegistry(NotifierCallback<C, T> notifier) {
-        mNotifier = notifier;
-    }
-
-    /**
-     * Notify all callbacks.
-     *
-     * @param sender The originator. This is an opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param arg An opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     */
-    public synchronized void notifyCallbacks(T sender, int arg) {
-        mNotificationLevel++;
-        notifyRecurse(sender, arg);
-        mNotificationLevel--;
-        if (mNotificationLevel == 0) {
-            if (mRemainderRemoved != null) {
-                for (int i = mRemainderRemoved.length - 1; i >= 0; i--) {
-                    final long removedBits = mRemainderRemoved[i];
-                    if (removedBits != 0) {
-                        removeRemovedCallbacks((i + 1) * Long.SIZE, removedBits);
-                        mRemainderRemoved[i] = 0;
-                    }
-                }
-            }
-            if (mFirst64Removed != 0) {
-                removeRemovedCallbacks(0, mFirst64Removed);
-                mFirst64Removed = 0;
-            }
-        }
-    }
-
-    /**
-     * Notify up to the first Long.SIZE callbacks that don't have a bit set in <code>removed</code>.
-     *
-     * @param sender The originator. This is an opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param arg An opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     */
-    private void notifyFirst64(T sender, int arg) {
-        final int maxNotified = Math.min(Long.SIZE, mCallbacks.size());
-        notifyCallbacks(sender, arg, 0, maxNotified, mFirst64Removed);
-    }
-
-    /**
-     * Notify all callbacks using a recursive algorithm to avoid allocating on the heap.
-     * This part captures the callbacks beyond Long.SIZE that have no bits allocated for
-     * removal before it recurses into {@link #notifyRemainder(Object, int, int)}.
-     *
-     * <p>Recursion is used to avoid allocating temporary state on the heap.</p>
-     *
-     * @param sender The originator. This is an opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param arg An opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     */
-    private void notifyRecurse(T sender, int arg) {
-        final int callbackCount = mCallbacks.size();
-        final int remainderIndex = mRemainderRemoved == null ? -1 : mRemainderRemoved.length - 1;
-
-        // Now we've got all callbakcs that have no mRemainderRemoved value, so notify the
-        // others.
-        notifyRemainder(sender, arg, remainderIndex);
-
-        // notifyRemainder notifies all at maxIndex, so we'd normally start at maxIndex + 1
-        // However, we must also keep track of those in mFirst64Removed, so we add 2 instead:
-        final int startCallbackIndex = (remainderIndex + 2) * Long.SIZE;
-
-        // The remaining have no bit set
-        notifyCallbacks(sender, arg, startCallbackIndex, callbackCount, 0);
-    }
-
-    /**
-     * Notify callbacks that have mRemainderRemoved bits set for remainderIndex. If
-     * remainderIndex is -1, the first 64 will be notified instead.
-     *
-     * @param sender The originator. This is an opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param arg An opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param remainderIndex The index into mRemainderRemoved that should be notified.
-     */
-    private void notifyRemainder(T sender, int arg, int remainderIndex) {
-        if (remainderIndex < 0) {
-            notifyFirst64(sender, arg);
-        } else {
-            final long bits = mRemainderRemoved[remainderIndex];
-            final int startIndex = (remainderIndex + 1) * Long.SIZE;
-            final int endIndex = Math.min(mCallbacks.size(), startIndex + Long.SIZE);
-            notifyRemainder(sender, arg, remainderIndex - 1);
-            notifyCallbacks(sender, arg, startIndex, endIndex, bits);
-        }
-    }
-
-    /**
-     * Notify callbacks from startIndex to endIndex, using bits as the bit status
-     * for whether they have been removed or not. bits should be from mRemainderRemoved or
-     * mFirst64Removed. bits set to 0 indicates that all callbacks from startIndex to
-     * endIndex should be notified.
-     *
-     * @param sender The originator. This is an opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param arg An opaque parameter passed to
-     *      {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
-     * @param startIndex The index into the mCallbacks to start notifying.
-     * @param endIndex One past the last index into mCallbacks to notify.
-     * @param bits A bit field indicating which callbacks have been removed and shouldn't
-     *             be notified.
-     */
-    private void notifyCallbacks(T sender, int arg, final int startIndex, final int endIndex,
-            final long bits) {
-        long bitMask = 1;
-        for (int i = startIndex; i < endIndex; i++) {
-            if ((bits & bitMask) == 0) {
-                mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg);
-            }
-            bitMask <<= 1;
-        }
-    }
-
-    /**
-     * Add a callback to be notified. If the callback is already in the list, another won't
-     * be added. This does not affect current notifications.
-     * @param callback The callback to add.
-     */
-    public synchronized void add(C callback) {
-        int index = mCallbacks.lastIndexOf(callback);
-        if (index < 0 || isRemoved(index)) {
-            mCallbacks.add(callback);
-        }
-    }
-
-    /**
-     * Returns true if the callback at index has been marked for removal.
-     *
-     * @param index The index into mCallbacks to check.
-     * @return true if the callback at index has been marked for removal.
-     */
-    private boolean isRemoved(int index) {
-        if (index < Long.SIZE) {
-            // It is in the first 64 callbacks, just check the bit.
-            final long bitMask = 1L << index;
-            return (mFirst64Removed & bitMask) != 0;
-        } else if (mRemainderRemoved == null) {
-            // It is after the first 64 callbacks, but nothing else was marked for removal.
-            return false;
-        } else {
-            final int maskIndex = (index / Long.SIZE) - 1;
-            if (maskIndex >= mRemainderRemoved.length) {
-                // There are some items in mRemainderRemoved, but nothing at the given index.
-                return false;
-            } else {
-                // There is something marked for removal, so we have to check the bit.
-                final long bits = mRemainderRemoved[maskIndex];
-                final long bitMask = 1L << (index % Long.SIZE);
-                return (bits & bitMask) != 0;
-            }
-        }
-    }
-
-    /**
-     * Removes callbacks from startIndex to startIndex + Long.SIZE, based
-     * on the bits set in removed.
-     * @param startIndex The index into the mCallbacks to start removing callbacks.
-     * @param removed The bits indicating removal, where each bit is set for one callback
-     *                to be removed.
-     */
-    private void removeRemovedCallbacks(int startIndex, long removed) {
-        // The naive approach should be fine. There may be a better bit-twiddling approach.
-        final int endIndex = startIndex + Long.SIZE;
-
-        long bitMask = 1L << (Long.SIZE - 1);
-        for (int i = endIndex - 1; i >= startIndex; i--) {
-            if ((removed & bitMask) != 0) {
-                mCallbacks.remove(i);
-            }
-            bitMask >>>= 1;
-        }
-    }
-
-    /**
-     * Remove a callback. This callback won't be notified after this call completes.
-     * @param callback The callback to remove.
-     */
-    public synchronized void remove(C callback) {
-        if (mNotificationLevel == 0) {
-            mCallbacks.remove(callback);
-        } else {
-            int index = mCallbacks.lastIndexOf(callback);
-            if (index >= 0) {
-                setRemovalBit(index);
-            }
-        }
-    }
-
-    private void setRemovalBit(int index) {
-        if (index < Long.SIZE) {
-            // It is in the first 64 callbacks, just check the bit.
-            final long bitMask = 1L << index;
-            mFirst64Removed |= bitMask;
-        } else {
-            final int remainderIndex = (index / Long.SIZE) - 1;
-            if (mRemainderRemoved == null) {
-                mRemainderRemoved = new long[mCallbacks.size() / Long.SIZE];
-            } else if (mRemainderRemoved.length < remainderIndex) {
-                // need to make it bigger
-                long[] newRemainders = new long[mCallbacks.size() / Long.SIZE];
-                System.arraycopy(mRemainderRemoved, 0, newRemainders, 0, mRemainderRemoved.length);
-                mRemainderRemoved = newRemainders;
-            }
-            final long bitMask = 1L << (index % Long.SIZE);
-            mRemainderRemoved[remainderIndex] |= bitMask;
-        }
-    }
-
-    /*
-    private void clearRemovalBit(int index) {
-        if (index < Long.SIZE) {
-            // It is in the first 64 callbacks, just check the bit.
-            final long bitMask = 1L << index;
-            mFirst64Removed &= ~bitMask;
-        } else if (mRemainderRemoved != null) {
-            final int maskIndex = (index / Long.SIZE) - 1;
-            if (maskIndex < mRemainderRemoved.length) {
-                // There is something marked for removal, so we have to check the bit.
-                final long bitMask = 1L << (index % Long.SIZE);
-                mRemainderRemoved[maskIndex] &= ~bitMask;
-            }
-        }
-    }
-    */
-
-    /**
-     * Makes a copy of the registered callbacks and returns it.
-     *
-     * @return a copy of the registered callbacks.
-     */
-    public synchronized ArrayList<C> copyListeners() {
-        ArrayList<C> callbacks = new ArrayList<C>(mCallbacks.size());
-        int numListeners = mCallbacks.size();
-        for (int i = 0; i < numListeners; i++) {
-            if (!isRemoved(i)) {
-                callbacks.add(mCallbacks.get(i));
-            }
-        }
-        return callbacks;
-    }
-
-    /**
-     * Returns true if there are no registered callbacks or false otherwise.
-     *
-     * @return true if there are no registered callbacks or false otherwise.
-     */
-    public synchronized boolean isEmpty() {
-        if (mCallbacks.isEmpty()) {
-            return true;
-        } else if (mNotificationLevel == 0) {
-            return false;
-        } else {
-            int numListeners = mCallbacks.size();
-            for (int i = 0; i < numListeners; i++) {
-                if (!isRemoved(i)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Removes all callbacks from the list.
-     */
-    public synchronized void clear() {
-        if (mNotificationLevel == 0) {
-            mCallbacks.clear();
-        } else if (!mCallbacks.isEmpty()) {
-            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                setRemovalBit(i);
-            }
-        }
-    }
-
-    public synchronized CallbackRegistry<C, T> clone() {
-        CallbackRegistry<C, T> clone = null;
-        try {
-            clone = (CallbackRegistry<C, T>) super.clone();
-            clone.mFirst64Removed = 0;
-            clone.mRemainderRemoved = null;
-            clone.mNotificationLevel = 0;
-            clone.mCallbacks = new ArrayList<C>();
-            final int numListeners = mCallbacks.size();
-            for (int i = 0; i < numListeners; i++) {
-                if (!isRemoved(i)) {
-                    clone.mCallbacks.add(mCallbacks.get(i));
-                }
-            }
-        } catch (CloneNotSupportedException e) {
-            Log.e(TAG, "Could not clone CallbackRegistry", e);
-        }
-        return clone;
-    }
-
-    /**
-     * Class used to notify events from CallbackRegistry.
-     *
-     * @param <C> The callback type.
-     * @param <T> The notification sender type. Typically this is the containing class.
-     */
-    public abstract static class NotifierCallback<C, T> {
-        /**
-         * Used to notify the callback.
-         *
-         * @param callback The callback to notify.
-         * @param sender The opaque sender object.
-         * @param arg The opaque notification parameter.
-         * @see CallbackRegistry#CallbackRegistry(com.android.databinding.library.CallbackRegistry.NotifierCallback)
-         */
-        public abstract void onNotifyCallback(C callback, T sender, int arg);
-    }
-}
diff --git a/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java b/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java
deleted file mode 100644
index 46de743..0000000
--- a/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.databinding.library;
-
-/**
- * Created by mount on 12/15/14.
- */
-public class ChangeListenerRegistry extends
-        CallbackRegistry<OnPropertyChangedListener, Observable> {
-
-    private static final CallbackRegistry.NotifierCallback<OnPropertyChangedListener, Observable> NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback<OnPropertyChangedListener, Observable>() {
-        @Override
-        public void onNotifyCallback(OnPropertyChangedListener callback, Observable sender,
-                int arg) {
-            callback.onPropertyChanged(arg);
-        }
-    };
-
-    public ChangeListenerRegistry() {
-        super(NOTIFIER_CALLBACK);
-    }
-}
diff --git a/library/src/main/java/com/android/databinding/library/Observable.java b/library/src/main/java/com/android/databinding/library/Observable.java
index 59ffd0e..e825dd5 100644
--- a/library/src/main/java/com/android/databinding/library/Observable.java
+++ b/library/src/main/java/com/android/databinding/library/Observable.java
@@ -17,6 +17,6 @@
 package com.android.databinding.library;
 
 public interface Observable {
-    public void addListener(OnPropertyChangedListener listener);
-    public void removeListener(OnPropertyChangedListener listener);
+    public void register(ObservableListener listener);
+    public void unRegister(ObservableListener listener);
 }
diff --git a/library/src/main/java/com/android/databinding/library/ObservableHelper.java b/library/src/main/java/com/android/databinding/library/ObservableHelper.java
new file mode 100644
index 0000000..bac5686
--- /dev/null
+++ b/library/src/main/java/com/android/databinding/library/ObservableHelper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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 com.android.databinding.library;
+
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class ObservableHelper implements Observable {
+    final Observable owner;
+    CopyOnWriteArraySet<ObservableListener> mListeners;
+
+    public ObservableHelper(Observable owner) {
+        this.owner = owner;
+    }
+
+    private synchronized CopyOnWriteArraySet<ObservableListener> getListeners(boolean createIfMissing) {
+        if (mListeners == null) {
+            if (createIfMissing) {
+                mListeners = new CopyOnWriteArraySet<>();
+            }
+        }
+        return mListeners;
+    }
+
+    public void fireChange() {
+        fireChange("");
+    }
+    public void fireChange(String fieldName) {
+        fireChange(DataBinder.convertToId(fieldName));
+    }
+    public void fireChange(int fieldId) {
+        final CopyOnWriteArraySet<ObservableListener> listeners = getListeners(false);
+        if (listeners == null) {
+            return;
+        }
+        for (ObservableListener listener : listeners) {
+            listener.onChange(fieldId);
+        }
+    }
+
+    @Override
+    public void register(ObservableListener listener) {
+        getListeners(true).add(listener);
+    }
+
+    @Override
+    public void unRegister(ObservableListener listener) {
+        final CopyOnWriteArraySet<ObservableListener> listeners = getListeners(false);
+        if (listener != null) {
+            listeners.remove(listener);
+        }
+    }
+}
diff --git a/library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java b/library/src/main/java/com/android/databinding/library/ObservableListener.java
similarity index 86%
rename from library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java
rename to library/src/main/java/com/android/databinding/library/ObservableListener.java
index eab1e9c..04ccd38 100644
--- a/library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java
+++ b/library/src/main/java/com/android/databinding/library/ObservableListener.java
@@ -16,6 +16,7 @@
 
 package com.android.databinding.library;
 
-public interface OnPropertyChangedListener {
-    public void onPropertyChanged(int fieldId);
+public interface ObservableListener {
+    public void onChange();
+    public void onChange(int fieldId);
 }
diff --git a/library/src/main/java/com/android/databinding/library/ViewDataBinder.java b/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
index c0ac85c..f1a3bf5 100644
--- a/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
+++ b/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
@@ -16,11 +16,16 @@
 
 package com.android.databinding.library;
 
+import android.util.SparseIntArray;
 import android.view.View;
 
 import java.lang.Override;
 import java.lang.Runnable;
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 abstract public class ViewDataBinder {
     WeakReferencedListener[] mLocalFieldObservers;
@@ -107,7 +112,7 @@
         listener.setTarget(observable);
     }
 
-    protected abstract class WeakReferencedListener implements OnPropertyChangedListener {
+    protected abstract class WeakReferencedListener implements ObservableListener {
         WeakReference<Observable> mTarget;
 
         public WeakReferencedListener() {
@@ -116,7 +121,7 @@
         public void setTarget(Observable observable) {
             if (observable != null) {
                 mTarget = new WeakReference<>(observable);
-                observable.addListener(this);
+                observable.register(this);
             } else {
                 mTarget = null;
             }
@@ -125,7 +130,7 @@
         public boolean unregister() {
             Observable oldTarget = getTarget();
             if (oldTarget != null) {
-                oldTarget.removeListener(this);
+                oldTarget.unRegister(this);
             }
             mTarget = null;
             return oldTarget != null;
@@ -143,7 +148,16 @@
         }
 
         @Override
-        public void onPropertyChanged(int fieldId) {
+        public void onChange() {
+            Observable obj = getTarget();
+            if (obj == null) {
+                return;//how come i live if it died ?
+            }
+            ViewDataBinder.this.handleFieldChange(mLocalFieldId, obj, 0);
+        }
+
+        @Override
+        public void onChange(int fieldId) {
             Observable obj = getTarget();
             if (obj == null) {
                 return;//how come i live if it died ?
diff --git a/samples/BindingDemo/app/build.gradle b/samples/BindingDemo/app/build.gradle
index 2347998..45e7ebe 100644
--- a/samples/BindingDemo/app/build.gradle
+++ b/samples/BindingDemo/app/build.gradle
@@ -17,8 +17,6 @@
 apply plugin: 'com.android.application'
 apply plugin: 'com.android.databinding'
 
-def generatedSources = "$buildDir/generated/source/br"
-
 android {
     compileSdkVersion 21
     buildToolsVersion "21.1.1"
@@ -40,19 +38,6 @@
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
     }
-    sourceSets {
-        //main.java.srcDirs += generatedSources
-    }
-}
-
-android.applicationVariants.all { variant ->
-    variant.javaCompile.doFirst {
-        println "*** compile doFirst ${variant.name}"
-        new File(generatedSources).mkdirs()
-        variant.javaCompile.options.compilerArgs += [
-                '-s', generatedSources
-        ]
-    }
 }
 
 dependencies {
@@ -62,5 +47,4 @@
     compile 'com.android.support:recyclerview-v7:21.0.2'
     compile 'com.android.support:gridlayout-v7:21+'
     compile 'com.android.support:cardview-v7:21.0.2'
-    provided 'com.android.databinding:annotationprocessor:0.1-SNAPSHOT'
 }
diff --git a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
index 02f3d7b..51b1c90 100644
--- a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
+++ b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
@@ -1,6 +1,5 @@
 package com.android.example.bindingdemo;
 
-import android.binding.Bindable;
 import android.support.v7.app.ActionBarActivity;
 import android.os.Bundle;
 import android.support.v7.widget.LinearLayoutManager;
@@ -10,14 +9,15 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.databinding.library.ChangeListenerRegistry;
-import com.android.databinding.library.Observable;
-import com.android.databinding.library.OnPropertyChangedListener;
+import com.android.example.bindingdemo.generated.BR;
 import com.android.example.bindingdemo.generated.ListItemBinder;
 import com.android.example.bindingdemo.generated.MainActivityBinder;
 import com.android.example.bindingdemo.vo.User;
 import com.android.example.bindingdemo.vo.Users;
 import com.android.databinding.library.DataBinder;
+import com.android.databinding.library.Observable;
+import com.android.databinding.library.ObservableHelper;
+import com.android.databinding.library.ObservableListener;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -28,13 +28,13 @@
     UserAdapter tkAdapter;
     UserAdapter robotAdapter;
     MainActivityBinder dataBinder;
-    @Bindable
     User selected;
-    ChangeListenerRegistry mChangeListeners = new ChangeListenerRegistry();
+    ObservableHelper helper;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        helper = new ObservableHelper(this);
         dataBinder = DataBinder.createBinder(MainActivityBinder.class, this, R.layout.main_activity, null);
         setContentView(dataBinder.getRoot());
         dataBinder.getRobotList().setHasFixedSize(true);
@@ -64,7 +64,7 @@
             return;
         }
         this.selected = selected;
-        mChangeListeners.notifyCallbacks(this, android.binding.BR.selected);
+        helper.fireChange(BR.selected);
     }
 
     public View.OnClickListener onSave = new View.OnClickListener() {
@@ -130,20 +130,21 @@
     }
 
     @Override
-    public void addListener(OnPropertyChangedListener onPropertyChangedListener) {
-        mChangeListeners.add(onPropertyChangedListener);
+    public void register(ObservableListener observableListener) {
+        helper.register(observableListener);
     }
 
     @Override
-    public void removeListener(OnPropertyChangedListener onPropertyChangedListener) {
-        mChangeListeners.remove(onPropertyChangedListener);
+    public void unRegister(ObservableListener observableListener) {
+        helper.unRegister(observableListener);
     }
 
     public class UserAdapter extends DataBoundAdapter<ListItemBinder> implements View.OnClickListener, Observable {
-        List<User> userList = new ArrayList<User>();
-        ChangeListenerRegistry mChangeListeners = new ChangeListenerRegistry();
+        List<User> userList = new ArrayList<>();
+        ObservableHelper mHelper;
         public UserAdapter(User[] toolkities) {
             super(R.layout.list_item, ListItemBinder.class);
+            mHelper = new ObservableHelper(this);
             userList.addAll(Arrays.asList(toolkities));
         }
 
@@ -161,7 +162,6 @@
         }
 
         @Override
-        @Bindable
         public int getItemCount() {
             return userList.size();
         }
@@ -172,7 +172,7 @@
             }
             userList.add(user);
             notifyItemInserted(userList.size() - 1);
-            mChangeListeners.notifyCallbacks(this, android.binding.BR.itemCount);
+            mHelper.fireChange("itemCount");
         }
 
         public void remove(User user) {
@@ -182,7 +182,7 @@
             }
             userList.remove(i);
             notifyItemRemoved(i);
-            mChangeListeners.notifyCallbacks(this, android.binding.BR.itemCount);
+            mHelper.fireChange("itemCount");
         }
 
         @Override
@@ -198,13 +198,13 @@
         }
 
         @Override
-        public void addListener(OnPropertyChangedListener onPropertyChangedListener) {
-            mChangeListeners.add(onPropertyChangedListener);
+        public void register(ObservableListener observableListener) {
+            mHelper.register(observableListener);
         }
 
         @Override
-        public void removeListener(OnPropertyChangedListener onPropertyChangedListener) {
-            mChangeListeners.remove(onPropertyChangedListener);
+        public void unRegister(ObservableListener observableListener) {
+            mHelper.unRegister(observableListener);
         }
     }
 }
diff --git a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
index 8ea225d..091dc5c 100644
--- a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
+++ b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
@@ -1,23 +1,17 @@
 package com.android.example.bindingdemo.vo;
 
-import android.binding.Bindable;
 import android.graphics.Color;
 
-import com.android.databinding.library.AbsObservable;
+import com.android.databinding.library.BaseObservable;
 
 import java.util.Objects;
 
-public class User extends AbsObservable {
-    @Bindable
+public class User extends BaseObservable {
     private String name;
-    @Bindable
     private String lastName;
-    @Bindable
     private int photoResource = 0;
     private int favoriteColor = Color.RED;
-    @Bindable
     private int group;
-
     public static final int TOOLKITTY = 1;
     public static final int ROBOT = 2;
 
@@ -33,7 +27,7 @@
             return;
         }
         this.group = group;
-        notifyChange(android.binding.BR.group);
+        fireChange("group");
     }
 
     public int getGroup() {
@@ -49,7 +43,7 @@
             return;
         }
         this.name = name;
-        notifyChange(android.binding.BR.name);
+        fireChange("name");
     }
 
     public String getLastName() {
@@ -61,7 +55,7 @@
             return;
         }
         this.lastName = lastName;
-        notifyChange(android.binding.BR.lastName);
+        fireChange("lastName");
     }
 
     public int getPhotoResource() {
@@ -73,7 +67,7 @@
             return;
         }
         this.photoResource = photoResource;
-        notifyChange(android.binding.BR.photoResource);
+        fireChange("photoResource");
     }
 
     public int getFavoriteColor() {
diff --git a/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties b/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
index 1d32c67..ddbd613 100644
--- a/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
+++ b/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,22 @@
-#Mon Dec 15 15:24:30 PST 2014
+#
+# Copyright (C) 2014 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.
+#
+
+#Wed Apr 10 15:27:10 PDT 2013
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
diff --git a/settings.gradle b/settings.gradle
index e1f91a6..c069a57 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,4 @@
-include ':library', ':annotationprocessor'
+include ':library'
 include ':compiler'
 include ':gradlePlugin'
-include ':grammerBuilder'
+include ':grammerBuilder'
\ No newline at end of file