view gwt-client/src/test/java/test/ModuleRunner.java @ 9133:af73fdd96920

Title current/historical diff pair; limit on entries in diff'pair twin_panel
author gernotbelger
date Thu, 07 Jun 2018 11:41:10 +0200
parents dbb26bc81843
children
line wrap: on
line source
package test;

/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
 * Software engineering by
 *  Björnsen Beratende Ingenieure GmbH
 *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
import org.dive4elements.artifacts.common.utils.ClientProtocolUtils;
import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
import org.dive4elements.artifacts.httpclient.http.HttpClient;
import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
import org.dive4elements.artifacts.httpclient.http.response.DocumentResponseHandler;
import org.dive4elements.artifacts.httpclient.utils.XMLUtils;
import org.dive4elements.river.client.client.ui.NilDatacageTwinPanelInfo;
import org.dive4elements.river.client.client.ui.RecommandationUtils;
import org.dive4elements.river.client.server.AdvanceServiceImpl;
import org.dive4elements.river.client.server.ArtifactHelper;
import org.dive4elements.river.client.server.CollectionHelper;
import org.dive4elements.river.client.server.CreateCollectionServiceImpl;
import org.dive4elements.river.client.server.FLYSArtifactCreator;
import org.dive4elements.river.client.server.FeedServiceImpl;
import org.dive4elements.river.client.server.LoadArtifactServiceImpl;
import org.dive4elements.river.client.server.auth.DefaultUser;
import org.dive4elements.river.client.server.auth.User;
import org.dive4elements.river.client.server.auth.UserClient;
import org.dive4elements.river.client.shared.exceptions.ServerException;
import org.dive4elements.river.client.shared.model.Artifact;
import org.dive4elements.river.client.shared.model.Collection;
import org.dive4elements.river.client.shared.model.Data;
import org.dive4elements.river.client.shared.model.DataItem;
import org.dive4elements.river.client.shared.model.DefaultCollection;
import org.dive4elements.river.client.shared.model.DefaultDataItem;
import org.dive4elements.river.client.shared.model.OutputMode;
import org.dive4elements.river.client.shared.model.Recommendation;
import org.dive4elements.river.client.shared.model.StringOptionsData;
import org.junit.Assert;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import test.BerechnungsartenTester.CalcMode;
import test.BerechnungsartenTester.FilenameMapper;
import test.BerechnungsartenTester.River;

/**
 * @author Domenico Nardi Tironi
 *
 */
public abstract class ModuleRunner {

    public enum Infotype {
        sinfo
    }

    private final String serverUrl = "http://localhost:8181";
    private final String locale = "de";
    private final HttpClient client;

    private static final String exportFileDir = "D:" + File.separator;
    private static final String IGNORE_ERSTELLDATUM = "# Datum der Erstellung";
    private static final String IGNORE_FLYS_VERSION = "# FLYS-Version:";
    private static final String IGNORE_BEARBEITER = "# Bearbeiter:";

    private final String username;
    private final String password;
    private final Infotype infotype;
    private final String userUuid;
    private Collection collection;
    private Artifact artifact;
    private final FilenameMapper fileName;

    // common attributes
    private final CalcMode calcMode;
    private final double from;
    private final double to;
    private final River river;

    private final List<String> pairIds = new ArrayList<String>(); // TODO in Subklassen

    public ModuleRunner(final String username, final String password, final Infotype infotype, final CalcMode sinfoCalcFlowDepth,
            final FilenameMapper helloWorldFile, final double from, final double to, final River beispielfluss) throws ConnectionException, ServerException {
        // common attributes (evtl. doch in subklassen, evtl. Zwischenhierarchiestufe einführen

        this.calcMode = sinfoCalcFlowDepth;
        this.river = beispielfluss;
        this.from = from;
        this.to = to;

        this.username = username;
        this.password = password;
        this.infotype = infotype;
        this.fileName = helloWorldFile;

        // init
        this.client = new HttpClientImpl(this.serverUrl, this.locale);
        this.userUuid = makeUserUuid();
        this.collection = getCollection();
        this.artifact = getArtifact();
    }

