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

Java tutorial

Introduction

Here is the source code for org.roda.wui.client.browse.EditDescriptiveMetadata.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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.v2.validation.ValidationException;
import org.roda.core.data.v2.validation.ValidationIssue;
import org.roda.wui.client.browse.bundle.DescriptiveMetadataEditBundle;
import org.roda.wui.client.browse.bundle.SupportedMetadataTypeBundle;
import org.roda.wui.client.common.UserLogin;
import org.roda.wui.client.common.dialogs.Dialogs;
import org.roda.wui.client.common.utils.AsyncCallbackUtils;
import org.roda.wui.client.common.utils.FormUtilities;
import org.roda.wui.client.common.utils.JavascriptUtils;
import org.roda.wui.common.client.HistoryResolver;
import org.roda.wui.common.client.tools.HistoryUtils;
import org.roda.wui.common.client.tools.ListUtils;
import org.roda.wui.common.client.widgets.Toast;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
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.Window;
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.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import config.i18n.client.ClientMessages;

/**
 * @author Luis Faria
 * 
 */
public class EditDescriptiveMetadata extends Composite {

    public static final HistoryResolver RESOLVER = new HistoryResolver() {

        @Override
        public void resolve(List<String> historyTokens, final AsyncCallback<Widget> callback) {
            if (historyTokens.size() == 2 || historyTokens.size() == 3) {
                final String aipId = historyTokens.get(0);
                final String representationId = historyTokens.size() == 3 ? historyTokens.get(1) : null;
                final String descriptiveMetadataId = new HTML(historyTokens.get(historyTokens.size() - 1))
                        .getText();

                BrowserService.Util.getInstance().retrieveDescriptiveMetadataEditBundle(aipId, representationId,
                        descriptiveMetadataId, LocaleInfo.getCurrentLocale().getLocaleName(),
                        new AsyncCallback<DescriptiveMetadataEditBundle>() {

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

                            @Override
                            public void onSuccess(DescriptiveMetadataEditBundle bundle) {
                                EditDescriptiveMetadata edit = new EditDescriptiveMetadata(aipId, representationId,
                                        bundle);
                                callback.onSuccess(edit);
                            }
                        });
            } else {
                HistoryUtils.newHistory(BrowseAIP.RESOLVER);
                callback.onSuccess(null);
            }
        }

        @Override
        public void isCurrentUserPermitted(AsyncCallback<Boolean> callback) {
            // TODO check for edit metadata permission
            UserLogin.getInstance().checkRoles(new HistoryResolver[] { BrowseAIP.RESOLVER }, false, callback);
        }

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

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

    interface MyUiBinder extends UiBinder<Widget, EditDescriptiveMetadata> {
    }

    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    private final String aipId;
    private final String representationId;
    private DescriptiveMetadataEditBundle bundle;
    private SupportedMetadataTypeBundle supportedBundle;
    private boolean inXML = false;
    private TextArea metadataXML;
    private String metadataTextFromForm = null;

    private static final ClientMessages messages = GWT.create(ClientMessages.class);

    @UiField
    TextBox id;

    @UiField
    ListBox type;

    @UiField
    Label formSimilarDanger;

    @UiField
    FocusPanel showXml;

    @UiField
    HTML showXmlIconXML;

    @UiField
    HTML showXmlIconForm;

    @UiField
    FlowPanel formOrXML;

    @UiField
    Button buttonApply;

    @UiField
    Button buttonRemove;

    @UiField
    Button buttonCancel;

    @UiField
    HTML errors;

    /**
     * Create a new panel to edit a user
     * 
     * @param user
     *          the user to edit
     */
    public EditDescriptiveMetadata(final String aipId, final String representationId,
            final DescriptiveMetadataEditBundle bundleParam) {
        this.aipId = aipId;
        this.representationId = representationId;
        this.bundle = bundleParam;

        // Create new Set of MetadataValues so we can keep the original
        Set<MetadataValue> newValues = null;
        if (bundle.getValues() != null) {
            newValues = new TreeSet<>();
            for (MetadataValue mv : bundle.getValues())
                newValues.add(mv.copy());
        }
        supportedBundle = new SupportedMetadataTypeBundle(bundle.getId(), bundle.getType(), bundle.getVersion(),
                bundle.getId(), bundle.getRawTemplate(), newValues);

        initWidget(uiBinder.createAndBindUi(this));
        metadataXML = new TextArea();
        metadataXML.addStyleName("form-textbox metadata-edit-area metadata-form-textbox");
        metadataXML.setTitle("Metadata edit area");

        id.setText(bundle.getId());
        id.setEnabled(false);

        type.addChangeHandler(new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent changeEvent) {
                String typeString = null;
                String version = "";
                String value = type.getSelectedValue();
                if (value.contains(RodaConstants.METADATA_VERSION_SEPARATOR) && bundle.getVersion() != null) {
                    typeString = value.substring(0, value.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR));
                    version = value.substring(value.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR) + 1,
                            value.length());
                }
                if (typeString == null) {
                    typeString = value;
                }

                BrowserService.Util.getInstance().retrieveDescriptiveMetadataEditBundle(aipId, representationId,
                        bundle.getId(), typeString, version, LocaleInfo.getCurrentLocale().getLocaleName(),
                        new AsyncCallback<DescriptiveMetadataEditBundle>() {
                            @Override
                            public void onFailure(Throwable caught) {
                                AsyncCallbackUtils.defaultFailureTreatment(caught);
                            }

                            @Override
                            public void onSuccess(DescriptiveMetadataEditBundle editBundle) {
                                bundle = editBundle;
                                // Create new Set of MetadataValues so we can keep the original
                                Set<MetadataValue> newValues = null;
                                if (bundle.getValues() != null) {
                                    newValues = new TreeSet<>();
                                    for (MetadataValue mv : bundle.getValues())
                                        newValues.add(mv.copy());
                                }

                                supportedBundle = new SupportedMetadataTypeBundle(bundle.getId(), bundle.getType(),
                                        bundle.getVersion(), bundle.getId(), bundle.getRawTemplate(), newValues);
                                updateFormOrXML();
                            }
                        });
            }
        });

        BrowserService.Util.getInstance().retrieveSupportedMetadata(aipId, representationId,
                LocaleInfo.getCurrentLocale().getLocaleName(),
                new AsyncCallback<List<SupportedMetadataTypeBundle>>() {

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

                    @Override
                    public void onSuccess(List<SupportedMetadataTypeBundle> metadataTypes) {
                        // TODO sort by alphabetic order of value
                        int selected = -1;
                        int index = 0;
                        Map<String, Integer> types = new HashMap<>();
                        for (SupportedMetadataTypeBundle b : metadataTypes) {
                            if (b.getVersion() != null) {
                                type.addItem(b.getLabel(),
                                        b.getType() + RodaConstants.METADATA_VERSION_SEPARATOR + b.getVersion());
                            } else {
                                type.addItem(b.getLabel(), b.getType());
                            }

                            String lowerCaseType = bundle.getType() != null ? bundle.getType().toLowerCase() : null;
                            if (b.getType().equalsIgnoreCase(lowerCaseType)) {
                                String lowerCaseVersion = bundle.getVersion() != null
                                        ? bundle.getVersion().toLowerCase()
                                        : null;
                                if (b.getVersion() != null && lowerCaseVersion != null) {
                                    if (lowerCaseVersion != null
                                            && b.getVersion().equalsIgnoreCase(lowerCaseVersion)) {
                                        selected = index;
                                    }
                                } else if (b.getVersion() == null && lowerCaseVersion == null) {
                                    selected = index;
                                }
                            }

                            types.put(b.getType(), index);
                            index++;
                        }

                        updateFormOrXML();

                        if (selected >= 0) {
                            type.addItem(messages.otherItem(), "");
                            type.setSelectedIndex(selected);
                        } else if ("".equals(bundle.getType())) {
                            type.addItem(messages.otherItem(), "");
                            type.setSelectedIndex(type.getItemCount() - 1);
                        } else {
                            if (!types.keySet().contains(bundle.getType())) {
                                type.addItem(messages.otherItem() + "(" + bundle.getType() + ")", bundle.getType());
                                type.addItem(messages.otherItem(), "");
                                type.setSelectedIndex(type.getItemCount() - 2);
                            } else {
                                type.addItem(messages.otherItem(), "");
                                type.setSelectedIndex(types.get(bundle.getType()));
                            }

                        }
                    }
                });

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

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

    private void createForm(SupportedMetadataTypeBundle bundle) {
        formOrXML.clear();
        metadataXML.setText(this.bundle.getXml());
        FormUtilities.create(formOrXML, bundle.getValues(), true);
    }

    public void setInXML(boolean inXML) {
        this.inXML = inXML;
        if (inXML) {
            showXmlIconXML.setVisible(false);
            showXmlIconForm.setVisible(true);
        } else {
            showXmlIconXML.setVisible(true);
            showXmlIconForm.setVisible(false);
        }
    }

    @UiHandler("showXml")
    void buttonShowXmlHandler(ClickEvent e) {
        setInXML(!inXML);
        updateFormOrXML();
    }

    private void updateFormOrXML() {
        if (bundle != null && bundle.getValues() != null && !bundle.getValues().isEmpty()) {
            if (!bundle.isSimilar()) {
                formSimilarDanger.setVisible(true);
            } else {
                formSimilarDanger.setVisible(false);
            }
            showXml.setVisible(true);
            if (inXML) {
                updateMetadataXML();
            } else {
                // if the user changed the metadata text
                if (metadataTextFromForm != null && !metadataXML.getText().equals(metadataTextFromForm)) {
                    Dialogs.showConfirmDialog(messages.confirmChangeToFormTitle(),
                            messages.confirmChangeToFormMessage(), messages.dialogCancel(), messages.dialogYes(),
                            new AsyncCallback<Boolean>() {
                                @Override
                                public void onFailure(Throwable caught) {
                                    AsyncCallbackUtils.defaultFailureTreatment(caught);
                                }

                                @Override
                                public void onSuccess(Boolean aBoolean) {
                                    if (aBoolean) {
                                        formOrXML.clear();
                                        createForm(supportedBundle);
                                    } else {
                                        setInXML(!inXML);
                                    }
                                }
                            });
                } else {
                    formOrXML.clear();
                    createForm(supportedBundle);
                }
            }
        } else {
            inXML = true;
            formSimilarDanger.setVisible(false);
            formOrXML.clear();
            if (bundle != null) {
                metadataXML.setText(bundle.getXml());
            } else {
                metadataXML.setText("");
            }
            formOrXML.add(metadataXML);
            showXml.setVisible(false);
            metadataTextFromForm = null;
        }
    }

    private boolean hasModifiedForm() {
        HashMap<String, MetadataValue> formMap = new HashMap<>();
        for (MetadataValue mv : supportedBundle.getValues()) {
            formMap.put(mv.getId(), mv);
        }
        HashMap<String, MetadataValue> bundleMap = new HashMap<>();
        for (MetadataValue mv : bundle.getValues()) {
            bundleMap.put(mv.getId(), mv);
        }
        for (Entry<String, MetadataValue> entry : formMap.entrySet()) {
            String key = entry.getKey();
            MetadataValue mvForm = entry.getValue();
            String formValue = mvForm != null ? mvForm.get("value") : "";
            MetadataValue mvBundle = bundleMap.get(key);
            String bundleValue = mvBundle != null ? bundleMap.get(key).get("value") : "";

            if (!formValue.equals(bundleValue))
                return true;
        }
        return false;
    }

    private void updateMetadataXML() {
        if (hasModifiedForm()) {
            // Apply the form values to the template (server)
            BrowserService.Util.getInstance().retrieveDescriptiveMetadataPreview(supportedBundle,
                    new AsyncCallback<String>() {
                        @Override
                        public void onFailure(Throwable caught) {
                            AsyncCallbackUtils.defaultFailureTreatment(caught);
                        }

                        @Override
                        public void onSuccess(String preview) {
                            formOrXML.clear();
                            metadataXML.setText(preview);
                            formOrXML.add(metadataXML);
                            metadataTextFromForm = preview;
                        }
                    });
        } else {
            formOrXML.clear();
            metadataXML.setText(bundle.getXml());
            formOrXML.add(metadataXML);
            metadataTextFromForm = bundle.getXml();
        }
    }

    @UiHandler("buttonApply")
    void buttonApplyHandler(ClickEvent e) {
        Window.scrollTo(0, 0);
        String xmlText = metadataXML.getText();
        if (inXML) {
            updateMetadataOnServer(xmlText);
        } else {
            // Get the resulting XML using the data from the form
            BrowserService.Util.getInstance().retrieveDescriptiveMetadataPreview(supportedBundle,
                    new AsyncCallback<String>() {
                        @Override
                        public void onFailure(Throwable caught) {
                            AsyncCallbackUtils.defaultFailureTreatment(caught);
                        }

                        @Override
                        public void onSuccess(String preview) {
                            updateMetadataOnServer(preview);
                        }
                    });
        }
    }

    private void updateMetadataOnServer(String content) {
        String typeText = type.getSelectedValue();
        String version = null;

        if (typeText.contains(RodaConstants.METADATA_VERSION_SEPARATOR)) {
            version = typeText.substring(typeText.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR) + 1,
                    typeText.length());
            typeText = typeText.substring(0, typeText.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR));
        }

        DescriptiveMetadataEditBundle updatedBundle = new DescriptiveMetadataEditBundle(bundle.getId(), typeText,
                version, content);

        BrowserService.Util.getInstance().updateDescriptiveMetadataFile(aipId, representationId, updatedBundle,
                new AsyncCallback<Void>() {

                    @Override
                    public void onFailure(Throwable caught) {
                        if (caught instanceof ValidationException) {
                            ValidationException e = (ValidationException) caught;
                            updateErrors(e);
                        } else {
                            AsyncCallbackUtils.defaultFailureTreatment(caught);
                        }
                    }

                    @Override
                    public void onSuccess(Void result) {
                        errors.setText("");
                        errors.setVisible(false);
                        Toast.showInfo(messages.dialogSuccess(), messages.metadataFileSaved());
                        back();
                    }
                });

    }

    protected void updateErrors(ValidationException e) {
        SafeHtmlBuilder b = new SafeHtmlBuilder();
        for (ValidationIssue issue : e.getReport().getIssues()) {
            b.append(SafeHtmlUtils.fromSafeConstant("<span class='error'>"));
            b.append(messages.metadataParseError(issue.getLineNumber(), issue.getColumnNumber(),
                    issue.getMessage()));
            b.append(SafeHtmlUtils.fromSafeConstant("</span>"));

        }

        errors.setHTML(b.toSafeHtml());
        errors.setVisible(true);
    }

    @UiHandler("buttonRemove")
    void buttonRemoveHandler(ClickEvent e) {
        BrowserService.Util.getInstance().deleteDescriptiveMetadataFile(aipId, representationId, bundle.getId(),
                new AsyncCallback<Void>() {

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

                    @Override
                    public void onSuccess(Void result) {
                        Toast.showInfo(messages.dialogSuccess(), messages.metadataFileRemoved());
                        back();
                    }
                });
    }

    @UiHandler("buttonCancel")
    void buttonCancelHandler(ClickEvent e) {
        back();
    }

    private void back() {
        if (representationId == null) {
            HistoryUtils.openBrowse(aipId);
        } else {
            HistoryUtils.openBrowse(aipId, representationId);
        }
    }

}