Package org.gridkit.coherence.txlite

Source Code of org.gridkit.coherence.txlite.TxCacheWrapper$EntryWrapper

/**
* Copyright 2011 Grid Dynamics Consulting Services, Inc.
*
* 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 org.gridkit.coherence.txlite;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.tangosol.net.CacheService;
import com.tangosol.net.NamedCache;
import com.tangosol.util.Filter;
import com.tangosol.util.MapListener;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.AlwaysFilter;
import com.tangosol.util.filter.EqualsFilter;

/**
* @author Alexey Ragozin (alexey.ragozin@gmail.com)
*/
@SuppressWarnings("deprecation")
class TxCacheWrapper implements NamedCache, TxWrappedCache {

  private NamedCache nestedCache;
  private CacheAccessAdapter adapter;
 
  public TxCacheWrapper(NamedCache nestedCache, CacheAccessAdapter adapter) {
    this.nestedCache = nestedCache;
    this.adapter = adapter;
  }
 
  @Override
  public String getCacheName() {
    return nestedCache.getCacheName();
  }
 
  public NamedCache getVersionedCache() {
    return nestedCache;
  }
 
  @Override
  public TxSession getSession() {
    return (TxSession) (adapter instanceof TxSession ? adapter : null);
  }

  @Override
  public CacheService getCacheService() {
    return nestedCache.getCacheService();
  }

  @Override
  public boolean isActive() {
    return nestedCache.isActive();
  }

  /**
   * Transactionally inaccurate, may return true even is key is invisible
   * to a transaction.
   */
  @Override
  public boolean containsKey(Object key) {
    return nestedCache.containsKey(key);
  }

  @Override
  public boolean containsValue(Object value) {
    // brute force search
    return !keySet(new EqualsFilter(IdentityExtractor.INSTANCE, value)).isEmpty();
  }

  @Override
  public Object get(Object oKey) {
    adapter.beforeOperation(this);
    Object result = internalGet(oKey);
    adapter.afterOperation(this);
    return result;
  }

