org.roda.wui.client.browse.BrowseRepresentation.java Source code

Java tutorial

Introduction

Here is the source code for org.roda.wui.client.browse.BrowseRepresentation.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE file at the root of the source
 * tree and available online at
 *
 * https://github.com/keeps/roda
 */
/**
 * 
 */
package org.roda.wui.client.browse;

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

import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.v2.common.Pair;
import org.roda.core.data.v2.index.facet.Facets;
import org.roda.core.data.v2.index.filter.EmptyKeyFilterParameter;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.filter.SimpleFilterParameter;
import org.roda.core.data.v2.ip.AIPState;
import org.roda.core.data.v2.ip.IndexedFile;
import org.roda.core.data.v2.ip.IndexedRepresentation;
import org.roda.wui.client.browse.bundle.BrowseRepresentationBundle;
import org.roda.wui.client.browse.bundle.DescriptiveMetadataViewBundle;
import org.roda.wui.client.common.LastSelectedItemsSingleton;
import org.roda.wui.client.common.UserLogin;
import org.roda.wui.client.common.actions.Actionable;
import org.roda.wui.client.common.actions.DisseminationActions;
import org.roda.wui.client.common.actions.FileActions;
import org.roda.wui.client.common.actions.RepresentationActions;
import org.roda.wui.client.common.lists.DIPList;
import org.roda.wui.client.common.lists.SearchFileList;
import org.roda.wui.client.common.lists.pagination.ListSelectionUtils;
import org.roda.wui.client.common.search.SearchFilters;
import org.roda.wui.client.common.search.SearchPanel;
import org.roda.wui.client.common.utils.AsyncCallbackUtils;
import org.roda.wui.client.common.utils.HtmlSnippetUtils;
import org.roda.wui.client.common.utils.JavascriptUtils;
import org.roda.wui.client.main.BreadcrumbPanel;
import org.roda.wui.client.main.BreadcrumbUtils;
import org.roda.wui.common.client.HistoryResolver;
import org.roda.wui.common.client.tools.DescriptionLevelUtils;
import org.roda.wui.common.client.tools.HistoryUtils;
import org.roda.wui.common.client.tools.ListUtils;
import org.roda.wui.common.client.tools.RestErrorOverlayType;
import org.roda.wui.common.client.tools.RestUtils;
import org.roda.wui.common.client.widgets.Toast;
import org.roda.wui.common.client.widgets.wcag.WCAGUtilities;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
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.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.Widget;

import config.i18n.client.ClientMessages;

/**
 * @author Luis Faria
 * 
 */
public class BrowseRepresentation extends Composite {
    private static final MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
    private static final ClientMessages messages = (ClientMessages) GWT.create(ClientMessages.class);

    public static final HistoryResolver RESOLVER = new HistoryResolver() {

        @Override
        public void resolve(List<String> historyTokens, final AsyncCallback<Widget> callback) {
            if (historyTokens.size() == 2) {
                final String historyAipId = historyTokens.get(0);
                final String histortyRepresentationId = historyTokens.get(1);

                BrowserService.Util.getInstance().retrieveBrowseRepresentationBundle(historyAipId,
                        histortyRepresentationId, LocaleInfo.getCurrentLocale().getLocaleName(),
                        representationFields, new AsyncCallback<BrowseRepresentationBundle>() {

                            @Override
                            public void onFailure(Throwable caught) {
                                Toast.showError(caught.getClass().getSimpleName(), caught.getMessage());
                                errorRedirect(callback);
                            }

                            @Override
                            public void onSuccess(final BrowseRepresentationBundle representationBundle) {
                                callback.onSuccess(new BrowseRepresentation(representationBundle));
                            }
                        });

            } else {
                errorRedirect(callback);
            }
        }

        @Override
        public void isCurrentUserPermitted(AsyncCallback<Boolean> callback) {
            UserLogin.getInstance().checkRole(BrowseAIP.RESOLVER, callback);
        }

        @Override
        public List<String> getHistoryPath() {
            return ListUtils.concat(BrowseAIP.RESOLVER.getHistoryPath(), getHistoryToken());
        }

        @Override
        public String getHistoryToken() {
            return "representation";
        }

        private void errorRedirect(AsyncCallback<Widget> callback) {
            HistoryUtils.newHistory(BrowseAIP.RESOLVER);
            callback.onSuccess(null);
        }
    };

    interface MyUiBinder extends UiBinder<Widget, BrowseRepresentation> {
    }

    private List<HandlerRegistration> handlers;
    private IndexedRepresentation representation;
    private String aipId;
    private String repId;
    private String repUUID;

