n3phele.client.CacheManager.java Source code

Java tutorial

Introduction

Here is the source code for n3phele.client.CacheManager.java

Source

/**
 * @author Nigel Cook
 *
 * (C) Copyright 2010-2012. Nigel Cook. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Licensed under the terms described in LICENSE file that accompanied this code, (the "License"); you may not use this file
 * except in compliance with the License. 
 * 
 *  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 n3phele.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Timer;

import n3phele.client.model.Change;
import n3phele.client.model.ChangeGroup;
import n3phele.client.model.Cloud;
import n3phele.client.model.Collection;
import n3phele.client.model.Root;
import n3phele.client.presenter.helpers.AuthenticatedRequestFactory;

public class CacheManager {
    Map<String, List<Registration>> cache = new HashMap<String, List<Registration>>();
    EventBus eventBus;
    private long stamp = 0;
    private boolean gotClouds = false;
    private int backoff = 0;
    private int counter = 0;
    private Timer refreshTimer = null;
    // final public String ServiceAddress = "https://n3phele.appspot.com/resources/";
    final public String ServiceAddress = "https://n3phele-dev.appspot.com/resources/";
    // final public String ServiceAddress = "http://localhost:8888/resources/";   // uncomment for local access

    public CacheManager(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    public void start() {
        if (refreshTimer == null) {
            if (!gotClouds)
                refreshClouds();
            refreshTimer = new Timer() {
                public void run() {
                    if (AuthenticatedRequestFactory.isAuthenticated()) {
                        if (!gotClouds) {
                            refreshClouds();
                        }
                        int recentRequests = AuthenticatedRequestFactory.incrementalRequests();
                        counter += 1;
                        boolean expired = counter >= backoff;
                        if (recentRequests > 0) {
                            counter = 0;
                            backoff = 0;
                        } else if (expired) {
                            counter = 0;
                            if (backoff <= 0) {
                                backoff = 1;
                            } else {
                                backoff = backoff >= 32 ? 32 : backoff + 1;
                            }
                        }
                        GWT.log("recentRequests=" + recentRequests + " counter=" + counter + " backoff=" + backoff);
                        if (backoff <= 2 || expired) {
                            refresh();
                        }
                    }
                }
            };
            refreshTimer.scheduleRepeating(10000);
        }
    }

    public void refresh() {
        RequestBuilder builder = AuthenticatedRequestFactory.newCacheManagerRequest(RequestBuilder.GET,
                ServiceAddress + "?summary=false&changeOnly=true&since=" + stamp);
        if (builder == null)
            return;
        try {
            GWT.log("Sending request");
            @SuppressWarnings("unused")
            Request request = builder.sendRequest(null, new RequestCallback() {
                public void onError(Request request, Throwable exception) {
                    // displayError("Couldn't retrieve JSON "+exception.getMessage());
                }

                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        Root root = Root.parse(response.getText());
                        GWT.log(response.getText());
                        GWT.log(root.toString());
                        stamp = root.getStamp();
                        ChangeGroup changes = root.getChangeGroup();
                        if (changes != null) {
                            if (changes.getChange() != null) {
                                for (Change x : changes.getChange()) {
                                    List<Registration> item;
                                    item = cache.get(x.getUri());
                                    GWT.log("Got change URI " + x.getUri() + " item " + item);
                                    if (x.getUri().equals(cloudUrl)) {
                                        refreshClouds();
                                    }
                                    if (item != null) {
                                        fireAll(x.getUri(), item);
                                    }
                                }
                                if (changes.getChange().size() != 0) {
                                    backoff = 0;
                                }
                            }
                        } else {
                            for (Entry<String, List<Registration>> entry : cache.entrySet()) {
                                fireAll(entry.getKey(), entry.getValue());
                            }
                        }

                    } else {
                        // displayError("Couldn't retrieve JSON (" + response.getStatusText() + ")");
                    }
                }

            });
        } catch (RequestException e) {
            // displayError("Couldn't retrieve JSON "+e.getMessage());
        }
    }

    //   public void refreshProgressList() {
    //      List<Registration> item;
    //      final String progressURI = ServiceAddress + "progress";
    //      item = cache.get(progressURI);
    //      if (item != null) {
    //         fireAll(progressURI, item);
    //      }
    //   }

    private void fireAll(String key, List<Registration> l) {
        if (l != null) {
            for (Registration r : l) {
                GWT.log("Firing " + r.registrant + " " + key);
                eventBus.fireEvent(r.constructor.newInstance(key));
            }
        }
    }

    /**
     * Register a class of event to be sent when modifications to key occur.
     * 
     * @param key
     * @param registrant
     * @param event
     */
    public void register(String key, String registrant, EventConstructor constructor) {
        Registration registration = new Registration(registrant, constructor);
        List<Registration> l = cache.get(key);
        if (l == null) {
            l = new ArrayList<Registration>();
            cache.put(key, l);
        } else {
            for (int i = 0; i < l.size(); i++) {
                Registration r = l.get(i);
                if (r.registrant.equals(registration.registrant)) {
                    l.set(i, registration);
                    return;
                }
            }
        }
        l.add(registration);
    }

    public void unregister(String key, String registrant) {
        List<Registration> l = cache.get(key);
        if (l != null) {
            for (int i = 0; i < l.size(); i++) {
                Registration r = l.get(i);
                if (r.registrant.equals(registrant)) {
                    l.remove(i);
                    if (l.size() == 0) {
                        cache.remove(key);
                    }
                    return;
                }
            }
        }
    }

    public void unregisterAll(String registrant) {
        String[] keys = cache.keySet().toArray(new String[cache.keySet().size()]);
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            List<Registration> list = cache.get(key);
            if (list != null) {
                for (int l = 0; l < list.size(); l++) {
                    Registration r = list.get(l);
                    if (r.registrant.equals(registrant)) {
                        list.remove(l);
                        if (list.size() == 0) {
                            cache.remove(key);
                        }
                        break;
                    }
                }
            }
        }
    }

    public interface EventConstructor {
        public GwtEvent<?> newInstance(String key);
    }

    private static class Registration {
        public final EventConstructor constructor;
        public final String registrant;

        public Registration(String registrant, EventConstructor constructor) {
            this.constructor = constructor;
            this.registrant = registrant;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((constructor == null) ? 0 : constructor.hashCode());
            result = prime * result + ((registrant == null) ? 0 : registrant.hashCode());
            return result;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Registration other = (Registration) obj;
            if (constructor == null) {
                if (other.constructor != null)
                    return false;
            } else if (!constructor.equals(other.constructor))
                return false;
            if (registrant == null) {
                if (other.registrant != null)
                    return false;
            } else if (!registrant.equals(other.registrant))
                return false;
            return true;
        }
    }

    public void test(String username, String password, RequestCallback requestCallback) {

        // Send request to server and catch any errors.
        RequestBuilder builder = AuthenticatedRequestFactory.request(RequestBuilder.GET,
                ServiceAddress + "user/byName?id=" + URL.encodeQueryString(username), username, password);
        GWT.log("Sending authentication test request");
        Request request = null;
        try {
            request = builder.sendRequest(null, requestCallback);
        } catch (RequestException e) {
            requestCallback.onError(request, e);
        }

    }

    private final String cloudUrl = ServiceAddress + "cloud";
    private final List<Cloud> clouds = new ArrayList<Cloud>();

    public List<Cloud> getClouds() {
        return clouds;
    }

    protected void refreshClouds() {

        RequestBuilder builder = AuthenticatedRequestFactory.newCacheManagerRequest(RequestBuilder.GET, cloudUrl);
        try {
            builder.sendRequest(null, new RequestCallback() {
                public void onError(Request request, Throwable exception) {
                    GWT.log("Couldn't retrieve JSON " + exception.getMessage());
                }

                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        Collection<Cloud> p = Cloud.asCollection(response.getText());
                        clouds.clear();
                        clouds.addAll(p.getElements());
                        GWT.log("Got " + clouds.size() + " clouds.");
                        gotClouds = true;
                        eventBus.fireEvent(new CloudListUpdate(cloudUrl));
                    } else {
                        GWT.log("Couldn't retrieve JSON (" + response.getStatusText() + ")");
                    }
                }
            });
            gotClouds = false;
        } catch (RequestException e) {
            GWT.log("Couldn't retrieve JSON " + e.getMessage());
        }
    }

    public CacheManager.EventConstructor cloudListConstructor = new CacheManager.EventConstructor() {
        @Override
        public CloudListUpdate newInstance(String key) {
            return new CloudListUpdate(key);
        }
    };

    public interface CloudListUpdateEventHandler extends EventHandler {
        void onMessageReceived(CloudListUpdate event);
    }

    public static class CloudListUpdate extends GwtEvent<CloudListUpdateEventHandler> {
        public static Type<CloudListUpdateEventHandler> TYPE = new Type<CloudListUpdateEventHandler>();
        private final String key;

        public CloudListUpdate(String key) {
            this.key = key;
        }

        @Override
        public com.google.gwt.event.shared.GwtEvent.Type<CloudListUpdateEventHandler> getAssociatedType() {
            return TYPE;
        }

        @Override
        protected void dispatch(CloudListUpdateEventHandler handler) {
            handler.onMessageReceived(this);
        }

        public String getKey() {
            return this.key;
        }
    }

}