    private String makeUserUuid() throws ConnectionException {
        final User user = new DefaultUser(this.username, this.password, null, false, new ArrayList<String>(), new ArrayList<String>());
        final UserClient userClient = new UserClient(this.serverUrl);
        Element userElement;

        userElement = userClient.findUser(user);
        return userElement.getAttributeNS(ArtifactNamespaceContext.NAMESPACE_URI, "uuid");

    }

    protected final Artifact getArtifact() throws ServerException, ConnectionException {
        if (this.artifact == null) {
            this.artifact = ArtifactHelper.createArtifact(this.serverUrl, this.locale, this.infotype.name(), null);
            setCollection(CollectionHelper.addArtifact(getCollection(), this.artifact, this.serverUrl, this.locale)); // wichtig; sorgt für Persistenz
        }
        return this.artifact;
    }

    private Collection getCollection() throws ConnectionException {

        if (this.collection == null) {
            // lazy-Loading
            final Document create = ClientProtocolUtils.newCreateCollectionDocument(null);
            final Document doc = (Document) this.client.createCollection(create, this.userUuid, new DocumentResponseHandler());
            final String uuid = XMLUtils.xpathString(doc, CreateCollectionServiceImpl.XPATH_COLLECTION_UUID, ArtifactNamespaceContext.INSTANCE);
            final String ttlStr = XMLUtils.xpathString(doc, CreateCollectionServiceImpl.XPATH_COLLECTION_TTL, ArtifactNamespaceContext.INSTANCE);
            this.collection = new DefaultCollection(uuid, Long.valueOf(ttlStr), uuid);
        }
        return this.collection;

    }

    private final void setCollection(final Collection collection) {
        this.collection = collection;
    }

    private final void setArtifact(final Artifact artifact) {
        this.artifact = artifact;
    }

    public abstract void runTest(final boolean exportToFile) throws ConnectionException, ServerException, IOException;

    protected final void describeCollection() throws ConnectionException {

        final String uuid = getCollection().identifier();
        final Document describe = ClientProtocolUtils.newDescribeCollectionDocument(uuid);
        final Document response = (Document) this.client.doCollectionAction(describe, uuid, new DocumentResponseHandler());
        final Collection c = CollectionHelper.parseCollection(response);
        setCollection(c);

    }

    protected final void feedAndGo(final Data[] data, final int reachableStateIndex) throws ConnectionException, ServerException {
        feed(data);
        advance(getReachableStateByIndex(getArtifact(), reachableStateIndex)); // reachablestate könnte auch String sein.

    }

    private final String getReachableStateByIndex(final Artifact artifact, final int index) {

        final String[] states = artifact.getArtifactDescription().getReachableStates();
        if (states != null) {
            if (states.length > index) {
                return states[index];
            } else {
                return states[0];
            }
        } else {
            return "";
        }
    }

    private final void feed(final Data[] data) throws ServerException, ConnectionException {
        final Document feed = ClientProtocolUtils.newFeedDocument(getArtifact().getUuid(), getArtifact().getHash(), createKVP(data));
        final Document description = (Document) this.client.feed(
                new org.dive4elements.artifacts.httpclient.objects.Artifact(getArtifact().getUuid(), getArtifact().getHash()), feed,
                new DocumentResponseHandler());

        final String result = XMLUtils.xpathString(description, FeedServiceImpl.XPATH_RESULT, ArtifactNamespaceContext.INSTANCE);

        if (result == null || !result.equals(FeedServiceImpl.OPERATION_FAILURE)) {
            setArtifact((Artifact) new FLYSArtifactCreator().create(description));
        } else if (result != null && result.equals(FeedServiceImpl.OPERATION_FAILURE)) {
            final String msg = XMLUtils.xpathString(description, FeedServiceImpl.XPATH_RESULT_MSG, ArtifactNamespaceContext.INSTANCE);
            throw new ServerException(msg);
        }
    }

