Skip to content

Commit

Permalink
implemented invoke and invokeAll
Browse files Browse the repository at this point in the history
  • Loading branch information
ocafebabe committed Feb 26, 2016
1 parent 56042ed commit 3e452b5
Show file tree
Hide file tree
Showing 4 changed files with 287 additions and 2 deletions.
35 changes: 33 additions & 2 deletions src/main/java/ca/exprofesso/guava/jcache/GuavaCache.java
Expand Up @@ -18,6 +18,7 @@
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -429,14 +430,44 @@ public <C extends Configuration<K, V>> C getConfiguration(Class<C> clazz)
public <T> T invoke(K key, EntryProcessor<K, V, T> entryProcessor, Object... arguments)
throws EntryProcessorException
{
throw new UnsupportedOperationException("Not supported yet.");
checkState();

if (key == null || entryProcessor == null)
{
throw new NullPointerException();
}

V value = get(key);

GuavaMutableEntry<K, V> entry = new GuavaMutableEntry<>(key, value);

T t = entryProcessor.process(entry, arguments);

if (entry.isUpdated())
{
replace(key, entry.getValue());
}

if (entry.isRemoved())
{
remove(key);
}

return t;
}

@Override
public <T> Map<K, EntryProcessorResult<T>>
invokeAll(Set<? extends K> keys, EntryProcessor<K, V, T> entryProcessor, Object... arguments)
{
throw new UnsupportedOperationException("Not supported yet.");
Map<K, EntryProcessorResult<T>> results = new HashMap<>();

for (K key : keys)
{
results.put(key, new GuavaEntryProcessorResult<>(invoke(key, entryProcessor, arguments)));
}

return results;
}

@Override
Expand Down
@@ -0,0 +1,36 @@
/*
* Copyright 2016 ExProfesso.
*
* 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 ca.exprofesso.guava.jcache;

import javax.cache.processor.EntryProcessorException;

public class GuavaEntryProcessorResult<T>
implements javax.cache.processor.EntryProcessorResult<T>
{
private final T t;

public GuavaEntryProcessorResult(T t)
{
this.t = t;
}

@Override
public T get()
throws EntryProcessorException
{
return t;
}
}
87 changes: 87 additions & 0 deletions src/main/java/ca/exprofesso/guava/jcache/GuavaMutableEntry.java
@@ -0,0 +1,87 @@
/*
* Copyright 2016 ExProfesso.
*
* 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 ca.exprofesso.guava.jcache;

public class GuavaMutableEntry<K, V>
implements javax.cache.processor.MutableEntry<K, V>
{
private final K key;
private final V oldValue;

private volatile V newValue;
private volatile boolean removed;
private volatile boolean updated;

public GuavaMutableEntry(K key, V oldValue)
{
this.key = key;
this.oldValue = oldValue;
this.newValue = oldValue;
}

@Override
public boolean exists()
{
return !removed && ((oldValue != null) || (newValue != null));
}

@Override
public void remove()
{
removed = true;
}

@Override
public void setValue(V value)
{
newValue = value;

updated = true;
}

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

@Override
public V getValue()
{
if (newValue != oldValue)
{
return newValue;
}

return oldValue;
}

@Override
public <T> T unwrap(Class<T> clazz)
{
return clazz.cast(this);
}

protected boolean isRemoved()
{
return removed;
}

protected boolean isUpdated()
{
return updated;
}
}
131 changes: 131 additions & 0 deletions src/test/java/ca/exprofesso/guava/jcache/GuavaCacheTest.java
Expand Up @@ -44,6 +44,9 @@
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CompletionListener;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.MutableEntry;
import javax.cache.spi.CachingProvider;
import javax.management.MBeanServer;
import javax.management.ObjectName;
Expand Down Expand Up @@ -437,6 +440,134 @@ public CacheLoader<String, Integer> create()
assertEquals(Integer.valueOf(6), loadingCache.getAndRemove("6"));
}

@Test
public void testInvoke()
{
final CacheLoader<String, Integer> cacheLoader = new CacheLoader<String, Integer>()
{
@Override
public Integer load(String key)
throws CacheLoaderException
{
return Integer.valueOf(key);
}

@Override
public Map<String, Integer> loadAll(Iterable<? extends String> keys)
throws CacheLoaderException
{
throw new UnsupportedOperationException("Not supported yet.");
}
};

final EntryProcessor<String, Integer, Boolean> entryProcessor = new EntryProcessor<String, Integer, Boolean>()
{
@Override
public Boolean process(MutableEntry<String, Integer> entry, Object... arguments)
throws EntryProcessorException
{
assertTrue(entry.exists());
assertEquals(Integer.valueOf(1), entry.getValue());
entry.setValue(2);
assertEquals(Integer.valueOf(2), entry.getValue());
entry.remove();
assertFalse(entry.exists());

return Boolean.TRUE;
}
};

MutableConfiguration<String, Integer> custom = new MutableConfiguration<>(configuration);

custom.setReadThrough(true);
custom.setCacheLoaderFactory
(
new Factory<CacheLoader<String, Integer>>()
{
@Override
public CacheLoader<String, Integer> create()
{
return cacheLoader;
}
}
);

Cache<String, Integer> invokingCache = cacheManager.createCache("invokingCache", custom);

assertTrue(invokingCache.invoke("1", entryProcessor));
assertFalse(invokingCache.containsKey("1"));
}

@Test
public void testInvokeAll()
{
final CacheLoader<String, Integer> cacheLoader = new CacheLoader<String, Integer>()
{
@Override
public Integer load(String key)
throws CacheLoaderException
{
return Integer.valueOf(key);
}

@Override
public Map<String, Integer> loadAll(Iterable<? extends String> keys)
throws CacheLoaderException
{
throw new UnsupportedOperationException("Not supported yet.");
}
};

final EntryProcessor<String, Integer, Void> entryProcessor1 = new EntryProcessor<String, Integer, Void>()
{
@Override
public Void process(MutableEntry<String, Integer> entry, Object... arguments)
throws EntryProcessorException
{
assertTrue(entry.exists());
assertEquals(Integer.valueOf(1), entry.getValue());
entry.setValue(2);
assertEquals(Integer.valueOf(2), entry.getValue());

return null;
}
};

final EntryProcessor<String, Integer, Void> entryProcessor2 = new EntryProcessor<String, Integer, Void>()
{
@Override
public Void process(MutableEntry<String, Integer> entry, Object... arguments)
throws EntryProcessorException
{
entry.remove();

return null;
}
};

MutableConfiguration<String, Integer> custom = new MutableConfiguration<>(configuration);

custom.setReadThrough(true);
custom.setCacheLoaderFactory
(
new Factory<CacheLoader<String, Integer>>()
{
@Override
public CacheLoader<String, Integer> create()
{
return cacheLoader;
}
}
);

Cache<String, Integer> invokingCache = cacheManager.createCache("invokingCache", custom);

assertNull(invokingCache.invoke("1", entryProcessor1));
assertEquals(Integer.valueOf(2), invokingCache.get("1"));
assertNull(invokingCache.invoke("1", entryProcessor2));
assertFalse(invokingCache.containsKey("1"));
}

@Test
public void testCacheManagementBean()
throws Exception
Expand Down

0 comments on commit 3e452b5

Please sign in to comment.