org.krypsis.gwt.store.client.javascript.JsStore.java Source code

Java tutorial

Introduction

Here is the source code for org.krypsis.gwt.store.client.javascript.JsStore.java

Source

/*
 * Copyright (c) 2010 Sergej Soller (kontakt@5ws.de)
 *
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 */
package org.krypsis.gwt.store.client.javascript;

import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import org.krypsis.gwt.store.client.*;
import org.krypsis.gwt.store.client.event.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class JsStore<E extends JsStorable> implements Store<E> {
    private static final String SEQUENCE = "$SEQ";
    private final StoreBackend backend;
    private final StoreKey key;
    private final HandlerManager eventBus;

    public JsStore(String name, StoreBackend backend) {
        this(name, backend, null);
    }

    public JsStore(String name, StoreBackend backend, HandlerManager eventBus) {
        this.key = new StoreKey(name);
        this.backend = backend;
        this.eventBus = eventBus;
    }

    public String save(E instance) {
        return save(instance, true);
    }

    public String save(E instance, boolean fireEvents) {
        try {
            final JSONObject object = loadObject();

            boolean update = true;
            if (instance.getId() == null) {
                final String id = nextId();
                instance.setId(id);
                update = false;
            }

            if (update) {
                fireEvent(new BeforeUpdatedEvent<E>(this, instance), fireEvents);
            } else {
                fireEvent(new BeforeInsertedEvent<E>(this, instance), fireEvents);
            }
            fireEvent(new BeforeSavedEvent<E>(this, instance), fireEvents);

            object.put(instance.getId(), new JSONObject(instance));
            saveObject(object);

            if (update) {
                fireEvent(new AfterUpdatedEvent<E>(this, instance), fireEvents);
            } else {
                fireEvent(new AfterInsertedEvent<E>(this, instance), fireEvents);
            }
            fireEvent(new AfterSavedEvent<E>(this, instance), fireEvents);

            return instance.getId();
        } catch (Exception e) {
            throw new StoreException("Could not add instance into store", e);
        }
    }

    public E get(String id) {
        try {
            final JSONObject object = loadObject();
            if (!object.containsKey(id)) {
                return null;
            }
            //noinspection unchecked
            return (E) object.get(id).isObject().getJavaScriptObject();
        } catch (Exception e) {
            throw new StoreException("Could not load instance. Key = " + key + ", id = " + id, e);
        }
    }

    public List<E> all() {
        try {
            final JSONObject object = loadObject();
            return all(object.keySet());
        } catch (Exception e) {
            throw new StoreException("Could not return instances");
        }
    }

    public List<E> all(Collection<String> ids) {
        try {
            final List<E> result = new ArrayList<E>();
            for (String key : ids) {
                final E instance = get(key);
                if (instance == null) {
                    continue;
                }

                result.add(instance);
            }
            return result;
        } catch (Exception e) {
            throw new StoreException("Could not load the instance with ids = " + ids, e);
        }
    }

    public int size() {
        return loadObject().size();
    }

    public E findFirst(Matcher<E> matcher) {
        final JSONObject object = loadObject();
        for (String key : object.keySet()) {
            final E instance = get(key);
            if (matcher.match(instance)) {
                return instance;
            }
        }
        return null;
    }

    public <T> T findFirst(PropertyMatcher<E, T> matcher) {
        final JSONObject object = loadObject();
        for (String key : object.keySet()) {
            final E instance = get(key);
            if (matcher.match(instance)) {
                return matcher.getValueOf(instance);
            }
        }
        return null;
    }

    public List<E> findAll(Matcher<E> matcher) {
        final List<E> result = new ArrayList<E>();
        for (E e : all()) {
            if (matcher.match(e)) {
                result.add(e);
            }
        }
        return result;
    }

    public <T> List<T> findAll(PropertyMatcher<E, T> matcher) {
        final List<T> result = new ArrayList<T>();
        for (E e : all()) {
            if (matcher.match(e)) {
                result.add(matcher.getValueOf(e));
            }
        }
        return result;
    }

    public void delete(E instance) {
        delete(instance, true);
    }

    public void delete(E instance, boolean fireEvents) {
        final String id = instance.getId();
        try {
            final JSONObject object = loadObject();
            if (!object.containsKey(id)) {
                throw new StoreException("Could not delete instance with id = " + id + ". It does not exists");
            }
            fireEvent(new BeforeDeletedEvent<E>(this, instance), fireEvents);
            object.put(id, null);
            saveObject(object);
            fireEvent(new AfterDeletedEvent<E>(this, instance), fireEvents);
        } catch (Exception e) {
            throw new StoreException("Could not delete instance with id = " + id, e);
        }
    }

    public void delete(String id) {
        delete(get(id));
    }

    public void deleteAll(List<String> ids) {
        deleteAll(ids, true);
    }

    @SuppressWarnings({ "unchecked" })
    public void deleteAll(List<String> ids, boolean fireEvents) {
        final JSONObject object = loadObject();
        final List<E> deleted = new ArrayList<E>();
        for (String id : ids) {
            if (!object.containsKey(id)) {
                continue;
            }
            final E e = (E) object.get(id).isObject().getJavaScriptObject();
            deleted.add(e);
            fireEvent(new BeforeDeletedEvent<E>(this, e), fireEvents);
            object.put(id, null);
        }
        saveObject(object);

        for (E e : deleted) {
            fireEvent(new AfterDeletedEvent<E>(this, e), fireEvents);
        }
    }

    public void deleteAll() {
        deleteAll(true);
    }

    public void deleteAll(boolean fireEvents) {
        fireEvent(new BeforeClearedEvent(this), fireEvents);
        backend.remove(getKey().getName());
        fireEvent(new AfterClearedEvent(this), fireEvents);
    }

    /* GETTER, SETTER and private methods */

    public StoreKey getKey() {
        return key;
    }

    public StoreBackend getBackend() {
        return backend;
    }

    /**
     * Loads the object that contains all instances.
     *
     * @return The JSON Object that contains all saved instance
     */
    private JSONObject loadObject() {
        final String data = backend.get(key.getName());

        JSONObject object;
        if (data == null) {
            object = new JSONObject();
        } else {
            final JSONValue jsonValue = JSONParser.parse(data);
            object = jsonValue.isObject();
        }

        if (object == null) {
            throw new IllegalArgumentException("Database is broken. Array could not been deserialized");
        }

        return object;
    }

    /**
     * Loads the sequence from the backend or creates a new one.
     *
     * @return The sequence
     */
    private JSONString loadSequence() {
        final String data = backend.get(key.getName() + SEQUENCE);

        JSONString jsonString;
        if (data == null) {
            jsonString = new JSONString("1");
        } else {
            final JSONValue jsonValue = JSONParser.parse(data);
            jsonString = jsonValue.isString();
        }

        if (jsonString == null) {
            throw new IllegalArgumentException("Database is broken. Array could not been deserialized");
        }

        return jsonString;
    }

    /**
     * Saves the sequence
     *
     * @param sequence The sequence for the instances of this store
     */
    public void saveSequence(JSONString sequence) {
        backend.put(key.getName() + SEQUENCE, sequence.toString());
    }

    /**
     * Saves the object to the backend
     *
     * @param object The object to save
     */
    private void saveObject(JSONObject object) {
        backend.put(key.getName(), object.toString());
    }

    /**
     * @return The next id for a new instance
     */
    private String nextId() {
        final JSONString jsonString = loadSequence();
        final String id = jsonString.stringValue();
        saveSequence(new JSONString(String.valueOf(Integer.parseInt(id) + 1)));
        return id;
    }

    /**
     * Fires a store event, if event bus is given. Otherwise
     * nothing happens
     *
     * @param event The event to dispatch
     * @param reallyFire Should the event really be fired?
     */
    private void fireEvent(GwtEvent<?> event, boolean reallyFire) {
        if (eventBus != null && event != null && reallyFire) {
            eventBus.fireEvent(event);
        }
    }
}