    private final String[][] createKVP(final Data[] data) {
        if (data != null) {
            final String[][] kvp = new String[data.length][];

            int i = 0;

            for (final Data d : data) {
                // final DataItem[] items = d.getItems();
                final String key = d.getLabel();
                final String value = d.getStringValue();

                kvp[i++] = new String[] { key, value };
            }

            return kvp;
        }
        return null;
    }

    private final void advance(final String target) throws ConnectionException, ServerException {
        final Document advance = ClientProtocolUtils.newAdvanceDocument(getArtifact().getUuid(), getArtifact().getHash(), target);
        final Document description = (Document) this.client.advance(
                new org.dive4elements.artifacts.httpclient.objects.Artifact(getArtifact().getUuid(), getArtifact().getHash()), advance,
                new DocumentResponseHandler());

        if (description == null) {
            throw new ServerException(AdvanceServiceImpl.ERROR_ADVANCE_ARTIFACT);
        }

        final String result = XMLUtils.xpathString(description, AdvanceServiceImpl.XPATH_RESULT, ArtifactNamespaceContext.INSTANCE);

        if (result == null || !result.equals(AdvanceServiceImpl.OPERATION_FAILURE)) {
            setArtifact((Artifact) new FLYSArtifactCreator().create(description));
        }
    }

    protected final Artifact[] loadMany(final Recommendation[] recoms, final String factory) throws ServerException, ConnectionException {
        final ArrayList<Artifact> artifacts = new ArrayList<Artifact>();
        final HashMap<Recommendation, Artifact> cloneMap = new HashMap<Recommendation, Artifact>();

        for (final Recommendation recom : recoms) {

            final Artifact prevClone = cloneMap.get(recom);
            if (prevClone != null) {

                artifacts.add(prevClone);
            } else {
                // Not already cloned.
                final String realFactory = factory != null ? factory : recom.getFactory();

                final Artifact clone = ArtifactHelper.createArtifact(this.serverUrl, this.locale, realFactory, recom);

                if (clone != null) {
                    final Collection c = CollectionHelper.addArtifact(getCollection(), clone, this.serverUrl, this.locale);

                    if (c != null) {
                        artifacts.add(clone);
                        // Remember we cloned a recommendation like this.
                        cloneMap.put(recom, clone);
                    } else {
                        throw new ServerException(LoadArtifactServiceImpl.ERROR_LOAD_ARTIFACT);
                    }
                }
            }
        }
        return artifacts.toArray(new Artifact[artifacts.size()]);

    }

    /// ExportServiceImpl
    protected final void doGet(final String mode, final boolean exportToFile) throws IOException {

        final String type = "csv";

        final String enc = "windows-1252";// req.getParameter("encoding");

        final URL expectedResource = getClass().getResource(this.fileName.getFilename());
        final Document attr = null;
        final Document request = ClientProtocolUtils.newOutCollectionDocument(getCollection().identifier(), mode, type, attr);

        final InputStream response = this.client.collectionOut(request, getCollection().identifier(), mode);

        final String actual = deleteErstelldatum(IOUtils.toString(response, "UTF-8"));

        final String expected = deleteErstelldatum(FileUtils.readFileToString(new File(expectedResource.getFile()), enc));

        // if (!actual.equals(expected)) {
        if (exportToFile) {
            doGetWriteToDisk(mode); // TODO: WENN der Test negativ ausfällt, Datei abspeichern -> Diskussion
        }

        Assert.assertEquals(expected, actual);
    }

    private final String deleteErstelldatum(final String input) {
        String result = "";
        final String[] lines = input.split(System.lineSeparator());
        for (final String line : lines) {
            if (!line.contains(ModuleRunner.IGNORE_ERSTELLDATUM) && !line.contains(ModuleRunner.IGNORE_FLYS_VERSION)
                    && !line.contains(ModuleRunner.IGNORE_BEARBEITER)) {
                result = result + line + System.lineSeparator();
            }
        }
        return result;
    }