  protected Object internalGet(Object oKey) {
    ValueContatiner vc = (ValueContatiner) nestedCache.get(oKey);
    Object result = vc == null ? null : adapter.transformValue(this, vc);
    return result;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Map getAll(Collection keys) {
    adapter.beforeOperation(this);
    Map vclist = nestedCache.getAll(keys);
    Map result = new HashMap();
    for(Map.Entry entry: (Collection<Map.Entry>)vclist.entrySet()) {
      Object key = entry.getKey();
      ValueContatiner vc = (ValueContatiner) entry.getValue();
      Object value = vc == null ? null : adapter.transformValue(this, vc);
      if (value != null) {
        result.put(key, value);
      }
    }
    adapter.afterOperation(this);
    return result;
  }

  @Override
  public Object put(Object key, Object value) {
    if (adapter.isReadOnly(this)) {
      throw new UnsupportedOperationException("Read only mode");
    }
    adapter.beforeOperation(this);
    // TODO not efficient but functional
    Object oldValue = internalGet(key);
    adapter.markDirty(this, key);
    nestedCache.invoke(key, adapter.newPutProcessor(this, key, value));
    adapter.afterOperation(this);
    return oldValue;
  }

  @Override
  @SuppressWarnings("unchecked")
  public void putAll(Map m) {
    if (adapter.isReadOnly(this)) {
      throw new UnsupportedOperationException("Read only mode");
    }
    adapter.beforeOperation(this);
    // TODO not efficient but functional
    adapter.markDirty(this, m.keySet());
    nestedCache.invokeAll(new HashSet(m.keySet()), adapter.newPutProcessor(this, new HashMap(m)));
    adapter.afterOperation(this);
  }

  @Override
  public Object put(Object key, Object value, long expiry) {
    throw new UnsupportedOperationException("Expiry is not supported by TxLite cache");
  }

  @Override
  public Object remove(Object key) {
    if (adapter.isReadOnly(this)) {
      throw new UnsupportedOperationException("Read only mode");
    }
    return put(key, null); // null is equivalent to no value
  }

  /**
   * Transactionally inaccurate, may return true even is key is invisible
   * to a transaction.
   */
  @Override
  @SuppressWarnings("unchecked")
  public Set keySet() {
    Set keys = new HashSet(nestedCache.keySet());
    return new WrapperSetView(keys) {
           
      @Override
      protected void delete(Object element) {
        remove(element);
        delegate.remove(element);
      }
     
      @Override
      protected void deleteAll(Collection elements) {
        removeAll(elements);
        delegate.removeAll(elements);
      }
    };
  }

  @Override
  @SuppressWarnings("unchecked")
  public Set keySet(Filter filter) {
    adapter.beforeOperation(this);
    Filter transformed = adapter.transformFilter(this, filter);
    Set keys = new HashSet(nestedCache.keySet(transformed));
    WrapperSetView wrapperSetView = new WrapperSetView(keys) {
           
      @Override
      protected void delete(Object element) {
        remove(element);
        delegate.remove(element);
      }
     
      @Override
      protected void deleteAll(Collection elements) {
        removeAll(elements);
        delegate.removeAll(elements);
      }
    };
    adapter.afterOperation(this);
    return wrapperSetView;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Set entrySet() {
    return entrySet(AlwaysFilter.INSTANCE);
  }

  @Override
  @SuppressWarnings("unchecked")
  public Set entrySet(Filter filter) {
    adapter.beforeOperation(this);
    Filter transformedFilter = adapter.transformFilter(this, filter);
    Set entries = new HashSet(nestedCache.entrySet(transformedFilter));
    Set result = new HashSet(entries.size());
    for(Object x: entries) {
      Map.Entry centry = (Map.Entry) x;
      result.add(new EntryWrapper(centry.getKey(), adapter.transformValue(this, (ValueContatiner) centry.getValue())));
    }
   
    WrapperSetView wrapperSetView = new WrapperSetView(result) {
           
      @Override
      protected void delete(Object element) {
        remove(((Map.Entry)element).getKey());
        delegate.remove(element);
      }
     
      @Override
      protected void deleteAll(Collection elements) {
        List keys = new ArrayList();
        for (Object e : elements) {
          keys.add(((Map.Entry)e).getKey());
        }
        removeAll(keys);
        delegate.removeAll(elements);
      }
    };
    adapter.afterOperation(this);
    return wrapperSetView;
  }
 
  @Override
  @SuppressWarnings("unchecked")
  public Set entrySet(Filter filter, final Comparator comparator) {
    adapter.beforeOperation(this);
    Filter transformedFilter = adapter.transformFilter(this, filter);
    Set entries = new HashSet(nestedCache.entrySet(transformedFilter));
    List result = new ArrayList(entries.size());
    for(Object x: entries) {
      Map.Entry centry = (Map.Entry) x;
      result.add(new EntryWrapper(centry.getKey(), adapter.transformValue(this, (ValueContatiner) centry.getValue())));
    }
   
    Collections.sort(result, new Comparator() {
      @Override
      public int compare(Object o1, Object o2) {
        o1 = ((Map.Entry)o1).getValue();
        o2 = ((Map.Entry)o2).getValue();
        if (comparator == null) {
          return ((Comparable)o1).compareTo(o2);
        }
        else {
          return comparator.compare(o1, o2);
        }
      }
    });
   
    WrapperSetView wrapperSetView = new WrapperSetView(result) {
           
      @Override
      protected void delete(Object element) {
        remove(((Map.Entry)element).getKey());
        delegate.remove(element);
      }
     
      @Override
      protected void deleteAll(Collection elements) {
        List keys = new ArrayList();
        for (Object e : elements) {
          keys.add(((Map.Entry)e).getKey());
        }
        removeAll(keys);
        delegate.removeAll(elements);
      }
    };
    adapter.afterOperation(this);
    return wrapperSetView;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Collection values() {
    adapter.beforeOperation(this);
    Collection values = nestedCache.values();
    List result = new ArrayList(values.size());
    for(Object value : values) {
      Object cv = adapter.transformValue(this, (ValueContatiner) value);
      if (cv != null) {
        result.add(cv);
      }
    }   
    adapter.afterOperation(this);
    return result;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Object aggregate(Collection collKeys, EntryAggregator agent) {
    adapter.beforeOperation(this);
    EntryAggregator transformedAgent = adapter.transformAggregator(this, agent);
    Object result = nestedCache.aggregate(collKeys, transformedAgent);
    adapter.afterOperation(this);
    return result;
  }

  @Override
  public Object aggregate(Filter filter, EntryAggregator agent) {
    adapter.beforeOperation(this);
    Filter transformedFilter = adapter.transformFilter(this, filter);
    EntryAggregator transformedAgent = adapter.transformAggregator(this, agent);
    Object result = nestedCache.aggregate(transformedFilter, transformedAgent);
    adapter.afterOperation(this);
    return result;
  }

  @Override
  public Object invoke(Object key, EntryProcessor agent) {
    if (adapter.isReadOnly(this)) {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      Object result = nestedCache.invoke(key, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
    else {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      adapter.markDirty(this, key);
      Object result = nestedCache.invoke(key, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
  }

  @Override
  @SuppressWarnings("unchecked")
  public Map invokeAll(Collection keys, EntryProcessor agent) {
    if (adapter.isReadOnly(this)) {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      Map result = nestedCache.invokeAll(keys, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
    else {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      adapter.markDirty(this, keys);
      Map result = nestedCache.invokeAll(keys, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
  }

  @Override
  @SuppressWarnings("unchecked")
  public Map invokeAll(Filter filter, EntryProcessor agent) {
    if (adapter.isReadOnly(this)) {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      Filter transformedFilter = adapter.transformFilter(this, filter);
      Map result = nestedCache.invokeAll(transformedFilter, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
    else {
      adapter.beforeOperation(this);
      EntryProcessor transformedAgent = adapter.transformProcessor(this, agent);
      Filter transformedFilter = adapter.transformFilter(this, filter);
      // all keys affected by processor should be marked as dirty in transaction
      Collection keys = nestedCache.keySet(transformedFilter);
      adapter.markDirty(this, keys);
      Map result = nestedCache.invokeAll(keys, transformedAgent);
      adapter.afterOperation(this);
      return result;
    }
  }

  /**
   * Transactionally inaccurate, may count keys not visible for current transaction.
   */
  @Override
  public boolean isEmpty() {
    return nestedCache.isEmpty();
  }

  /**
   * Transactionally inaccurate, may count keys not visible for current transaction.
   */
  @Override
  public int size() {
    return nestedCache.size();
  }

  @Override
  public void clear() {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean lock(Object key) {
    return nestedCache.lock(key);
  }
 
  @Override
  public boolean lock(Object key, long timeout) {
    return nestedCache.lock(key, timeout);
  }

  @Override
  public boolean unlock(Object key) {
    return nestedCache.unlock(key);
  }

  @Override
  public void destroy() {
    nestedCache.release();   
  }

  @Override
  public void release() {
    nestedCache.release();   
  }

  @Override
  @SuppressWarnings("unchecked")
  public void addIndex(ValueExtractor extractor, boolean fOrdered, Comparator comparator) {
    // does not count as cache operation
    ValueExtractor transformed = adapter.transformIndexExtractor(this, extractor);
    nestedCache.addIndex(transformed, fOrdered, comparator);
  }

  @Override
  public void removeIndex(ValueExtractor extractor) {
    // does not count as cache operation
    ValueExtractor transformed = adapter.transformIndexExtractor(this, extractor);
    nestedCache.removeIndex(transformed);
  }

  @Override
  public void addMapListener(MapListener listener) {
    MapListener transformend = adapter.transformListener(this, listener);
    nestedCache.addMapListener(transformend);
  }

  @Override
  public void addMapListener(MapListener listener, Object key, boolean lite) {
    MapListener transformend = adapter.transformListener(this, listener);
    nestedCache.addMapListener(transformend, key, true);
  }

  @Override
  public void addMapListener(MapListener listener, Filter filter, boolean lite) {
    MapListener transformend = adapter.transformListener(this, listener);
    Filter transformedFilter = adapter.transformListenerFilter(this, filter);
    nestedCache.addMapListener(transformend, transformedFilter, true);
  }

  @Override
  public void removeMapListener(MapListener listener) {
    MapListener transformend = adapter.transformListener(this, listener);
    nestedCache.removeMapListener(transformend);
  }

  @Override
  public void removeMapListener(MapListener listener,  Object key) {
    MapListener transformend = adapter.transformListener(this, listener);
    nestedCache.removeMapListener(transformend, key);
  }

  @Override
  public void removeMapListener(MapListener listener,  Filter filter) {
    MapListener transformend = adapter.transformListener(this, listener);
    Filter transformedFilter = adapter.transformListenerFilter(this, filter);
    nestedCache.removeMapListener(transformend, transformedFilter);
  }
 
  @SuppressWarnings("unchecked")
  private abstract static class WrapperSetView implements Set {

    protected Collection delegate;
 
    public WrapperSetView(Collection delegate) {
      this.delegate = delegate;
    }
   
    protected boolean isConverted() {
      return false;
    }
   
    protected Object convert(Object element) {
      return element;
    }
   
    protected abstract void delete(Object element);

    protected abstract void deleteAll(Collection element);

    @Override
    public boolean add(Object e) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean addAll(Collection c) {
      if (!c.isEmpty()) {
        throw new UnsupportedOperationException();
      }
      else {
        return false;
      }
    }

    @Override
    public void clear() {
      if (!isConverted()) {
        deleteAll(delegate);
      }
      else {
        deleteAll(Arrays.asList(toArray()));
      }
    }

    @Override
    public boolean contains(Object o) {
      if (o == null) {
        return false;
      }
      else if (!isConverted()) {
        return delegate.contains(o);
      }
      else {
        for(Object obj : delegate) {
          if (o.equals(convert(obj))) {
            return true;
          }
        }
        return false;
      }
    }

    @Override
    public boolean containsAll(Collection c) {
      for(Object o : c) {
        if (!contains(o)) {
          return false;
        }
      }
      return true;
    }

    @Override
    public boolean isEmpty() {
      return delegate.isEmpty();
    }

    @Override
    public Iterator iterator() {
      final Iterator nested = delegate.iterator();
      return new Iterator() {
       
        Object last = null;
       
        @Override
        public boolean hasNext() {
          return nested.hasNext();
        }

        @Override
        public Object next() {
          last = nested.next();
          return convert(last);
        }

        @Override
        public void remove() {
          if (last == null) {
            throw new IllegalStateException();
          }
          else {
            delete(convert(last));
          }
        }
      };
    }

    @Override
    public boolean remove(Object o) {
      boolean contains = contains(o);
      delete(o);
      return contains;
    }

    @Override
    public boolean removeAll(Collection c) {
      int size = delegate.size();
      deleteAll(c);
      return size != delegate.size();
    }

    @Override
    public boolean retainAll(Collection c) {
      List forRemoval = new ArrayList();
      for(Object x : delegate) {
        Object y = convert(x);
        if (!c.contains(y)) {
          forRemoval.add(y);
        }
      }
      deleteAll(forRemoval);
      return forRemoval.size() > 0;
    }

    @Override
    public int size() {
      return delegate.size();
    }

    @Override
    public Object[] toArray() {
      return toArray(new Object[size()]);
    }

    @Override
    public Object[] toArray(Object[] a) {
      if (a.length < size()) {
        a = Arrays.copyOf(a, size());
      }
      int n = 0;
      for(Object x : delegate) {
        Object y = convert(x);
        a[n] = y;
        ++n;
      }
      return a;
    }
   
    @Override
    public String toString() {
      return Arrays.toString(toArray());
    }
  }
 
  @SuppressWarnings("unchecked")
  private class EntryWrapper implements Map.Entry {

    private Object key;
    private Object value;

    public EntryWrapper(Object key, Object value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public Object getKey() {
      return key;
    }

    @Override
    public Object getValue() {
      return value;
    }

    @Override
    public Object setValue(Object value) {
      Object old = put(key, value);
      this.value = get(key);
      return old;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((key == null) ? 0 : key.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      EntryWrapper other = (EntryWrapper) obj;
      if (!getOuterType().equals(other.getOuterType()))
        return false;
      if (key == null) {
        if (other.key != null)
          return false;
      } else if (!key.equals(other.key))
        return false;
      return true;
    }

    private TxCacheWrapper getOuterType() {
      return TxCacheWrapper.this;
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append(key).append("->").append(value);
      return builder.toString();
    }
  }
}
TOP

Related Classes of org.gridkit.coherence.txlite.TxCacheWrapper$EntryWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.