Package com.data2semantics.yasgui.client.tab.results

Source Code of com.data2semantics.yasgui.client.tab.results.ResultContainer

package com.data2semantics.yasgui.client.tab.results;

/*
* #%L
* YASGUI
* %%
* Copyright (C) 2013 Laurens Rietveld
* %%
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* #L%
*/

import java.util.ArrayList;
import java.util.HashMap;

import com.data2semantics.yasgui.client.GwtCallbackWrapper;
import com.data2semantics.yasgui.client.View;
import com.data2semantics.yasgui.client.helpers.ContentTypes;
import com.data2semantics.yasgui.client.helpers.ContentTypes.Type;
import com.data2semantics.yasgui.client.helpers.Helper;
import com.data2semantics.yasgui.client.helpers.HistoryHelper.HistQueryResults;
import com.data2semantics.yasgui.client.helpers.JsMethods;
import com.data2semantics.yasgui.client.settings.Imgs;
import com.data2semantics.yasgui.client.settings.TabSettings;
import com.data2semantics.yasgui.client.tab.QueryTab;
import com.data2semantics.yasgui.client.tab.results.input.DlvResults;
import com.data2semantics.yasgui.client.tab.results.input.JsonResults;
import com.data2semantics.yasgui.client.tab.results.input.ResultsHelper;
import com.data2semantics.yasgui.client.tab.results.input.SparqlResults;
import com.data2semantics.yasgui.client.tab.results.input.XmlResults;
import com.data2semantics.yasgui.client.tab.results.output.Csv;
import com.data2semantics.yasgui.client.tab.results.output.RawResponse;
import com.data2semantics.yasgui.client.tab.results.output.ResultGrid;
import com.data2semantics.yasgui.client.tab.results.output.SimpleGrid;
import com.data2semantics.yasgui.shared.Output;
import com.data2semantics.yasgui.shared.exceptions.EndpointIdException;
import com.data2semantics.yasgui.shared.exceptions.SparqlEmptyException;
import com.data2semantics.yasgui.shared.exceptions.SparqlParseException;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.XMLParser;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLPane;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ResizedEvent;
import com.smartgwt.client.widgets.events.ResizedHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class ResultContainer extends VLayout {
  public static String XSD_DATA_PREFIX = "http://www.w3.org/2001/XMLSchema#";

  // use this setting to keep our memory use low. Only store query results in
  // settings (for re-use) when the char lenght is below this value
  private static int MAX_CHARS_RESULTS = 300000;// approx resultset of a 1000
  // use this setting to keep our settings object small enough to fit in local
  // storage. This value covers the aggregate resultset size of all tabs
  private static int MAX_CHARS_RESULTS_TOTAL = 600000;

  public enum ResultType {
    Table, Boolean, Insert;
  }

  private View view;
  private QueryTab queryTab;
  private RawResponse rawResponseOutput;
  private String queryString;
  HashMap<String, ResultType> queryTypes = new HashMap<String, ResultType>();

  private String endpoint;

  public ResultContainer(View view, QueryTab queryTab) {
    setPossibleQueryTypes();
    this.view = view;
    this.queryTab = queryTab;
  }

  private void setPossibleQueryTypes() {
    queryTypes.put("SELECT", ResultType.Table);
    queryTypes.put("ASK", ResultType.Boolean);
    queryTypes.put("CONSTRUCT", ResultType.Table);
    queryTypes.put("INSERT", ResultType.Insert);
    queryTypes.put("DESCRIBE", ResultType.Table);
    queryTypes.put("LOAD", ResultType.Insert);
    queryTypes.put("CLEAR", ResultType.Insert);
    queryTypes.put("DROP", ResultType.Insert);
    queryTypes.put("ADD", ResultType.Insert);
    queryTypes.put("MOVE", ResultType.Insert);
    queryTypes.put("COPY", ResultType.Insert);
    queryTypes.put("CREATE", ResultType.Insert);
    queryTypes.put("INSERT", ResultType.Insert);
    queryTypes.put("DELETE", ResultType.Insert);
    queryTypes.put("WITH", ResultType.Insert); // used in MODIFY
  }

  /**
   * Empty query result area
   */
  public void resetResultArea() {
    if (rawResponseOutput != null) {
      // We have an old codemirror object used for showing json results.
      // Clean this up
      JsMethods.destroyCodeMirrorQueryResponse(rawResponseOutput.getInputId());
      rawResponseOutput = null;
    }
    Canvas[] members = getMembers();
    for (Canvas member : members) {
      removeMember(member);
    }
  }

  public void resetVariables() {
    queryString = null;
    endpoint = null;
  }

  public void drawIfPossible() {
    TabSettings tabSettings = view.getSelectedTabSettings();
    if (view.getSelectedTabSettings().getQueryResultsString() != null) {
      endpoint = view.getSelectedTabSettings().getEndpoint();
      doDraw(tabSettings.getQueryResultsString(), tabSettings.getQueryResultsContentType());
    } else if (view.getHistory().getHistQueryResults(tabSettings.getEndpoint(), tabSettings.getQueryString()) != null) {
      HistQueryResults queryResults = view.getHistory().getHistQueryResults(tabSettings.getEndpoint(), tabSettings.getQueryString());
      endpoint = tabSettings.getEndpoint();
      doDraw(queryResults.getString(), queryResults.getContentType());
    } else {
      resetResultArea();
      resetVariables();
    }
  }

  /**
   * Process and draw results. Checks for content type. If it is missing or
   * strange, try to detect by parsing to xml or json
   *
   * @param queryString
   *            query string for which we got these results (this is -not-
   *            necessarily the query from the current tab object, as query
   *            execute might have a big latency with time to edit the query
   *            string)
   * @param resultString
   * @param contentType
   */
  public void drawResult(String endpoint, String queryString, String resultString, String contentType) {
    this.queryString = queryString;
    this.endpoint = endpoint;
    storeResult(endpoint, queryString, resultString, contentType);
    doDraw(resultString, contentType);
  }

  private void doDraw(String resultString, String contentTypeString) {
    if (resultString != null && resultString.length() > 0) {
      resetResultArea();
      Type contentType = ContentTypes.detectContentType(contentTypeString);

      if (contentType == null) {
        // assuming select query here (no construct)
        contentType = detectContentTypeFromResultstring(resultString);
      }
      if (contentType == null) {
        view.getErrorHelper().onQueryError(queryTab.getID(), "Unable to detect content type and parse the query results<br><br>" + resultString);
        return;
      }

      if ((queryTab.getQueryType().equals("CONSTRUCT") || queryTab.getQueryType().equals("DESCRIBE"))
          && !ResultsHelper.tabularConstructContentType(contentType)) {
        drawGraphResult(resultString, contentType);
      } else {
        addQueryResult(resultString, contentType);
      }
      resetVariables();
    }
  }

  private void storeResult(String endpoint, String queryString, String resultString, String contentType) {
    /**
     * Store in settings
     */
    view.getSettings().clearQueryResults(MAX_CHARS_RESULTS_TOTAL);
    if (resultString.length() < MAX_CHARS_RESULTS) {
      view.getSelectedTabSettings().setQueryResultsString(resultString);
      view.getSelectedTabSettings().setQueryResultsContentType(contentType);
    } else {
      view.getSelectedTabSettings().clearQueryResultsString();
      ;
      view.getSelectedTabSettings().clearQueryResultsContentType();
    }

    /**
     * Store in history helper as well. We store the resultsets in the
     * settings object (above) and store this in localstorage, but we remove
     * this part when storing the history state. If we don't, then every
     * resultset in our history gets stored, making the memory size (about)
     * linearly increase each time we execute a query... Cleaning our
     * history of our previous states is (for security reason) not
     * possible.. (we can only edit our -current- history state) Therefore,
     * keep our last three resultsets in memory manually. Is ugly though
     * (would prefer to use a proper history object for this instead of
     * building on manually), but it'll have to do
     */
    view.getHistory().addQueryResults(endpoint, queryString, resultString, contentType);
  }

  private void drawGraphResult(String responseString, Type contentType) {
    drawRawResponse(responseString, contentType);
  }

  private void addQueryResult(String responseString, Type contentType) {
    try {
      String queryType = JsMethods.getQueryType(view.getSelectedTab().getQueryTextArea().getInputId());
      if (!queryTypes.containsKey(queryType)) {
        throw new SparqlParseException("No valid query type detected for this query");
      }
      ResultType queryMode = queryTypes.get(queryType);
      switch (queryTypes.get(queryType)) {
      case Insert:
        addMember(getResultsLabel(Imgs.CHECKBOX.get(), "Done"));
        break;
      case Boolean:
      case Table:
        String outputFormat = view.getSelectedTabSettings().getOutputFormat();
        if (outputFormat.equals(Output.OUTPUT_RAW_RESPONSE)) {
          drawRawResponse(responseString, contentType);
        } else {
          SparqlResults results = getSelectResultsFromString(responseString, contentType, queryTypes.get(queryType));
          logQueryForAnalysis(results);
          if (queryMode == ResultType.Boolean) {
            drawResultsAsBoolean(results);
          } else if (queryMode == ResultType.Table) {
            drawResultsInTable(results, outputFormat);
          }
        }
        break;

      }

    } catch (SparqlEmptyException e) {
      VLayout vLayout = new VLayout();
      vLayout.setWidth100();
      vLayout.setHeight100();

      ArrayList<String> usedNamedGraphs = view.getSelectedTabSettings().getNamedGraphs();
      ArrayList<String> usedDefaultGraphs = view.getSelectedTabSettings().getDefaultGraphs();
      if ((view.getEnabledFeatures().defaultGraphsSpecificationEnabled() && usedDefaultGraphs.size() > 0)
          || (view.getEnabledFeatures().namedGraphsSpecificationEnabled() && usedNamedGraphs.size() > 0)) {
        vLayout.addMember(getResultsLabelWithWarning(Imgs.CROSS.get(), e.getMessage(),
            "You have specified named and/or default graphs in your query request, which may explain this empty result set"));
      } else {
        vLayout.addMember(getResultsLabel(Imgs.CROSS.get(), e.getMessage()));
      }

      addMember(vLayout);
    } catch (Exception e) {
      view.getErrorHelper().onError(e);

    }
  }

  private void logQueryForAnalysis(SparqlResults results) {
    // only log when we actually have results
    if (results.getBindings().size() > 0 && endpoint != null
        && (view.getAutocompletionsInfo() == null || view.getAutocompletionsInfo().queryAnalysisEnabled(endpoint))) {
      new GwtCallbackWrapper<Void>(view) {
        public void onCall(AsyncCallback<Void> callback) {
          if (view.getSettings().isDbSet()) view.getRemoteService().logLazyQuery(queryString, endpoint, callback);
        }

        protected void onFailure(Throwable throwable) {
          if (throwable instanceof EndpointIdException) {
            // ok, endpoint is not reachable from server, and user
            // is not logged in as well..
            if (JsMethods.corsEnabled(endpoint)) {
              JsMethods.drawShouldWeFetchNotification();
            }
          }
          JsMethods.logConsole("exception: " + throwable.getMessage());
        }

        protected void onSuccess(Void val) {
        }

      }.call();
    }
  }

  private SparqlResults getSelectResultsFromString(String responseString, Type contentType, ResultType resultType) {
    SparqlResults results = null;
    if (contentType == Type.SELECT_JSON) {
      results = new JsonResults(responseString, view, resultType);
    } else if (contentType == Type.SELECT_XML) {
      results = new XmlResults(responseString, view, resultType);
    } else if (contentType == Type.SELECT_CSV) {
      results = new DlvResults(responseString, view, resultType, ",");
    } else if (contentType == Type.SELECT_TSV) {
      results = new DlvResults(responseString, view, resultType, "\t");
    } else {
      throw new SparqlParseException("no valid content type found for this response");
    }
    return results;
  }

  public HLayout getResultsLabelWithWarning(String iconSrc, String message, String warningMessage) {
    HLayout resultLayout = new HLayout();
    resultLayout.setDefaultLayoutAlign(VerticalAlignment.CENTER);
    resultLayout.setHeight(60);
    resultLayout.setWidth100();

    Img cross = new Img();
    cross.setSrc(iconSrc);
    cross.setSize(20);

    Img warning = new Img();
    warning.setSrc(Imgs.WARNING.get());
    warning.setSize(13);
    warning.setTooltip(warningMessage);

    Label messageLabel = new Label("&nbsp;" + message);
    messageLabel.setAutoHeight();
    messageLabel.setStyleName("queryResultText");
    messageLabel.setWidth(70);
    resultLayout.addMembers(Helper.getHSpacer(), cross, messageLabel, warning, Helper.getHSpacer());
    return resultLayout;
  }

  public HLayout getResultsLabel(String iconSrc, String message) {
    HLayout resultLayout = new HLayout();
    resultLayout.setDefaultLayoutAlign(VerticalAlignment.CENTER);
    resultLayout.setHeight(60);
    resultLayout.setWidth100();

    Img cross = new Img();
    cross.setSrc(iconSrc);
    cross.setSize(16);

    Label messageLabel = new Label("&nbsp;" + message);
    messageLabel.setAutoHeight();
    messageLabel.setStyleName("queryResultText");
    messageLabel.setWidth(70);
    resultLayout.addMember(Helper.getHSpacer());
    resultLayout.addMember(cross);
    resultLayout.addMember(messageLabel);
    resultLayout.addMember(Helper.getHSpacer());

    return resultLayout;
  }

  private void drawResultsAsBoolean(SparqlResults sparqlResults) {
    if (sparqlResults.getBooleanResult()) {
      addMember(getResultsLabel(Imgs.CHECKBOX.get(), "true"));
    } else {
      addMember(getResultsLabel(Imgs.CROSS.get(), "false"));
    }
  }

  private void drawResultsInTable(SparqlResults sparqlResults, String outputFormat) {
    Csv csvParser = new Csv(view, sparqlResults);
    if (JsMethods.stringToDownloadSupported()) {
      String url = JsMethods.stringToUrl(csvParser.getCsvString(), "text/csv");
      view.getSelectedTab().getDownloadLink().showCsvIcon(url);
    }
    if (outputFormat.equals(Output.OUTPUT_TABLE)) {
      HTMLPane html = new HTMLPane();
      // html.setHeight(27);
      addMember(html);
      addMember(new ResultGrid(view, sparqlResults, html));
    } else if (outputFormat.equals(Output.OUTPUT_TABLE_SIMPLE)) {
      addMember(new SimpleGrid(view, sparqlResults));
    }
  }

  private void drawRawResponse(String responseString, Type contentType) {
    if (JsMethods.stringToDownloadSupported()) {
      String url = JsMethods.stringToUrl(responseString, contentType.getContentType());
      view.getSelectedTab().getDownloadLink().showDownloadIcon(url, contentType);
    }
    rawResponseOutput = new RawResponse(view, queryTab, responseString);
    addMember(rawResponseOutput);

    final String mode;
    if (contentType.getCmMode() != null) {
      mode = contentType.getCmMode();
    } else {
      mode = Type.SELECT_XML.getCmMode();
    }
    // on window resize, part of the page get redrawn. This means we have to
    // attach to codemirror again
    // this is also called on first load
    rawResponseOutput.addResizedHandler(new ResizedHandler() {
      @Override
      public void onResized(ResizedEvent event) {
        Scheduler.get().scheduleDeferred(new Command() {
          public void execute() {
            JsMethods.initializeQueryResponseCodemirror(rawResponseOutput.getInputId(), mode);
            rawResponseOutput.adjustForContent(true);
          }
        });
      }
    });
  }

  public RawResponse getRawResponseOutput() {
    return this.rawResponseOutput;
  }

  public Type detectContentTypeFromResultstring(String responseString) {
    Type contentType = null;
    try {
      JSONValue jsonValue = JSONParser.parseStrict(responseString);
      if (jsonValue != null) {
        JSONObject jsonObject = jsonValue.isObject();
        JSONValue head = jsonObject.get("head");
        if (head != null) {
          return Type.SELECT_JSON;
        }
      }
    } catch (Exception e) {
    }
    try {
      Document xmlDoc = XMLParser.parse(responseString);
      if (xmlDoc != null && xmlDoc.getElementsByTagName("sparql").getLength() > 0) {
        return Type.SELECT_XML;
      }
    } catch (Exception e) {
    }

    return contentType;
  }
}
TOP

Related Classes of com.data2semantics.yasgui.client.tab.results.ResultContainer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.