org.obiba.opal.web.gwt.app.client.magma.view.TableValidationView.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.opal.web.gwt.app.client.magma.view.TableValidationView.java

Source

/*
 * Copyright (c) 2013 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.obiba.opal.web.gwt.app.client.magma.view;

import com.github.gwtbootstrap.client.ui.Alert;
import com.github.gwtbootstrap.client.ui.Button;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.json.client.JSONArray;
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.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
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.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.ViewWithUiHandlers;
import org.obiba.opal.web.gwt.app.client.i18n.Translations;
import org.obiba.opal.web.gwt.app.client.magma.presenter.TableValidationPresenter;
import org.obiba.opal.web.gwt.app.client.magma.presenter.TableValidationUiHandlers;
import org.obiba.opal.web.model.client.magma.TableDto;
import org.obiba.opal.web.model.client.opal.ValidationResultDto;

import java.util.*;

@SuppressWarnings("OverlyCoupledClass")
public class TableValidationView extends ViewWithUiHandlers<TableValidationUiHandlers>
        implements TableValidationPresenter.Display {

    interface TableValidationViewUiBinder extends UiBinder<Widget, TableValidationView> {
    }

    private static final TableValidationViewUiBinder uiBinder = GWT.create(TableValidationViewUiBinder.class);

    private final Widget widget;

    @UiField
    FlowPanel alertsPanel;

    @UiField
    Alert alert;

    @UiField
    Label errorMessage;

    @UiField
    Button validate;

    private TableDto table;

    //@todo is there a better way than hardcoding the styles?
    private static final String TABLE_TAG = "<TABLE class=\"table table-striped table-condensed table-bordered bottom-margin\">";

    @UiField
    HTMLPanel validationResultsPanel;

    private final Translations translations = GWT.create(Translations.class);

    @Inject
    public TableValidationView(EventBus eventBus) {
        widget = uiBinder.createAndBindUi(this);
    }

    @Override
    public Widget asWidget() {
        return widget;
    }

    @Override
    public void setTable(TableDto table) {

        clearErrorMessages();

        if (needsValidationViewReset(table)) {
            //only clear validation results if needed.
            //this way we can keep the results if they are still on the same datasource/table
            setValidationResult(null);
        } else {
            validationResultsPanel.setVisible(true);
        }

        this.table = table;
    }

    @UiHandler("validate")
    public void onValidate(ClickEvent event) {
        validate.setEnabled(false);
        getUiHandlers().onValidate();
    }

    @Override
    public void setValidationResult(ValidationResultDto dto) {
        if (dto != null) {
            SafeHtml html = buildValidationResultsHtml(dto);
            validationResultsPanel.getElement().setInnerSafeHtml(html);
        } else {
            validationResultsPanel.clear();
            validationResultsPanel.getElement().setInnerHTML("");
        }
    }

    @Override
    public void setValidationFinished() {
        validate.setEnabled(true);
    }

    @Override
    public void setValidationInProgress() {
        validationResultsPanel.clear();
        validationResultsPanel.getElement().setInnerHTML(translations.validationInProgress());
    }

    @Override
    public void clearErrorMessages() {
        alertsPanel.clear();
    }

    @Override
    public void setErrorMessage(String title, String message) {
        alert.setHeading(title);
        errorMessage.getElement().setInnerHTML(message);
        alertsPanel.add(alert);
    }

    private static final Map<String, Set<String>> getVariableRuleMap(JSONObject rules) {
        List<String> vars = new ArrayList<>(rules.keySet());
        Map<String, Set<String>> map = new LinkedHashMap<>();
        for (String var : vars) {
            JSONArray array = (JSONArray) rules.get(var);
            Set<String> set = new LinkedHashSet<>();
            for (int i = 0; i < array.size(); i++) {
                JSONString str = (JSONString) array.get(i);
                set.add(str.stringValue());
            }
            map.put(var, set);
        }
        return map;
    }

    private static Set<String> flatten(Collection<Set<String>> sets) {
        Set<String> result = new HashSet<>();
        for (Set<String> set : sets) {
            result.addAll(set);
        }
        return result;
    }

    private static Map<List<String>, List<String>> getVariableRuleFailedValuesMap(JSONObject failures) {
        Map<List<String>, List<String>> result = new HashMap<>();

        for (String key : failures.keySet()) {
            //@todo improve the tokenizing code (use regex)
            String str = key.replace("[", "").replace("]", "").replace(",", " ");
            String[] parts = str.split("\\s+");
            List<String> pair = Arrays.asList(parts);
            result.put(pair, toList((JSONArray) failures.get(key)));
        }

        return result;
    }

    private static List<String> toList(JSONArray array) {
        List<String> result = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONString str = (JSONString) array.get(i);
            result.add(str.stringValue());
        }
        return result;
    }

    private SafeHtml buildValidationResultsHtml(ValidationResultDto dto) {
        JSONObject rules = (JSONObject) JSONParser.parseStrict(dto.getRules());
        JSONObject failures = (JSONObject) JSONParser.parseStrict(dto.getFailures());

        SafeHtmlBuilder builder = new SafeHtmlBuilder();

        if (rules.size() > 0) {
            Map<String, Set<String>> variableRuleMap = getVariableRuleMap(rules);
            Map<List<String>, List<String>> failedValuesMap = getVariableRuleFailedValuesMap(failures);
            builder.appendHtmlConstant("<h4>").appendEscaped(translations.validationOverviewTitle())
                    .appendHtmlConstant("</h4>");
            builder.append(buildValidationSummaryTable(variableRuleMap, failedValuesMap));
            builder.appendHtmlConstant("<h4>").appendEscaped(translations.validationDetailTitle())
                    .appendHtmlConstant("</h4>");
            addValidationFailureTable(builder, failedValuesMap);
        } else {
            builder.appendEscaped("No validation configured");
        }
        return builder.toSafeHtml();
    }

    private SafeHtml buildValidationSummaryTable(Map<String, Set<String>> variableRuleMap,
            Map<List<String>, List<String>> failedValuesMap) {
        SafeHtmlBuilder builder = new SafeHtmlBuilder();
        List<String> constraints = new ArrayList<>(flatten(variableRuleMap.values()));

        builder.appendHtmlConstant(TABLE_TAG);
        builder.appendHtmlConstant("<TR>");
        addTableHeader(builder, translations.variableLabel());

        for (String constraint : constraints) {
            addTableHeader(builder, constraint);
        }

        builder.appendHtmlConstant("</TR>");

        for (String var : variableRuleMap.keySet()) {
            builder.appendHtmlConstant("<TR>");

            builder.appendHtmlConstant("<TD>").appendEscaped(var).appendHtmlConstant("</TD>");
            Set<String> set = variableRuleMap.get(var);
            for (String cons : constraints) {
                Boolean failure = null;
                if (set.contains(cons)) {
                    //constraint/variable is configured
                    List<String> key = Arrays.asList(var, cons);
                    failure = failedValuesMap.containsKey(key);
                }
                builder.appendHtmlConstant("<TD>");
                if (failure != null) {
                    addValidationCell(builder, failure.booleanValue());
                }
                builder.appendHtmlConstant("</TD>");
            }
            builder.appendHtmlConstant("</TR>");
        }

        builder.appendHtmlConstant("</TABLE>");

        return builder.toSafeHtml();
    }

    private void addValidationCell(SafeHtmlBuilder builder, boolean failure) {
        String color = translations.validationOkColor();
        String text = translations.validationOk();
        if (failure) {
            color = translations.validationFailColor();
            text = translations.validationFail();
        }

        builder.appendHtmlConstant("<font color=\"" + color + "\">");
        builder.appendEscaped(text);
        builder.appendHtmlConstant("</font>");
    }

    private void addValidationFailureTable(SafeHtmlBuilder builder,
            Map<List<String>, List<String>> failedValuesMap) {
        builder.appendHtmlConstant(TABLE_TAG);
        builder.appendHtmlConstant("<TR>");
        addTableHeader(builder, translations.variableLabel());
        addTableHeader(builder, translations.constraintLabel());
        addTableHeader(builder, translations.values());
        builder.appendHtmlConstant("</TR>");

        for (List<String> key : failedValuesMap.keySet()) {

            builder.appendHtmlConstant("<TR>");
            builder.appendHtmlConstant("<TD>").appendEscaped(key.get(0)).appendHtmlConstant("</TD>");
            builder.appendHtmlConstant("<TD>").appendEscaped(key.get(1)).appendHtmlConstant("</TD>");
            builder.appendHtmlConstant("<TD>");
            List<String> values = failedValuesMap.get(key);
            for (String value : values) {
                builder.appendEscaped(value).appendHtmlConstant("</BR>");
            }
            builder.appendHtmlConstant("</TD>");
            builder.appendHtmlConstant("</TR>");
        }

        builder.appendHtmlConstant("</TABLE>");
    }

    private static void addTableHeader(SafeHtmlBuilder builder, String header) {
        builder.appendHtmlConstant("<TH>").appendEscaped(header).appendHtmlConstant("</TH>");
    }

    private boolean needsValidationViewReset(TableDto newTable) {

        if (newTable == null || this.table == null) {
            return true;
        }

        if (!newTable.getName().equals(this.table.getName())) {
            return true; //different table
        }

        if (!newTable.getDatasourceName().equals(this.table.getDatasourceName())) {
            return true; //different datasource
        }

        return false;
    }

}