org.springframework.data.keyvalue.riak.groovy.RiakOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.data.keyvalue.riak.groovy.RiakOperation.java

Source

/*
 * Copyright (c) 2010 by J. Brisbin <jon@jbrisbin.com>
 * Portions (c) 2010 by NPC International, Inc. or the
 * original author(s).
 *
 * 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.springframework.data.keyvalue.riak.groovy;

import groovy.lang.Closure;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.keyvalue.riak.DataStoreOperationException;
import org.springframework.data.keyvalue.riak.core.AsyncKeyValueStoreOperation;
import org.springframework.data.keyvalue.riak.core.AsyncRiakTemplate;
import org.springframework.data.keyvalue.riak.core.KeyValueStoreMetaData;
import org.springframework.data.keyvalue.riak.core.QosParameters;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author J. Brisbin <jon@jbrisbin.com>
 */
public class RiakOperation<T> implements Callable {

    static enum Type {
        SET, SETASBYTES, PUT, GET, GETASBYTES, GETASTYPE, CONTAINSKEY, DELETE, FOREACH
    }

    static String COMPLETED = "completed";
    static String FAILED = "failed";

    protected final Log log = LogFactory.getLog(getClass());

    protected AsyncRiakTemplate riak;
    protected Type type;
    protected String bucket;
    protected String key;
    protected T value;
    protected Class<?> requiredType = null;
    protected long timeout = -1L;
    protected QosParameters qosParameters;
    protected Map<String, List<GuardedClosure>> callbacks = new LinkedHashMap<String, List<GuardedClosure>>();
    protected ClosureInvokingCallback callbackInvoker = new ClosureInvokingCallback();

    public RiakOperation(AsyncRiakTemplate riak, Type type) {
        this.riak = riak;
        this.type = type;
    }

    public Type getType() {
        return type;
    }

    public Map<String, List<GuardedClosure>> getCallbacks() {
        return callbacks;
    }

    public QosParameters getQosParameters() {
        return qosParameters;
    }

    public void setQosParameters(QosParameters qosParameters) {
        this.qosParameters = qosParameters;
    }

    public String getBucket() {
        return bucket;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public Class<?> getRequiredType() {
        return requiredType;
    }

    public void setRequiredType(Class<?> requiredType) {
        this.requiredType = requiredType;
    }

    public long getTimeout() {
        return timeout;
    }

    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public void addHandler(String type, Closure handler, Closure guard) {
        List<GuardedClosure> guardedClosures = callbacks.get(type);
        if (null == guardedClosures) {
            guardedClosures = new ArrayList<GuardedClosure>();
            callbacks.put(type, guardedClosures);
        }
        guardedClosures.add(new GuardedClosure(handler, guard));
    }

    @SuppressWarnings({ "unchecked" })
    public Object call() throws Exception {
        Future<?> f = null;
        switch (type) {
        case GET:
            f = riak.get(bucket, key, callbackInvoker);
            break;
        case GETASBYTES:
            f = riak.getAsBytes(bucket, key, callbackInvoker);
            break;
        case GETASTYPE:
            f = riak.getAsType(bucket, key, requiredType, callbackInvoker);
            break;
        case PUT:
            f = riak.put(bucket, value, callbackInvoker);
            break;
        case SET:
            f = riak.set(bucket, key, value, callbackInvoker);
            break;
        case SETASBYTES:
            byte[] bytes;
            if (value instanceof byte[]) {
                bytes = (byte[]) value;
            } else {
                bytes = riak.getConversionService().convert(value, byte[].class);
            }
            f = riak.setAsBytes(bucket, key, bytes, callbackInvoker);
            break;
        case CONTAINSKEY:
            f = riak.containsKey(bucket, key, callbackInvoker);
            break;
        case DELETE:
            f = riak.delete(bucket, key, callbackInvoker);
            break;
        case FOREACH:
            f = riak.getBucketSchema(bucket, null, new AsyncKeyValueStoreOperation<Map<String, Object>, Object>() {
                public Object completed(KeyValueStoreMetaData meta, Map<String, Object> result) {
                    List<Object> results = new LinkedList<Object>();
                    List<String> keys = (List<String>) result.get("keys");
                    for (String key : keys) {
                        try {
                            Future<?> getFut = riak.get(bucket, key, callbackInvoker);
                            if (timeout > 0) {
                                Object o = getFut.get(timeout, TimeUnit.MILLISECONDS);
                                if (null != o) {
                                    results.add(o);
                                }
                            } else if (timeout < 0) {
                                Object o = getFut.get();
                                if (null != o) {
                                    results.add(o);
                                }
                            } else {
                                results.add(getFut);
                            }
                        } catch (InterruptedException e) {
                            throw new DataStoreOperationException(e.getMessage(), e);
                        } catch (ExecutionException e) {
                            throw new DataStoreOperationException(e.getMessage(), e);
                        } catch (TimeoutException e) {
                            throw new DataStoreOperationException(e.getMessage(), e);
                        }
                    }
                    return (results.size() > 0 ? results : null);
                }

                public Object failed(Throwable error) {
                    throw new RuntimeException(error);
                }
            });
            break;
        }

        if (null != f) {
            if (timeout > 0) {
                // Block until finished or timeout
                return f.get(timeout, TimeUnit.MILLISECONDS);
            } else if (timeout < 0) {
                // Block indefinitely
                return f.get();
            }
        }

        return f;
    }

    class GuardedClosure {

        private Closure delegate;
        private Closure guard;

        GuardedClosure(Closure delegate, Closure guard) {
            this.delegate = delegate;
            this.guard = guard;
        }

        public Closure getDelegate() {
            return delegate;
        }

        public Closure getGuard() {
            return guard;
        }

    }

    class ClosureInvokingCallback implements AsyncKeyValueStoreOperation {

        public Object completed(KeyValueStoreMetaData meta, Object result) {
            if (!callbacks.containsKey(COMPLETED)) {
                return new Object[] { result, meta };
            }
            for (GuardedClosure cl : callbacks.get(COMPLETED)) {
                boolean execute = true;

                Closure guardExpr = cl.getGuard();
                if (null != guardExpr) {
                    int noOfParams = guardExpr.getParameterTypes().length;
                    Object guardResult;
                    if (noOfParams == 2) {
                        guardResult = guardExpr.call(new Object[] { result, meta });
                    } else {
                        guardResult = guardExpr.call(result);
                    }
                    if (null != guardResult) {
                        if (guardResult instanceof Boolean) {
                            execute = (Boolean) guardResult;
                        } else {
                            execute = true;
                        }
                    }
                }

                if (execute) {
                    Closure callback = cl.getDelegate();
                    if (callback.getParameterTypes().length == 2) {
                        return callback.call(new Object[] { result, meta });
                    } else {
                        return callback.call(result);
                    }
                }
            }
            return null;
        }

        public Object failed(Throwable error) {
            if (!callbacks.containsKey(FAILED)) {
                throw new RuntimeException(error);
            }
            for (GuardedClosure cl : callbacks.get(FAILED)) {
                boolean execute = true;
                Closure guardExpr = cl.getGuard();
                if (null != guardExpr) {
                    Object guardResult = guardExpr.call(error);
                    if (null != guardResult) {
                        if (guardResult instanceof Boolean) {
                            execute = (Boolean) guardResult;
                        } else {
                            execute = true;
                        }
                    }
                }

                if (execute) {
                    Closure callback = cl.getDelegate();
                    return callback.call(error);
                }
            }
            return null;
        }

    }

}