    private static final List<String> representationFields = new ArrayList<>(
            Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.REPRESENTATION_AIP_ID,
                    RodaConstants.REPRESENTATION_ID, RodaConstants.REPRESENTATION_TYPE));

    private static final String ALL_FILTER = SearchFilters.allFilter(IndexedFile.class.getName());

    // Focus
    @UiField
    FocusPanel keyboardFocus;

    // STATUS

    @UiField
    HTML aipState;

    // IDENTIFICATION

    @UiField
    SimplePanel representationIcon;

    @UiField
    HTML representationType;

    @UiField
    Label representationId;

    @UiField
    BreadcrumbPanel breadcrumb;

    // DESCRIPTIVE METADATA

    @UiField
    TabPanel itemMetadata;

    @UiField
    Button newDescriptiveMetadata;

    // FILES

    @UiField(provided = true)
    SearchPanel filesSearch;

    @UiField(provided = true)
    SearchFileList filesList;

    // DISSEMINATIONS

    @UiField
    Label disseminationsTitle;

    @UiField(provided = true)
    SearchPanel disseminationsSearch;

    @UiField(provided = true)
    DIPList disseminationsList;

    // SIDEBAR

    @UiField
    SimplePanel actionsSidebar;

    @UiField
    FlowPanel searchSection;

    @UiField
    Button searchPrevious, searchNext;

    public BrowseRepresentation(BrowseRepresentationBundle bundle) {
        this.representation = bundle.getRepresentation();

        this.aipId = representation.getAipId();
        this.repId = representation.getId();
        this.repUUID = representation.getUUID();

        handlers = new ArrayList<>();
        String summary = messages.representationListOfFiles();

        AIPState state = bundle.getAip().getState();
        boolean justActive = AIPState.ACTIVE.equals(state);
        boolean selectable = true;
        boolean showFilesPath = false;

        // FILES

        Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.FILE_REPRESENTATION_UUID, repUUID),
                new EmptyKeyFilterParameter(RodaConstants.FILE_PARENT_UUID));

        filesList = new SearchFileList(filter, justActive, Facets.NONE, summary, selectable, showFilesPath);
        LastSelectedItemsSingleton.getInstance().setSelectedJustActive(justActive);
        filesList.setActionable(FileActions.get(aipId, repId));

        ListSelectionUtils.bindBrowseOpener(filesList);

        filesSearch = new SearchPanel(filter, ALL_FILTER, true, messages.searchPlaceHolder(), false, false, true);
        filesSearch.setList(filesList);

        // DISSEMINATIONS
        disseminationsList = new DIPList(Filter.NULL, Facets.NONE, messages.listOfDisseminations(), true);
        disseminationsList.setActionable(DisseminationActions.get());
        ListSelectionUtils.bindBrowseOpener(disseminationsList);

        disseminationsSearch = new SearchPanel(Filter.NULL, RodaConstants.DIP_SEARCH, true,
                messages.searchPlaceHolder(), false, false, true);
        disseminationsSearch.setList(disseminationsList);

        // INIT
        initWidget(uiBinder.createAndBindUi(this));

        // STATUS
        aipState.setHTML(HtmlSnippetUtils.getAIPStateHTML(state));
        aipState.setVisible(!justActive);

        // IDENTIFICATION

        HTMLPanel representationIconHtmlPanel = new HTMLPanel(
                DescriptionLevelUtils.getRepresentationTypeIcon(representation.getType(), false));
        representationIconHtmlPanel.addStyleName("browseItemIcon-other");
        representationIcon.setWidget(representationIconHtmlPanel);

        String type = representation.getType() != null ? representation.getType() : representation.getId();
        representationType.setHTML(HtmlSnippetUtils.getRepresentationTypeHTML(type, representation.isOriginal()));
        representationId.setText(representation.getId());

        breadcrumb.updatePath(BreadcrumbUtils.getRepresentationBreadcrumbs(bundle));
        breadcrumb.setVisible(true);

        // DESCRIPTIVE METADATA

        final List<Pair<String, HTML>> descriptiveMetadataContainers = new ArrayList<>();
        final Map<String, DescriptiveMetadataViewBundle> bundles = new HashMap<>();
        for (DescriptiveMetadataViewBundle descMetadataBundle : bundle.getRepresentationDescriptiveMetadata()) {
            String title = descMetadataBundle.getLabel() != null ? descMetadataBundle.getLabel()
                    : descMetadataBundle.getId();
            HTML container = new HTML();
            container.addStyleName("metadataContent");
            itemMetadata.add(container, title);
            descriptiveMetadataContainers.add(Pair.of(descMetadataBundle.getId(), container));
            bundles.put(descMetadataBundle.getId(), descMetadataBundle);
        }

        HandlerRegistration tabHandler = itemMetadata.addSelectionHandler(new SelectionHandler<Integer>() {

            @Override
            public void onSelection(SelectionEvent<Integer> event) {
                if (event.getSelectedItem() < descriptiveMetadataContainers.size()) {
                    Pair<String, HTML> pair = descriptiveMetadataContainers.get(event.getSelectedItem());
                    String descId = pair.getFirst();
                    final HTML html = pair.getSecond();
                    final DescriptiveMetadataViewBundle bundle = bundles.get(descId);
                    if (html.getText().length() == 0) {
                        getDescriptiveMetadataHTML(descId, bundle, new AsyncCallback<SafeHtml>() {

                            @Override
                            public void onFailure(Throwable caught) {
                                if (!AsyncCallbackUtils.treatCommonFailures(caught)) {
                                    Toast.showError(messages.errorLoadingDescriptiveMetadata(caught.getMessage()));
                                }
                            }

                            @Override
                            public void onSuccess(SafeHtml result) {
                                html.setHTML(result);
                            }
                        });
                    }
                }
            }
        });

        final int addTabIndex = itemMetadata.getWidgetCount();
        FlowPanel addTab = new FlowPanel();
        addTab.add(new HTML(SafeHtmlUtils.fromSafeConstant("<i class=\"fa fa-plus-circle\"></i>")));
        itemMetadata.add(new Label(), addTab);
        HandlerRegistration addTabHandler = itemMetadata.addSelectionHandler(new SelectionHandler<Integer>() {
            @Override
            public void onSelection(SelectionEvent<Integer> event) {
                if (event.getSelectedItem() == addTabIndex) {
                    newRepresentationDescriptiveMetadata();
                }
            }
        });
        addTab.addStyleName("addTab");
        addTab.getParent().addStyleName("addTabWrapper");

        handlers.add(tabHandler);
        handlers.add(addTabHandler);

        if (!bundle.getRepresentationDescriptiveMetadata().isEmpty()) {
            newDescriptiveMetadata.setVisible(false);
            itemMetadata.setVisible(true);
            itemMetadata.selectTab(0);
        } else {
            newDescriptiveMetadata.setVisible(true);
            itemMetadata.setVisible(false);
        }

        // DISSEMINATIONS (POST-INIT)
        if (bundle.getDipCount() > 0) {
            Filter disseminationsFilter = new Filter(
                    new SimpleFilterParameter(RodaConstants.DIP_REPRESENTATION_UUIDS, repUUID));
            disseminationsList.set(disseminationsFilter, state.equals(AIPState.ACTIVE), Facets.NONE);
            disseminationsSearch.setDefaultFilter(disseminationsFilter, true);
            disseminationsSearch.clearSearchInputBox();
        }
        disseminationsList.getParent().setVisible(bundle.getDipCount() > 0);

        // SIDEBAR
        actionsSidebar.setWidget(RepresentationActions.get(aipId).createActionsLayout(representation,
                new AsyncCallback<Actionable.ActionImpact>() {

                    @Override
                    public void onFailure(Throwable caught) {
                        AsyncCallbackUtils.defaultFailureTreatment(caught);
                    }

                    @Override
                    public void onSuccess(Actionable.ActionImpact impact) {
                        if (Actionable.ActionImpact.UPDATED.equals(impact)) {
                            BrowserService.Util.getInstance().retrieve(IndexedRepresentation.class.getName(),
                                    representation.getUUID(), representationFields,
                                    new AsyncCallback<IndexedRepresentation>() {

                                        @Override
                                        public void onFailure(Throwable caught) {
                                            AsyncCallbackUtils.defaultFailureTreatment(caught);
                                        }

                                        @Override
                                        public void onSuccess(IndexedRepresentation rep) {
                                            representation = rep;
                                            representationType.setText(rep.getType());
                                        }
                                    });
                        }
                    }
                }));

        ListSelectionUtils.bindLayout(representation, searchPrevious, searchNext, keyboardFocus, true, false, false,
                searchSection);

        // CSS
        this.addStyleName("browse");
        this.addStyleName("browse-representation");
        this.addStyleName(state.toString().toLowerCase());

        Element firstElement = this.getElement().getFirstChildElement();
        if ("input".equalsIgnoreCase(firstElement.getTagName())) {
            firstElement.setAttribute("title", "browse input");
        }

        WCAGUtilities.getInstance().makeAccessible(itemMetadata.getElement());
    }

    @Override
    protected void onLoad() {
        super.onLoad();
        JavascriptUtils.stickSidebar();
    }

    private void getDescriptiveMetadataHTML(final String descId, final DescriptiveMetadataViewBundle bundle,
            final AsyncCallback<SafeHtml> callback) {
        SafeUri uri = RestUtils.createRepresentationDescriptiveMetadataHTMLUri(aipId, repId, descId);
        RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, uri.asString());
        requestBuilder.setHeader("Authorization", "Custom");
        try {
            requestBuilder.sendRequest(null, new RequestCallback() {

                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        String html = response.getText();

                        SafeHtmlBuilder b = new SafeHtmlBuilder();
                        b.append(SafeHtmlUtils.fromSafeConstant("<div class='descriptiveMetadataLinks'>"));

                        if (bundle.hasHistory()) {
                            // History link
                            String historyLink = HistoryUtils.createHistoryHashLink(
                                    DescriptiveMetadataHistory.RESOLVER, aipId, repId, descId);
                            String historyLinkHtml = "<a href='" + historyLink
                                    + "' class='toolbarLink'><i class='fa fa-history'></i></a>";
                            b.append(SafeHtmlUtils.fromSafeConstant(historyLinkHtml));
                        }
                        // Edit link
                        String editLink = HistoryUtils.createHistoryHashLink(EditDescriptiveMetadata.RESOLVER,
                                aipId, repId, descId);
                        String editLinkHtml = "<a href='" + editLink
                                + "' class='toolbarLink'><i class='fa fa-edit'></i></a>";
                        b.append(SafeHtmlUtils.fromSafeConstant(editLinkHtml));

                        // Download link
                        SafeUri downloadUri = RestUtils.createRepresentationDescriptiveMetadataDownloadUri(aipId,
                                repId, descId);
                        String downloadLinkHtml = "<a href='" + downloadUri.asString()
                                + "' class='toolbarLink'><i class='fa fa-download'></i></a>";
                        b.append(SafeHtmlUtils.fromSafeConstant(downloadLinkHtml));

                        b.append(SafeHtmlUtils.fromSafeConstant("</div>"));

                        b.append(SafeHtmlUtils.fromSafeConstant("<div class='descriptiveMetadataHTML'>"));
                        b.append(SafeHtmlUtils.fromTrustedString(html));
                        b.append(SafeHtmlUtils.fromSafeConstant("</div>"));
                        SafeHtml safeHtml = b.toSafeHtml();

                        callback.onSuccess(safeHtml);
                    } else {
                        String text = response.getText();
                        String message;
                        try {
                            RestErrorOverlayType error = (RestErrorOverlayType) JsonUtils.safeEval(text);
                            message = error.getMessage();
                        } catch (IllegalArgumentException e) {
                            message = text;
                        }

                        SafeHtmlBuilder b = new SafeHtmlBuilder();
                        b.append(SafeHtmlUtils.fromSafeConstant("<div class='descriptiveMetadataLinks'>"));

                        if (bundle.hasHistory()) {
                            // History link
                            String historyLink = HistoryUtils.createHistoryHashLink(
                                    DescriptiveMetadataHistory.RESOLVER, aipId, repId, descId);
                            String historyLinkHtml = "<a href='" + historyLink
                                    + "' class='toolbarLink'><i class='fa fa-history'></i></a>";
                            b.append(SafeHtmlUtils.fromSafeConstant(historyLinkHtml));
                        }

                        // Edit link
                        String editLink = HistoryUtils.createHistoryHashLink(EditDescriptiveMetadata.RESOLVER,
                                aipId, repId, descId);
                        String editLinkHtml = "<a href='" + editLink
                                + "' class='toolbarLink'><i class='fa fa-edit'></i></a>";
                        b.append(SafeHtmlUtils.fromSafeConstant(editLinkHtml));

                        b.append(SafeHtmlUtils.fromSafeConstant("</div>"));

                        // error message
                        b.append(SafeHtmlUtils.fromSafeConstant("<div class='error'>"));
                        b.append(messages.descriptiveMetadataTransformToHTMLError());
                        b.append(SafeHtmlUtils.fromSafeConstant("<pre><code>"));
                        b.append(SafeHtmlUtils.fromString(message));
                        b.append(SafeHtmlUtils.fromSafeConstant("</core></pre>"));
                        b.append(SafeHtmlUtils.fromSafeConstant("</div>"));

                        callback.onSuccess(b.toSafeHtml());
                    }
                }

                @Override
                public void onError(Request request, Throwable exception) {
                    callback.onFailure(exception);
                }
            });
        } catch (RequestException e) {
            callback.onFailure(e);
        }
    }

    private void newRepresentationDescriptiveMetadata() {
        HistoryUtils.newHistory(CreateDescriptiveMetadata.RESOLVER, RodaConstants.RODA_OBJECT_REPRESENTATION, aipId,
                repId);
    }

    @UiHandler("newDescriptiveMetadata")
    void buttonNewDescriptiveMetadataEventsHandler(ClickEvent e) {
        newRepresentationDescriptiveMetadata();
    }
}