package org.holoeverywhere.addon;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.holoeverywhere.addon.IAddon.Addon;
public final class IAddonBasicAttacher<V extends IAddonBase<Z>, Z> implements IAddonAttacher<V> {
private final class AddonComparator implements Comparator<V> {
@Override
public int compare(V lhs, V rhs) {
final int i1 = getWeight(lhs.getParent());
final int i2 = getWeight(rhs.getParent());
return i1 > i2 ? 1 : i1 < i2 ? -1 : 0;
}
private int getWeight(IAddon addon) {
if (addon.getClass().isAnnotationPresent(Addon.class)) {
return addon.getClass().getAnnotation(Addon.class).weight();
}
return -1;
}
}
private final Map<Class<? extends IAddon>, V> mAddons = new HashMap<Class<? extends IAddon>, V>();
private final Set<V> mAddonsList = new TreeSet<V>(new AddonComparator());
private boolean mLockAttaching = false;
private Z mObject;
public IAddonBasicAttacher(Z object) {
mObject = object;
}
@Override
@SuppressWarnings("unchecked")
public <T extends V> T addon(Class<? extends IAddon> clazz) {
T addon = (T) mAddons.get(clazz);
if (addon == null) {
if (mLockAttaching) {
throw new AttachException(mObject, clazz);
}
addon = IAddon.obtain(clazz, mObject);
if (addon == null) {
return null;
}
mAddons.put(clazz, addon);
mAddonsList.add(addon);
}
return addon;
}
@Override
public void addon(Collection<Class<? extends IAddon>> classes) {
if (classes == null) {
return;
}
for (Class<? extends IAddon> clazz : classes) {
addon(clazz);
}
}
@Override
public <T extends V> T addon(String classname) {
return addon(IAddon.makeAddonClass(classname));
}
public void inhert(Collection<Class<? extends IAddon>> sourceClasses) {
if (sourceClasses == null || sourceClasses.size() == 0) {
return;
}
List<Class<? extends IAddon>> classes = new ArrayList<Class<? extends IAddon>>();
for (Class<? extends IAddon> clazz : sourceClasses) {
if (!clazz.isAnnotationPresent(Addon.class)) {
continue;
}
Addon addon = clazz.getAnnotation(Addon.class);
if (addon.inhert()) {
classes.add(clazz);
}
}
addon(classes);
}
public void inhert(IAddonAttacher<?> attacher) {
inhert(attacher == null ? null : attacher.obtainAddonsList());
}
@Override
public boolean isAddonAttached(Class<? extends IAddon> clazz) {
return mAddons.containsKey(clazz);
}
@Override
public void lockAttaching() {
mLockAttaching = true;
}
@Override
public Collection<Class<? extends IAddon>> obtainAddonsList() {
return new ArrayList<Class<? extends IAddon>>(mAddons.keySet());
}
@Override
public boolean performAddonAction(AddonCallback<V> callback) {
if (mAddons.size() == 0) {
return false;
}
callback.pre();
boolean result = false;
for (V addon : mAddonsList) {
result = callback.performAction(addon);
if (callback.mStopped) {
return result;
}
}
return callback.post();
}
public void reset() {
mAddons.clear();
mAddonsList.clear();
mLockAttaching = false;
}
}