fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage.java Source code

Java tutorial

Introduction

Here is the source code for fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage.java

Source

/*
 * Data Hub Service (DHuS) - For Space data distribution.
 * Copyright (C) 2013,2014,2015 GAEL Systems
 *
 * This file is part of DHuS software sources.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package fr.gael.dhus.gwt.client.page.management;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimpleCheckBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;

import fr.gael.dhus.gwt.client.AccessDeniedRedirectionCallback;
import fr.gael.dhus.gwt.client.GWTClient;
import fr.gael.dhus.gwt.client.page.AbstractPage;
import fr.gael.dhus.gwt.services.CollectionServiceAsync;
import fr.gael.dhus.gwt.services.ProductServiceAsync;
import fr.gael.dhus.gwt.share.CollectionData;
import fr.gael.dhus.gwt.share.ProductData;
import fr.gael.dhus.gwt.share.RoleData;

public class ManagementCollectionsPage extends AbstractPage {
    private static CollectionServiceAsync collectionService = CollectionServiceAsync.Util.getInstance();
    private static ProductServiceAsync productService = ProductServiceAsync.Util.getInstance();

    private static CollectionData selectedCollection;
    private static List<ProductData> displayedProducts = new ArrayList<ProductData>();
    private static HashMap<Long, CollectionData> displayedCollections = new HashMap<Long, CollectionData>();
    private static CollectionData root;

    private static TextBox name;
    private static TextArea description;
    private static TextBox parent;
    private static RootPanel createButton;
    private static RootPanel createSubButton;
    private static RootPanel resetButton;
    private static RootPanel saveButton;
    private static RootPanel updateButton;
    private static RootPanel deleteButton;
    private static RootPanel cancelButton;
    private static SimpleCheckBox productsCheckAll;

    private static boolean productsCheckAllDisabled = false;

    private static State state;

    public ManagementCollectionsPage() {
        // name is automatically prefixed in JS by "management_"
        super.name = "Collections";
        super.roles = Arrays.asList(RoleData.DATA_MANAGER);
    }

    @Override
    public native JavaScriptObject getJSInitFunction()
    /*-{
       return function() {
     @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::init()();
       }
    }-*/;

    @Override
    public native JavaScriptObject getJSRefreshFunction()
    /*-{
       return function() {      
     @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::refresh()();
       }
    }-*/;

    @Override
    public void load() {
        // This page can only be loaded from Management Page
    }

    private static native void refreshProducts()
    /*-{
        $wnd.coll_refreshProducts();
    }-*/;

    private static native void refreshCollections()
    /*-{
        $wnd.coll_refreshCollections();
    }-*/;

    private static native void deselectCollection()
    /*-{
        $wnd.coll_deselectCollection();
    }-*/;

    private static native void hideCollectionsCustomValidity()
    /*-{
        $wnd.coll_hideCollectionsCustomValidity();
    }-*/;

    private static native void setCollectionsTableEnabled(boolean enabled)
    /*-{
        $wnd.coll_setCollectionsTableEnabled(enabled);
    }-*/;

    private static native void setProductsTableEnabled(boolean enabled)
    /*-{
        $wnd.coll_setProductsTableEnabled(enabled);
    }-*/;

    private static native void saveScrollPosition()
    /*-{
        $wnd.coll_saveScrollPosition();
    }-*/;

    private static native void resetScrollPosition()
    /*-{
        $wnd.coll_resetScrollPosition();
    }-*/;

    private static native void showCollectionManagement()
    /*-{
       $wnd.showCollectionManagement(
     function ( sSource, aoData, fnCallback, oSettings ) {
        @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::getProducts(*)
           (oSettings._iDisplayStart, oSettings._iDisplayLength, 
           oSettings.oPreviousSearch.sSearch, fnCallback)},
     function ( sSource, aoData, fnCallback, oSettings ) {            
        @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::getCollections(*)
           (fnCallback)},
     function (data) {
        if (data == null) {
           @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::setNothingState(*)()
        } else {
           @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::edit(*)(data[0].id)
        }},
     function (authority) {
           @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::checkProduct(*)(authority)
        },
     function () {
         @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::checkAllProducts(*)()
        },
     function (event, id) {
         if (event.stopPropagation) {
             event.stopPropagation();   // W3C model
         } else {
             event.cancelBubble = true; // IE model
         }
         @fr.gael.dhus.gwt.client.page.management.ManagementCollectionsPage::openCollection(*)(id)
        }
     );
    }-*/;

    @Override
    public void refreshMe() {
        refresh();
    }

    private static void refresh() {
        refreshCollections();
        refreshProducts();
        setNothingState();
    }

    private static void init() {
        showCollectionManagement();

        name = TextBox.wrap(RootPanel.get("managementCollection_name").getElement());
        description = TextArea.wrap(RootPanel.get("managementCollection_description").getElement());
        parent = TextBox.wrap(RootPanel.get("managementCollection_parent").getElement());
        createButton = RootPanel.get("managementCollection_buttonCreate");
        createSubButton = RootPanel.get("managementCollection_buttonCreateSub");
        resetButton = RootPanel.get("managementCollection_buttonReset");
        saveButton = RootPanel.get("managementCollection_buttonSave");
        updateButton = RootPanel.get("managementCollection_buttonUpdate");
        deleteButton = RootPanel.get("managementCollection_buttonDelete");
        cancelButton = RootPanel.get("managementCollection_buttonCancel");

        createButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (createButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                deselect();
                CollectionData parent = selectedCollection;
                selectedCollection = new CollectionData();
                selectedCollection.setParent(parent);
                setState(State.CREATE, true);
            }
        }, ClickEvent.getType());
        createSubButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (createSubButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                CollectionData parent = selectedCollection;
                selectedCollection = new CollectionData();
                selectedCollection.setParent(parent);
                setState(State.CREATESUB, true);
            }
        }, ClickEvent.getType());
        resetButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (resetButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                setState(state, true);
            }
        }, ClickEvent.getType());
        saveButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (saveButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                save(true);
            }
        }, ClickEvent.getType());
        updateButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (updateButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                save(false);
            }
        }, ClickEvent.getType());
        deleteButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (deleteButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                Long selectedId = selectedCollection.getId();
                List<CollectionData> selectedDisplayedChildren = selectedCollection.getDisplayedChildren();
                disableAll();
                displayedCollections.remove(selectedId);
                if (selectedDisplayedChildren != null && selectedDisplayedChildren.size() > 0) {
                    removeFromDisplayedCollections(selectedDisplayedChildren);
                }

                collectionService.deleteCollection(selectedId, new AccessDeniedRedirectionCallback<Void>() {

                    @Override
                    public void _onFailure(Throwable caught) {
                        Window.alert("Cannot delete collection.\n" + caught.getMessage());
                        setNothingState();
                        refreshCollections();
                    }

                    @Override
                    public void onSuccess(Void result) {
                        setNothingState();
                        refreshCollections();
                    }
                });
            }
        }, ClickEvent.getType());
        cancelButton.addDomHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (cancelButton.getElement().getClassName().contains("disabled")) {
                    return;
                }
                setNothingState();
            }
        }, ClickEvent.getType());

        setNothingState();
    }

    private static void removeFromDisplayedCollections(List<CollectionData> collections) {
        for (CollectionData col : collections) {
            displayedCollections.remove(col.getId());
            if (col.getDisplayedChildren() != null && col.getDisplayedChildren().size() > 0) {
                removeFromDisplayedCollections(col.getDisplayedChildren());
            }
        }
    }

    private static void deselect() {
        selectedCollection = null;
        productsCheckAll.setValue(false);
        resetScrollPosition();
        deselectCollection();
    }

    private static void setNothingState() {
        boolean deselect = selectedCollection != null;
        if (deselect && state != State.CREATESUB && state != State.CREATE) {
            deselect();
            setState(State.NOTHING, true);
        } else if (state == State.CREATE) {
            selectedCollection = null;
            setState(State.NOTHING, true);
        } else {
            setState(State.NOTHING, true);
        }
    }

    private static void edit(final int collectionId) {
        DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "wait");

        collectionService.getProductIds(new Long(collectionId), new AccessDeniedRedirectionCallback<List<Long>>() {

            @Override
            public void _onFailure(Throwable caught) {
                Window.alert("Cannot load products of selected collection.\n" + caught.getMessage());
                setNothingState();
            }

            @Override
            public void onSuccess(final List<Long> productIds) {
                selectedCollection = displayedCollections.get(new Long(collectionId)).copy();
                selectedCollection.setProductIds(productIds);

                resetScrollPosition();
                setState(State.EDIT, true);

                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
            }
        });
    }

    private static void save(final boolean create) {
        CollectionData toSave = selectedCollection != null ? selectedCollection.copy() : new CollectionData();
        toSave.setName(name.getValue());
        toSave.setDescription(description.getValue());

        if (toSave.getName() == null || toSave.getName().trim().isEmpty()) {
            Window.alert("At least one required field (*) is missing.");
            return;
        }

        disableAll();

        AccessDeniedRedirectionCallback<Void> callback = new AccessDeniedRedirectionCallback<Void>() {
            @Override
            public void _onFailure(Throwable caught) {
                Window.alert("Cannot save collection.\n" + caught.getMessage());
                setState(create ? State.CREATE : State.EDIT, false);
            }

            @Override
            public void onSuccess(Void result) {
                setNothingState();
                refreshCollections();
            }
        };
        if (create) {
            collectionService.createCollection(toSave, callback);
        } else {
            collectionService.updateCollection(toSave, callback);
        }
    }

    private static void setState(State s, boolean setValue) {
        state = s;
        boolean updatable = state == State.EDIT && selectedCollection != null
                && selectedCollection.getName() != null && !selectedCollection.getName().trim().isEmpty();

        // Trees & Datagrids
        setCollectionsTableEnabled(state == State.NOTHING || state == State.EDIT);
        setProductsTableEnabled(state == State.EDIT || state == State.CREATE || state == State.CREATESUB);

        // Enable Buttons
        cancelButton.getElement().setClassName("button_black");
        createButton.getElement().setClassName("button_black");
        createSubButton.getElement().setClassName("button_black");
        deleteButton.getElement().setClassName("button_black");
        resetButton.getElement().setClassName("button_black");
        saveButton.getElement().setClassName("button_disabled");
        updateButton.getElement().setClassName(updatable ? "button_black" : "button_disabled");

        // Buttons Visibility
        cancelButton.setVisible(state == State.EDIT || state == State.CREATE || state == State.CREATESUB);
        createButton.setVisible(state == State.NOTHING || state == State.EDIT);
        createSubButton.setVisible(state == State.EDIT);
        deleteButton.setVisible(state == State.EDIT);
        resetButton.setVisible(state == State.CREATE || state == State.CREATESUB);
        saveButton.setVisible(state == State.CREATE || state == State.CREATESUB);
        updateButton.setVisible(state == State.EDIT);

        // Enable Fields
        name.setEnabled(state == State.EDIT || state == State.CREATE || state == State.CREATESUB);
        description.setEnabled(state == State.EDIT || state == State.CREATE || state == State.CREATESUB);
        parent.setEnabled(false);
        productsCheckAllDisabled = false;

        // Fields Value
        if (setValue) {
            name.setValue((state == State.EDIT && selectedCollection != null) ? selectedCollection.getName() : "");
            description.setValue(
                    (state == State.EDIT && selectedCollection != null) ? selectedCollection.getDescription() : "");
            parent.setValue(((state == State.EDIT || state == State.CREATE || state == State.CREATESUB)
                    && selectedCollection != null && selectedCollection.getParent() != null)
                            ? selectedCollection.getParent().getName()
                            : "");

            refreshProducts();
        }

        // hack to enable Save button if needed by revalidating fields.
        name.setFocus(true);
        name.setFocus(false);
        hideCollectionsCustomValidity();
        name.setFocus(state == State.CREATE || state == State.CREATESUB);
    }

    private static void disableAll() {
        selectedCollection = null;
        setCollectionsTableEnabled(false);
        setProductsTableEnabled(false);
        productsCheckAll.setEnabled(false);
        productsCheckAllDisabled = true;

        saveButton.getElement().setClassName("button_disabled");
        resetButton.getElement().setClassName("button_disabled");
        createButton.getElement().setClassName("button_disabled");
        createSubButton.getElement().setClassName("button_disabled");
        updateButton.getElement().setClassName("button_disabled");
        deleteButton.getElement().setClassName("button_disabled");
        cancelButton.getElement().setClassName("button_disabled");

        name.setEnabled(false);
        parent.setEnabled(false);
        description.setEnabled(false);
    }

    private static void openCollection(int id) {
        DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "wait");
        deselect();
        setState(State.NOTHING, true);
        CollectionData parent = displayedCollections.get(new Long(id));
        if (parent == null) {
            Window.alert("Error while opening collection #" + id);
            return;
        }
        if (parent.getDisplayedChildren() != null && parent.getDisplayedChildren().size() > 0) {
            removeFromDisplayedCollections(parent.getDisplayedChildren());
            parent.getDisplayedChildren().clear();
            displayedCollections.put(parent.getId(), parent);
            refreshCollections();
        } else {
            DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "wait");
            requestCollections(parent, new AccessDeniedRedirectionCallback<Void>() {
                @Override
                public void _onFailure(Throwable caught) {
                    DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
                }

                @Override
                public void onSuccess(Void result) {
                    refreshCollections();
                    DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
                }
            });
        }
    }

    private static void getCollections(final JavaScriptObject function) {
        DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "wait");

        GWTClient.callback(function,
                JsonUtils.safeEval("{\"aaData\": [],\"iTotalRecords\" : 0, \"iTotalDisplayRecords\" : 0}"));

        if (root == null) {
            root = new CollectionData();
            root.setId(null);
            root.setDeep(-1);
        }
        toRefresh = new ArrayList<Long>();
        for (CollectionData c : displayedCollections.values()) {
            if (c.getDisplayedChildren() != null && c.getDisplayedChildren().size() > 0) {
                toRefresh.add(c.getId());
            }
        }
        displayedCollections.clear();
        requestCollections(root, new AccessDeniedRedirectionCallback<Void>() {
            @Override
            public void _onFailure(Throwable caught) {
                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
            }

            @Override
            public void onSuccess(Void result) {
                String json = "{\"aaData\": [";
                json += computeJSON(root);
                boolean children = false;
                if (root.getDisplayedChildren() != null && root.getDisplayedChildren().size() > 0) {
                    json = json.substring(0, json.length() - 1);
                    children = true;
                }
                json += "],\"iTotalRecords\" : " + (children ? 1 : 0) + ", \"iTotalDisplayRecords\" : "
                        + (children ? 1 : 0) + "}";
                GWTClient.callback(function, JsonUtils.safeEval(json));
                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
            }
        });
    }

    private static void requestCollections(final CollectionData parent,
            final AccessDeniedRedirectionCallback<Void> callback) {
        collectionService.getSubCollections(parent, new AccessDeniedRedirectionCallback<List<CollectionData>>() {
            @Override
            public void _onFailure(Throwable caught) {
                callback.onFailure(caught);
            }

            @Override
            public void onSuccess(List<CollectionData> collections) {
                parent.setDisplayedChildren(collections);
                displayedCollections.put(parent.getId(), parent);
                for (CollectionData collection : collections) {
                    // if already added, don't replace it
                    if (!displayedCollections.containsKey(collection.getId())) {
                        displayedCollections.put(collection.getId(), collection);
                    }
                }
                refreshEnded(parent, callback);
            }
        });
    }

    private static ArrayList<Long> toRefresh;

    private static void refreshEnded(CollectionData refreshed, AccessDeniedRedirectionCallback<Void> callback) {
        toRefresh.remove(refreshed.getId());
        if (toRefresh.size() == 0) {
            callback.onSuccess(null);
        } else {
            CollectionData parent = displayedCollections.get(toRefresh.get(0));
            requestCollections(parent, callback);
        }
    }

    private static String computeJSON(CollectionData collection) {
        String json = "";
        if (collection == null || collection.getDisplayedChildren() == null) {
            return "";
        }
        for (CollectionData col : collection.getDisplayedChildren()) {
            CollectionData c = displayedCollections.get(col.getId());
            json += "[{\"name\":\"" + c.getName() + "\", \"id\":" + c.getId() + ", \"deep\":" + c.getDeep()
                    + ", \"hasChildren\":" + c.hasChildren() + ", \"open\":"
                    + (c.getDisplayedChildren() != null && c.getDisplayedChildren().size() > 0) + "}],";
            if (c.hasChildren()) {
                json += computeJSON(c);
            }
        }
        return json;
    }

    private static void checkProduct(int pId) {
        Long productId = new Long(pId);
        if (selectedCollection != null && selectedCollection.contains(productId)) {
            selectedCollection.removeProduct(productId);
        } else {
            selectedCollection.addProduct(productId);
        }
        saveScrollPosition();
        refreshProducts();
    }

    private static void checkAllProducts() {
        Long[] pids = new Long[displayedProducts.size()];
        int i = 0;
        for (ProductData product : displayedProducts) {
            pids[i] = product.getId();
            i++;
        }

        if (productsCheckAll.getValue()) {
            selectedCollection.addProducts(pids);
        } else {
            selectedCollection.removeProducts(pids);
        }
        saveScrollPosition();
        refreshProducts();
    }

    private static void getProducts(final int start, final int length, final String search,
            final JavaScriptObject function) {
        DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "wait");
        final Long parentId = selectedCollection != null && selectedCollection.getParent() != null
                ? selectedCollection.getParent().getId()
                : null;

        GWTClient.callback(function,
                JsonUtils.safeEval("{\"aaData\": [],\"iTotalRecords\" : 0, \"iTotalDisplayRecords\" : 0}"));
        productService.count(search, parentId, new AccessDeniedRedirectionCallback<Integer>() {
            @Override
            public void _onFailure(Throwable caught) {
                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
                Window.alert("There was an error while counting products");
            }

            @Override
            public void onSuccess(final Integer total) {
                //selectedCollection.getParent ().getId ()
                productService.getProducts(start, length, search, parentId,
                        new AccessDeniedRedirectionCallback<List<ProductData>>() {
                            @Override
                            public void _onFailure(Throwable caught) {
                                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");
                                Window.alert("There was an error while searching for '" + search + "'");
                            }

                            @Override
                            public void onSuccess(List<ProductData> products) {
                                displayedProducts = products;
                                boolean allChecked = true;
                                String json = "{\"aaData\": [";
                                for (ProductData product : products) {
                                    boolean checked = (selectedCollection != null
                                            && selectedCollection.contains(product.getId()));
                                    allChecked = allChecked && checked;
                                    json += "[{\"checked\":" + checked + ", \"id\":\"" + product.getId()
                                            + "\" }, \"" + product.getIdentifier() + "\"],";
                                }
                                if (total > 0) {
                                    json = json.substring(0, json.length() - 1);
                                } else {
                                    allChecked = false;
                                    productsCheckAllDisabled = true;
                                }
                                json += "],\"iTotalRecords\" : " + total + ", \"iTotalDisplayRecords\" : " + total
                                        + "}";

                                GWTClient.callback(function, JsonUtils.safeEval(json));
                                DOM.setStyleAttribute(RootPanel.getBodyElement(), "cursor", "default");

                                productsCheckAll = SimpleCheckBox
                                        .wrap(RootPanel.get("productsCheckAll").getElement());
                                productsCheckAll.setValue(allChecked);
                                productsCheckAll.setEnabled(!productsCheckAllDisabled && (state == State.EDIT
                                        || state == State.CREATE || state == State.CREATESUB));
                            }
                        });
            }
        });
    }

    private enum State {
        NOTHING, EDIT, CREATESUB, CREATE;
    }
}