    public final void doGetWriteToDisk(final String mode) throws FileNotFoundException, IOException {

        final String name = mode;
        final String type = "csv";

        final String fn = name + System.currentTimeMillis() + "." + type;
        final String enc = "windows-1252";

        final String filepath = exportFileDir + fn;

        final Document attr = null;
        final Document request = ClientProtocolUtils.newOutCollectionDocument(getCollection().identifier(), mode, type, attr);

        final InputStream response = this.client.collectionOut(request, getCollection().identifier(), mode);
        final InputStreamReader in = new InputStreamReader(response, "UTF-8");

        IOUtils.copy(in, new FileOutputStream(filepath), enc);

    }

    public final void addRecommendationPair(final SimpleRecommendation rec1, final SimpleRecommendation rec2) throws ConnectionException, ServerException {
        final Recommendation recom1 = new Recommendation(rec1.getFactory(), rec1.getIds(), rec1.getTarget());
        final Recommendation recom2 = new Recommendation(rec2.getFactory(), rec2.getIds(), rec2.getTarget());
        final Artifact[] artifacts = loadMany(new Recommendation[] { recom1, recom2 }, null);
        final String rec1String = RecommandationUtils.createDataString(artifacts[0].getUuid(), recom1, new NilDatacageTwinPanelInfo("xxxx"));
        final String rec2String = RecommandationUtils.createDataString(artifacts[1].getUuid(), recom2, new NilDatacageTwinPanelInfo("xxxx"));
        final String combinedIdNeu = rec1String + "#" + rec2String;
        this.pairIds.add(combinedIdNeu);
    }

    protected Data[] getPairData() {
        final Data[] data = new Data[this.pairIds.size()];
        int i = 0;
        for (final String pairId : this.pairIds) {
            final Data pair = new StringOptionsData("diffids", "diffids", new DataItem[] { new DefaultDataItem(pairId, pairId, pairId) });
            data[i] = pair;
            i++;
        }
        return data;
    }

    protected final void selectCalcMode() throws ConnectionException, ServerException {

        /* Select CalcMode */
        // final DataList calcModes = getArtifact().getArtifactDescription().getCurrentData(); // AUSWAHL-Möglichkeiten
        // final DataItem minMaxFlowdepth = calcModes.get(0).getItems()[2]; // CalcMode
        final String calcmodeStr = this.calcMode.name();
        final Data dataCalcMode = new StringOptionsData("calculation_mode", "calculation_mode",
                new DataItem[] { new DefaultDataItem(calcmodeStr, calcmodeStr, calcmodeStr) });
        feedAndGo(new Data[] { dataCalcMode }, 0);
    }

    protected final void selectRange() throws ConnectionException, ServerException {
        final String fromStr = String.valueOf(this.from);
        final String toStr = String.valueOf(this.to);
        final Data dataFrom = new StringOptionsData("ld_from", "ld_from", new DataItem[] { new DefaultDataItem(fromStr, fromStr, fromStr) });
        final Data dataTo = new StringOptionsData("ld_to", "ld_to", new DataItem[] { new DefaultDataItem(toStr, toStr, toStr) });
        final Data[] rangeFromToDetermined = new Data[] { dataFrom, dataTo };

        feedAndGo(rangeFromToDetermined, 0);
    }

    // private final void seletMaxRange() throws ConnectionException, ServerException {
    // final DataList list = getArtifact().getArtifactDescription().getCurrentData();
    // final Data[] rangeMax = new Data[] { list.get(0), list.get(1) };
    // feedAndGo(rangeMax, 0);
    // }

    protected final void selectRiver() throws ConnectionException, ServerException {
        final String riverStr = this.river.name();
        final Data data = new StringOptionsData("river", "river", new DataItem[] { new DefaultDataItem(riverStr, riverStr, riverStr) });
        feedAndGo(new Data[] { data }, 0);
    }

    protected final void export(final boolean exportToFile) throws IOException, ServerException {
        final OutputMode[] modes = getArtifact().getArtifactDescription().getOutputModes(); // TODO: CHECK IF THIS WORKS ALSO FOR FUTURE CALC_MODES
        if (modes != null) {
            final OutputMode mode = modes[1];
            doGet(mode.getName(), exportToFile);
        }
    }

}

http://dive4elements.wald.intevation.org