All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.zkoss.bind.proxy.MapProxy Maven / Gradle / Ivy
/** MapProxy.java.
Purpose:
Description:
History:
4:14:18 PM Dec 26, 2014, Created by jumperchen
Copyright (C) 2014 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.bind.proxy;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.bind.BindContext;
import org.zkoss.bind.annotation.ImmutableElements;
import org.zkoss.bind.sys.FormBinding;
import org.zkoss.bind.sys.SavePropertyBinding;
import org.zkoss.util.Pair;
/**
* A proxy object to implement Map
*
* @author jumperchen
* @since 8.0.0
*/
public class MapProxy implements Map, Proxy, FormProxyObject, Serializable {
private static final Logger log = LoggerFactory.getLogger(MapProxy.class);
private Map _cache;
private boolean _dirty;
private Map _origin;
private List _callerAnnots;
private static final long serialVersionUID = 20141226161502L;
private boolean isImmutableElements;
//ZK-3185: Enable form validation with reference and collection binding
private ProxyNode _node;
public MapProxy(Map origin, Annotation[] callerAnnots) {
_origin = origin;
_cache = new MapForCache(origin.size());
if (callerAnnots != null) {
for (Annotation annot : callerAnnots) {
if (annot.annotationType().isAssignableFrom(ImmutableElements.class)) {
isImmutableElements = true;
break;
}
}
}
resetFromOrigin();
}
public Object getOriginObject() {
return _origin;
}
@SuppressWarnings("unchecked")
protected Object replaceOrigin(Object origin) {
Object old = _origin;
_origin = (Map) origin;
return old;
}
public Set> entrySet() {
return _cache.entrySet();
}
@SuppressWarnings("unchecked")
public void resetFromOrigin() {
_cache.clear();
setDirty(false);
for (Map.Entry me : ((Map) getOriginObject()).entrySet()) {
V o = createProxyObject(me.getValue());
_cache.put(createProxyObject(me.getKey()), o);
if (o instanceof FormProxyObject)
setCreatedProxyPath((FormProxyObject) o, me.getKey());
}
}
@SuppressWarnings("unchecked")
public void submitToOrigin(BindContext ctx) {
_origin.clear();
for (Map.Entry me : _cache.entrySet()) {
V value = me.getValue();
if (value instanceof FormProxyObject) {
FormProxyObject proxyValue = (FormProxyObject) value;
proxyValue.submitToOrigin(ctx);
_origin.put(me.getKey(), (V) proxyValue.getOriginObject());
} else {
_origin.put(me.getKey(), me.getValue());
}
}
setDirty(false);
}
//F80: formProxyObject support notifyChange with Form.isDirty
public void onDirtyChange() {
ProxyHelper.callOnDirtyChange(_node);
}
public void onDataChange(Object o) {
ProxyHelper.callOnDataChange(_node, new Object[]{o, "."});
}
protected void setDirty(boolean d) {
if (_dirty != d) {
_dirty = d;
onDirtyChange();
}
if (d)
onDataChange(this);
}
public boolean isFormDirty() {
if (_dirty) {
return true;
} else {
for (Map.Entry me : _cache.entrySet()) {
if (me.getValue() instanceof FormProxyObject) {
if (((FormProxyObject) me.getValue()).isFormDirty())
return true;
}
}
}
return false;
}
public void setHandler(MethodHandler mi) {
throw new UnsupportedOperationException("Not support!");
}
public int size() {
return _cache.size();
}
public boolean isEmpty() {
return size() == 0;
}
public boolean containsKey(Object key) {
return _cache.containsKey(createProxyObject(key));
}
public boolean containsValue(Object value) {
Iterator it = _cache.values().iterator();
Object proxyValue = createProxyObject(value);
while (it.hasNext()) {
if (AbstractCollectionProxy.testEquals(it.next(), proxyValue))
return true;
}
return false;
}
public V get(Object key) {
return _cache.get(createProxyObject(key));
}
public V put(K key, V value) {
setDirty(true);
V o = createProxyObject(value);
if (o instanceof FormProxyObject)
setCreatedProxyPath((FormProxyObject) o, key);
return _cache.put(createProxyObject(key), o);
}
public V remove(Object key) {
setDirty(true);
return _cache.remove(createProxyObject(key));
}
public void putAll(Map extends K, ? extends V> m) {
for (Map.Entry extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
}
public void clear() {
setDirty(true);
_cache.clear();
}
public Set keySet() {
return _cache.keySet();
}
public Collection values() {
return _cache.values();
}
public void setFormOwner(Object owner, FormBinding binding) {
throw new IllegalAccessError("Not supported");
}
private T createProxyObject(T t) {
return isImmutableElements ? t : ProxyHelper.createProxyIfAny(t);
}
//ZK-3185: Enable form validation with reference and collection binding
private void setCreatedProxyPath(FormProxyObject fpo, Object key) {
fpo.setPath("['" + key + "']", _node);
}
public void cacheSavePropertyBinding(String property, SavePropertyBinding s) {
ProxyHelper.cacheSavePropertyBinding(_node, _node.getProperty() + "['" + property + "']" , s);
}
public Set> collectCachedSavePropertyBinding() {
throw new UnsupportedOperationException("Not support!");
}
public void setPath(String property, ProxyNode parent) {
if (property == null && _node != null) { // means update
_node.setParent(parent);
} else {
_node = new ProxyNodeImpl(property, parent);
for (Entry e : _cache.entrySet()) {
if (e.getValue() instanceof FormProxyObject)
((FormProxyObject) _cache.get(e.getKey())).setPath(null, _node);
}
}
}
private class MapForCache extends LinkedHashMap {
private transient Set> _entrySetProxy = null;
private transient Set _keySetProxy = null;
public MapForCache() {
super();
}
public MapForCache(int size) {
super(size);
}
@Override
public Set> entrySet() {
return _entrySetProxy == null ? createProxy(true) : _entrySetProxy;
}
@Override
public Set keySet() {
return _keySetProxy == null ? createProxy(false) : _keySetProxy;
}
private Set createProxy(boolean isEntry) {
Set proxy = null;
ProxyFactory factory = new ProxyFactory();
factory.setUseWriteReplace(false);
factory.setSuperclass(AbstractSet.class);
factory.createClass();
try {
if (isEntry) {
proxy = _entrySetProxy = (Set>) factory.createClass().newInstance();
((Proxy) _entrySetProxy).setHandler(new SetHandlerForCache(super.entrySet()));
} else {
proxy = _keySetProxy = (Set) factory.createClass().newInstance();
((Proxy) _keySetProxy).setHandler(new SetHandlerForCache(super.keySet()));
}
} catch (Exception e) {
//should not error
log.warn("", e);
}
return proxy;
}
}
private class SetHandlerForCache implements MethodHandler {
private Set _origin;
public SetHandlerForCache(Set origin) {
_origin = origin;
}
public Object invoke(Object self, Method method, Method proceed, Object[] args) throws Throwable {
final String mname = method.getName();
if (mname.equals("contains")) {
return method.invoke(_origin, createProxyObject(args[0]));
} else if (mname.equals("remove")) {
return method.invoke(_origin, createProxyObject(args[0]));
}
return method.invoke(_origin, args);
}
}
}