Package com.data2semantics.yasgui.server.db

Source Code of com.data2semantics.yasgui.server.db.DbHelper

package com.data2semantics.yasgui.server.db;

/*
* #%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.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.data2semantics.yasgui.server.Helper;
import com.data2semantics.yasgui.server.fetchers.ConfigFetcher;
import com.data2semantics.yasgui.server.fetchers.PropertiesFetcher;
import com.data2semantics.yasgui.server.openid.HttpCookies;
import com.data2semantics.yasgui.server.openid.OpenIdServlet;
import com.data2semantics.yasgui.shared.Bookmark;
import com.data2semantics.yasgui.shared.UserDetails;
import com.data2semantics.yasgui.shared.autocompletions.AccessibilityStatus;
import com.data2semantics.yasgui.shared.autocompletions.AutocompletionConfigCols;
import com.data2semantics.yasgui.shared.autocompletions.AutocompletionsInfo;
import com.data2semantics.yasgui.shared.autocompletions.EndpointPrivateFlag;
import com.data2semantics.yasgui.shared.autocompletions.FetchMethod;
import com.data2semantics.yasgui.shared.autocompletions.FetchStatus;
import com.data2semantics.yasgui.shared.autocompletions.FetchType;
import com.data2semantics.yasgui.shared.autocompletions.Util;
import com.data2semantics.yasgui.shared.exceptions.EndpointIdException;
import com.data2semantics.yasgui.shared.exceptions.OpenIdException;
import com.data2semantics.yasgui.shared.exceptions.PossiblyNeedPaging;
import com.google.common.collect.HashMultimap;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.rdf.model.RDFNode;

public class DbHelper {
  private JSONObject config;
  private Connection connect;
  private HttpServletRequest request;

  public DbHelper(File configDir, HttpServletRequest request) throws ClassNotFoundException, FileNotFoundException, JSONException, SQLException, IOException,
      ParseException {
    this.config = ConfigFetcher.getJsonObjectFromPath(configDir);
    this.connect = ConnectionFactory.getConnection(configDir);
    this.request = request;
  }

  public DbHelper(File configDir) throws ClassNotFoundException, FileNotFoundException, JSONException, SQLException, IOException, ParseException {
    this(configDir, null);
  }

  /**
   * Store user info (either update or insert)
   *
   * @param userDetails
   * @throws SQLException
   */
  public void storeUserInfo(UserDetails userDetails) throws SQLException {
    // check if user is already stored
    PreparedStatement preparedStatement = connect.prepareStatement("SELECT UniqueId FROM Users WHERE OpenId = ?");
    preparedStatement.setString(1, userDetails.getOpenId());

    ResultSet result = preparedStatement.executeQuery();
    boolean exists = result.next();
    result.close();
    if (exists) {
      PreparedStatement update = connect.prepareStatement("UPDATE Users SET " + "FirstName = ?, " + "LastName = ?, " + "UniqueId = ? ,"
          + "FullName = ? ," + "NickName = ? ," + "Email = ? ," + "LastLogin = default " + "WHERE OpenId = ?");
      update.setString(1, userDetails.getFirstName());
      update.setString(2, userDetails.getLastName());
      update.setString(3, userDetails.getUniqueId());
      update.setString(4, userDetails.getFullName());
      update.setString(5, userDetails.getNickName());
      update.setString(6, userDetails.getEmail());
      update.setString(7, userDetails.getOpenId());
      update.executeUpdate();
    } else {
      // new user, so insert
      PreparedStatement insert = connect.prepareStatement("INSERT into Users  "
          + "(OpenId, UniqueId, FirstName, LastName, FullName, NickName, Email, LastLogin) " + "values (?, ?, ?, ?, ?, ?, ?, default)",
          Statement.RETURN_GENERATED_KEYS);
      insert.setString(1, userDetails.getOpenId());
      insert.setString(2, userDetails.getUniqueId());
      insert.setString(3, userDetails.getFirstName());
      insert.setString(4, userDetails.getLastName());
      insert.setString(5, userDetails.getFullName());
      insert.setString(6, userDetails.getNickName());
      insert.setString(7, userDetails.getEmail());
      insert.executeUpdate();
      ResultSet rs = insert.getGeneratedKeys();
      int userId = -1;
      if (rs.next()) {
        userId = rs.getInt(1);
      }

      // so we have a new user, store default bookmarks as well
      storeDefaultBookmarks(userId);
    }
  }

  /**
   * get default bookmarks from config file, and insert them for a given user.
   * Ran after a user has his/her first login
   *
   * @param userId
   * @throws SQLException
   */
  private void storeDefaultBookmarks(int userId) throws SQLException {
    if (userId >= 0) {
      ArrayList<Bookmark> bookmarks = Helper.getDefaultBookmarksFromConfig(config);
      PreparedStatement insert = connect.prepareStatement("INSERT into Bookmarks  " + "(Id, UserId, Title, Endpoint, Query) "
          + "values (default, ?, ?, ?, ?)");
      int i = 0;
      for (Bookmark bookmark : bookmarks) {
        i++;
        insert.setInt(1, userId);
        insert.setString(2, bookmark.getTitle());
        insert.setString(3, bookmark.getEndpoint());
        insert.setString(4, bookmark.getQuery());

        insert.addBatch();
        if ((i + 1) % 1000 == 0) {
          insert.executeBatch(); // Execute every 1000 items
        }
      }
      insert.executeBatch();
    }
  }

  /**
   * Get user details, given a certain unique user id string
   *
   * @param userDetails
   * @return
   * @throws SQLException
   * @throws OpenIdException
   */
  public UserDetails getUserDetails(UserDetails userDetails) throws SQLException, OpenIdException {
    PreparedStatement preparedStatement = connect
        .prepareStatement("SELECT Id, FirstName, LastName, FullName, NickName, Email FROM Users WHERE UniqueId = ?");
    preparedStatement.setString(1, userDetails.getUniqueId());
    ResultSet result = preparedStatement.executeQuery();
    if (result.next()) {
      userDetails.setFirstName(result.getString("FirstName"));
      userDetails.setLastName(result.getString("LastName"));
      userDetails.setUserId(result.getInt("Id"));
      userDetails.setFullName(result.getString("FullName"));
      userDetails.setNickName(result.getString("NickName"));
      userDetails.setEmail(result.getString("Email"));
    } else {
      throw new OpenIdException("User not found in database");
    }
    result.close();
    return userDetails;
  }

  /**
   * get bookmarks for this user (unique user id retrieved from cookie)
   *
   * @return
   * @throws SQLException
   */
  public Bookmark[] getBookmarks() throws SQLException {
    int userId = getUserId(HttpCookies.getCookieValue(request, OpenIdServlet.uniqueIdCookieName));
    ArrayList<Bookmark> bookmarks = new ArrayList<Bookmark>();
    PreparedStatement preparedStatement = connect.prepareStatement("SELECT Id, Endpoint, Query, Title FROM Bookmarks WHERE UserId = ?");
    preparedStatement.setInt(1, userId);
    ResultSet result = preparedStatement.executeQuery();
    while (result.next()) {
      Bookmark bookmark = new Bookmark();
      bookmark.setBookmarkId(result.getInt("Id"));
      bookmark.setEndpoint(result.getString("Endpoint"));
      bookmark.setQuery(result.getString("Query"));
      bookmark.setTitle(result.getString("Title"));
      bookmarks.add(bookmark);
    }
    result.close();
    return bookmarks.toArray(new Bookmark[bookmarks.size()]);
  }

  /**
   * handler to close db connection
   */
  public void close() {
    try {
      connect.close();
    } catch (Exception e) {
      // do nothing
    }
  }

  /**
   * get user Id given a unique Id string
   *
   * @param uniqueId
   * @return
   * @throws SQLException
   * @throws OpenIdException
   */
  public int getUserId(String uniqueId) throws SQLException, OpenIdException {
    PreparedStatement preparedStatement = connect.prepareStatement("SELECT Id FROM Users WHERE UniqueId = ?");
    preparedStatement.setString(1, uniqueId);
    int userId = -1;
    ResultSet result = preparedStatement.executeQuery();
    if (result.next()) {
      userId = result.getInt("Id");
      result.close();
    } else {
      result.close();
      throw new OpenIdException("User does not exist in database");
    }
    return userId;
  }
 
  public int getUserId() throws SQLException, OpenIdException {
    return getUserId(HttpCookies.getCookieValue(request, OpenIdServlet.uniqueIdCookieName));
  }

  /**
   * Clear a number of bookmarks from the DB
   *
   * @param bookmarkIds
   * @throws SQLException
   * @throws OpenIdException
   */
  public void clearBookmarks(int... bookmarkIds) throws SQLException, OpenIdException {
    if (bookmarkIds.length > 0) {
      int userId = getUserId(HttpCookies.getCookieValue(request, OpenIdServlet.uniqueIdCookieName));
      Statement statement = connect.createStatement();
      String ids = "";
      boolean hasItemBefore = false;
      for (int bookmarkId : bookmarkIds) {
        if (hasItemBefore)
          ids += ", ";
        ids += bookmarkId;
        hasItemBefore = true;
      }
      String query = "DELETE FROM Bookmarks WHERE UserId = " + userId + " AND Id IN (" + ids + ")";
      statement.execute(query);
      statement.close();
    }
  }

  /**
   * add a set of bookmarks
   *
   * @param bookmarks
   * @throws SQLException
   * @throws OpenIdException
   */
  public void addBookmarks(Bookmark... bookmarks) throws SQLException, OpenIdException {
    int userId = getUserId(HttpCookies.getCookieValue(request, OpenIdServlet.uniqueIdCookieName));
    PreparedStatement insert = connect.prepareStatement("INSERT into Bookmarks  " + "(Id, UserId, Title, Endpoint, Query) "
        + "values (default, ?, ?, ?, ?)");
    int i = 0;
    for (Bookmark bookmark : bookmarks) {
      i++;
      insert.setInt(1, userId);
      insert.setString(2, bookmark.getTitle());
      insert.setString(3, bookmark.getEndpoint());
      insert.setString(4, bookmark.getQuery());

      insert.addBatch();
      if ((i + 1) % 1000 == 0) {
        insert.executeBatch(); // Execute every 1000 items
      }
    }
    insert.executeBatch();

  }

  /**
   * update a set of bookmarks
   *
   * @param bookmarks
   * @throws SQLException
   * @throws OpenIdException
   */
  public void updateBookmarks(Bookmark... bookmarks) throws SQLException, OpenIdException {
    int userId = getUserId(HttpCookies.getCookieValue(request, OpenIdServlet.uniqueIdCookieName));
    PreparedStatement insert = connect.prepareStatement("UPDATE Bookmarks  " + "SET Title = ?, " + "Endpoint = ?, " + "Query = ? " + "WHERE UserId = ? "
        + "AND Id = ?");
    int i = 0;
    for (Bookmark bookmark : bookmarks) {
      i++;

      insert.setString(1, bookmark.getTitle());
      insert.setString(2, bookmark.getEndpoint());
      insert.setString(3, bookmark.getQuery());
      insert.setInt(4, userId);
      insert.setInt(5, bookmark.getBookmarkId());
      insert.addBatch();
      if ((i + 1) % 1000 == 0) {
        insert.executeBatch(); // Execute every 1000 items
      }
    }
    insert.executeBatch();
  }

  public HashMultimap<String, String> getAutocompletions(int endpointId, String partialProperty, int maxResults, FetchType type) throws SQLException {
    return getAutocompletions(endpointId, partialProperty, maxResults, type, null);
  }

  public HashMultimap<String, String> getAutocompletions(int endpointId, String partialProperty, int maxResults, FetchType type, FetchMethod method) throws SQLException {
    HashMultimap<String, String> autocompletions = HashMultimap.create();
    PreparedStatement preparedStatement;
    if (method == null) {
      preparedStatement = connect.prepareStatement("SELECT Uri, Method "
          + "FROM " + type.getPluralCamelCase() + " AS completions "
          + " WHERE completions.EndpointId = ? AND completions.Uri LIKE ? LIMIT ?");
      preparedStatement.setInt(3, maxResults);
    } else {
      preparedStatement = connect.prepareStatement("SELECT Uri, Method "
          + "FROM " + type.getPluralCamelCase() + " AS completions "
          + " WHERE completions.EndpointId = ? AND completions.Uri LIKE ? AND completions.Method = ? LIMIT ?");
      preparedStatement.setString(3, method.get());
      preparedStatement.setInt(4, maxResults);
    }
    preparedStatement.setInt(1, endpointId);
    preparedStatement.setString(2, partialProperty + "%");
    ResultSet result = preparedStatement.executeQuery();
    while (result.next()) {
      autocompletions.put(result.getString("Uri"), result.getString("Method"));
    }
    result.close();
    return autocompletions;
  }

  public int getAutcompletionCount(int endpointId, String partialProperty, FetchType type, FetchMethod method) throws SQLException {
    int count = 0;
    PreparedStatement preparedStatement;
    if (method == null) {
      preparedStatement = connect.prepareStatement("SELECT COUNT(Uri) AS count "
          + " FROM " + type.getPluralCamelCase() + " AS completions"
          + " WHERE completions.EndpointId = ? AND completions.Uri LIKE ?");
    } else {
      preparedStatement = connect.prepareStatement("SELECT COUNT(Uri) AS count "
          + "FROM " + type.getPluralCamelCase() + " AS completions"
          + " WHERE completions.EndpointId = ? AND completions.Uri LIKE ? AND completions.Method = ?");
      preparedStatement.setString(3, method.get());
    }
    preparedStatement.setInt(1, endpointId);
    preparedStatement.setString(2, partialProperty + "%");
    ResultSet result = preparedStatement.executeQuery();
    result.next();// only 1 result;
    count = result.getInt("count");
    result.close();
    return count;
  }
 
  public Map<String, Boolean> areAutocompletionsAdded(int endpointId, Set<String> checkUris, FetchType type, FetchMethod method) throws SQLException {
    HashMap<String, Boolean> addedProperties = new HashMap<String, Boolean>();
    PreparedStatement preparedStatement = connect.prepareStatement("SELECT Uri FROM "
          + type.getPluralCamelCase() + " AS completions "
           + "WHERE completions.EndpointId = ? AND completions.Uri LIKE ? AND completions.Method = ?");
    for (String uri: checkUris) {
      preparedStatement.setInt(1, endpointId);
      preparedStatement.setString(2, uri.trim());
      preparedStatement.setString(3, method.get());
      ResultSet result = preparedStatement.executeQuery();
      addedProperties.put(uri, result.next());
    }
    return addedProperties;
  }

  public void setAutocompletionLog(int endpointId, FetchStatus status, FetchType fetchType, String message, boolean pagination) throws SQLException {
    PreparedStatement ps;
    if (message != null) {
      String sql = "insert into CompletionsLog (EndpointId, Type, Status, Pagination, Message) values (?, ?, ?, ?, ?)";
      ps = connect.prepareStatement(sql);
      ps.setString(5, message);
    } else {
      String sql = "insert into CompletionsLog (EndpointId, Type, Status, Pagination) values (?, ?, ?, ?)";
      ps = connect.prepareStatement(sql);
    }
    ps.setInt(1, endpointId);
    ps.setString(2, fetchType.getSingular());
    ps.setString(3, status.get());
    ps.setBoolean(4, pagination);
    ps.execute();
  }
 
  public void setAutocompletionLog(int endpointId, FetchStatus status, FetchType fetchType, String message) throws SQLException {
    setAutocompletionLog(endpointId, status, fetchType, message, false);
  }
  public void setAutocompletionLog(int endpointId, FetchStatus status, FetchType fetchType) throws SQLException {
    setAutocompletionLog(endpointId, status, fetchType, null);
  }
 
  public void clearPreviousAutocompletionFetches(int endpointId, FetchMethod method, FetchType fetchType) throws SQLException {
    String sql = "DELETE FROM " + fetchType.getPluralCamelCase() + ""
        + " WHERE Method = ? AND EndpointId = ?";
    PreparedStatement ps = connect.prepareStatement(sql);
    System.out.println(sql);
    ps.setString(1, method.get());
    ps.setInt(2, endpointId);
    ps.execute();
  }
 
  public void storeCompletionFetchesFromQueryResult(int endpointId, FetchType type, FetchMethod method, com.hp.hpl.jena.query.ResultSet resultSet, String sparqlKeyword) throws SQLException, PossiblyNeedPaging {
    storeCompletionFetchesFromQueryResult(endpointId, type, method, resultSet, sparqlKeyword, false);
  }
  public void storeCompletionFetchesFromQueryResult(int endpointId, FetchType type, FetchMethod method, com.hp.hpl.jena.query.ResultSet resultSet, String sparqlKeyword, boolean bypassPaginationCheck) throws SQLException, PossiblyNeedPaging {
    String sql = "insert into " + type.getPluralCamelCase() + " (Uri, EndpointId, Method) values (?, ?, ?)";
    PreparedStatement ps = connect.prepareStatement(sql);

    final int batchSize = 1000;
    int count = 0;
    while (resultSet.hasNext()) {
      QuerySolution querySolution = resultSet.next();
      RDFNode rdfNode = querySolution.get(sparqlKeyword);
     
      ps.setString(1, rdfNode.asResource().getURI().trim());
      ps.setInt(2, endpointId);
      ps.setString(3, method.get());
      ps.addBatch();
      if (++count % batchSize == 0) {
        System.out.println(count + " done");
        ps.executeBatch();
      }
    }
    System.out.println("looping done");
    ps.executeBatch(); // insert remaining records
    if (!bypassPaginationCheck && PropertiesFetcher.doubtfullResultSet(count)) {
      PossiblyNeedPaging pagingException = new PossiblyNeedPaging();
      pagingException.setQueryCount(count);
      throw pagingException;
    }
  }
 
  public void storeAutocompletionsFromQueryAnalysis(int endpointId, FetchType type, FetchMethod method, Set<String> properties) throws SQLException {
    String sql = "insert into " + type.getPluralCamelCase() + " (Uri, EndpointId, Method) values (?, ?, ?)";
    PreparedStatement ps = connect.prepareStatement(sql);

    final int batchSize = 1000;
    int count = 0;
    for (String property: properties) {
      ps.setString(1, property.trim());
      ps.setInt(2, endpointId);
      ps.setString(3, method.get());
      ps.addBatch();
      if (++count % batchSize == 0) {
        ps.executeBatch();
      }
    }
    ps.executeBatch(); // insert remaining records
  }
  public void storeCompletionFetchesFromLocalhost(int endpointId, FetchType type, FetchMethod method, JSONArray completions) throws SQLException, JSONException {
    String sql = "insert into " + type.getPluralCamelCase() + " (Uri, EndpointId, Method) values (?, ?, ?)";
    PreparedStatement ps = connect.prepareStatement(sql);
   
    final int batchSize = 1000;
    int count = 0;
    for (int i = 0; i < completions.length(); i++) {
      ps.setString(1, completions.getString(i).trim());
      ps.setInt(2, endpointId);
      ps.setString(3, method.get());
      ps.addBatch();
      if (++count % batchSize == 0) {
        ps.executeBatch();
      }
    }
    ps.executeBatch(); // insert remaining records
  }
 
  public boolean autocompletionFetchingEnabled(int endpointId, FetchType type, FetchMethod method) throws SQLException {
    String sql = "SELECT * "
        + "FROM DisabledCompletionEndpoints AS disabledEndpoints "
        + "WHERE disabledEndpoints.EndpointId = ? AND disabledEndpoints.Method = ? AND disabledEndpoints.Type = ?";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
    ps.setString(2, method.get());
    ps.setString(3, type.getSingular());
    ResultSet result = ps.executeQuery();
    boolean disabled = result.next();// only 1 result;
    result.close();
    return !disabled;
  }
 
  public HashMultimap<String, FetchMethod> getDisabledEndpointsForCompletionsFetching(FetchType type) throws SQLException {
    String sql = "SELECT DISTINCT endpoints.Endpoint, disabledEndpoints.Method "
        + "FROM DisabledCompletionEndpoints AS disabledEndpoints, CompletionEndpoints AS endpoints "
        + "WHERE disabledEndpoints.EndpointId = endpoints.Id AND disabledEndpoints.Type = ?";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setString(1, type.getSingular());
    ResultSet result = ps.executeQuery();
    HashMultimap<String, FetchMethod> endpoints = HashMultimap.create();
    while (result.next()) {
      endpoints.put(result.getString("Endpoint"), Util.stringToFetchMethod(result.getString("Method")));
    }
    result.close();
    return endpoints;
  }
 
  /**
   * ALL last x should not have status succesful
   * @param endpointId
   * @param numberOfFetchesToCheck
   * @return
   * @throws SQLException
   */
  public boolean lastFetchesFailed(int endpointId, FetchType type, int numberOfFetchesToCheck) throws SQLException {
    String sql = "SELECT * "
        + "FROM CompletionsLog AS log "
        + "WHERE log.EndpointId = ? AND log.Type = ? ORDER BY Time DESC LIMIT ?";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
//    ps.setString(2, FetchStatus.FETCHING.get());//we don't want the fetching status in there. Only the failed and succeeded ones
    ps.setString(2, type.getSingular());
    ps.setInt(3, numberOfFetchesToCheck);
    ResultSet result = ps.executeQuery();
    int count = 0;
    boolean allFailed = true;
    while (result.next()) {
      count ++;
      if (!result.getString("Status").equals(FetchStatus.FAILED)) {
        allFailed = false;
        break;
      }
    }
    if (count != numberOfFetchesToCheck) {
      allFailed = false;
    }
    result.close();
    return allFailed;
  }
 
  public boolean lastFetchSuccesful(int endpointId, FetchType type) throws SQLException {
    String sql = "SELECT * "
        + "FROM CompletionsLog AS log "
        + "WHERE log.EndpointId = ? AND log.Type = ? ORDER BY Time DESC LIMIT 1";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
    ps.setString(2, type.getSingular());
    ResultSet result = ps.executeQuery();
    boolean lastFetchSuccesful = false;
    if (result.next()) {
      if (result.getString("Status").equals(FetchStatus.SUCCESSFUL.get())) {
        lastFetchSuccesful = true;
      }
    }
    result.close();
    return lastFetchSuccesful;
  }
 
  /**
   * Check whether we are still fetching properties or classes for an endpoint
   * @param endpointId
   * @param fetchType
   * @param timeFrameSearch The number of minutes which we will check (e.g. only the last 5 minutes?).
   * If the status is 'fetching', but was logged 2 months ago, we don't want to show it as 'still fetching'
   * @return
   * @throws SQLException
   */
  public boolean stillFetching(int endpointId, FetchType fetchType, int timeFrameSearch) throws SQLException {
    String sql = "SELECT Status "
        + "FROM CompletionsLog AS log "
        + "WHERE log.EndpointId = ? AND TIMESTAMPDIFF(minute,log.Time,NOW()) <= ? AND log.Type = ? ORDER BY log.Time DESC LIMIT 1";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
    ps.setInt(2, timeFrameSearch);
    ps.setString(3, fetchType.getSingular());
    ResultSet result = ps.executeQuery();
    boolean stillFetching = false;
    while (result.next()) {
      if (result.getString("Status").equals(FetchStatus.FETCHING)) {
        stillFetching = true;
      }
    }
    result.close();
    return stillFetching;
  }
 
  /**
   * Get the number of times we have a 'failed' status in our logs for all endpoints.
   * @param type
   * @return
   * @throws SQLException
   */
  public Map<String, Integer> getFailCountForEndpoints(FetchType type) throws SQLException {
    int userId = -1;
    try {
      userId = getUserId();
    } catch (OpenIdException e) {
      //do nothing, just use the default (non-existing) userId
    }
    String sql = "SELECT endpoints.Endpoint, COUNT( endpoints.Endpoint ) AS NumberFails " +
        "FROM CompletionsLog AS log"
        + " JOIN CompletionEndpoints AS endpoints on endpoints.Id = log.EndpointId " +
        "WHERE log.STATUS =  ? "
        + "AND log.Type = ? " +
        " AND (endpoints.UserId IS NULL OR endpoints.userId = ?) " +
        "GROUP BY endpoints.Endpoint";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setString(1, FetchStatus.FAILED.get());
    ps.setString(2, type.getSingular());
    ps.setInt(3, userId);
    ResultSet result = ps.executeQuery();
    Map<String, Integer> endpoints = new HashMap<String, Integer>();
    while (result.next()) {
      endpoints.put(result.getString("Endpoint"), result.getInt("NumberFails"));
    }
    return endpoints;
  }
 
  /**
   * List all endpoints for which we have autocompletions
   *
   * @param fetchType
   * @return
   * @throws SQLException
   */
  public HashMultimap<String, FetchMethod> getEndpointsWithAutocompletions(FetchType fetchType) throws SQLException {
    int userId = -1;
    try {
      userId = getUserId();
    } catch (OpenIdException e) {
      //do nothing, just use the default (non-existing) userId
    }
    HashMultimap<String, FetchMethod> endpoints = HashMultimap.create();
    String sql = "SELECT DISTINCT endpoints.Endpoint, completions.Method "
        + "FROM " + fetchType.getPluralCamelCase() + " AS completions, CompletionEndpoints AS endpoints  "
        + "WHERE completions.EndpointId = endpoints.Id AND (endpoints.UserId IS NULL OR endpoints.UserId = ?)";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, userId);
    ResultSet result = ps.executeQuery();
    while (result.next()) {
      endpoints.put(result.getString("Endpoint"), Util.stringToFetchMethod(result.getString("Method")));
    }
    return endpoints;
  }
 
 
 
  public AutocompletionsInfo getAutocompletionInfo() throws SQLException {
    AutocompletionsInfo completionsInfo = new AutocompletionsInfo();
   
    HashMultimap<String, FetchMethod> endpointsWithCompletions = getEndpointsWithAutocompletions(FetchType.PROPERTIES);
    for (String endpoint: endpointsWithCompletions.keySet()) {
      for (FetchMethod method: endpointsWithCompletions.get(endpoint)) {
        completionsInfo.getOrCreateEndpointInfo(endpoint).getPropertyInfo().setHasCompletions(method, true);
      }
    }
    endpointsWithCompletions = getEndpointsWithAutocompletions(FetchType.CLASSES);
    for (String endpoint: endpointsWithCompletions.keySet()) {
      for (FetchMethod method: endpointsWithCompletions.get(endpoint)) {
        completionsInfo.getOrCreateEndpointInfo(endpoint).getClassInfo().setHasCompletions(method, true);
      }
    }
    for (Entry<String, Integer> entry: getFailCountForEndpoints(FetchType.PROPERTIES).entrySet()) {
      completionsInfo.getOrCreateEndpointInfo(entry.getKey()).getPropertyInfo().setFetchFailCount(entry.getValue());
    }
    for (Entry<String, Integer> entry: getFailCountForEndpoints(FetchType.CLASSES).entrySet()) {
      completionsInfo.getOrCreateEndpointInfo(entry.getKey()).getClassInfo().setFetchFailCount(entry.getValue());
    }
    HashMultimap<String, FetchMethod> disabledPropEndpoints = getDisabledEndpointsForCompletionsFetching(FetchType.PROPERTIES);
    for (String endpoint: disabledPropEndpoints.keySet()) {
      for (FetchMethod method: disabledPropEndpoints.get(endpoint)) {
        if (method == FetchMethod.QUERY_ANALYSIS) {
          completionsInfo.getOrCreateEndpointInfo(endpoint).getPropertyInfo().setQueryAnalysisEnabled(false);
        } else if (method == FetchMethod.QUERY_RESULTS) {
          completionsInfo.getOrCreateEndpointInfo(endpoint).getPropertyInfo().setQueryResultsFetchingEnabled(false);
        }
      }
    }
    HashMultimap<String, FetchMethod> disabledClassEndpoints = getDisabledEndpointsForCompletionsFetching(FetchType.CLASSES);
    for (String endpoint: disabledClassEndpoints.keySet()) {
      for (FetchMethod method: disabledClassEndpoints.get(endpoint)) {
        if (method == FetchMethod.QUERY_ANALYSIS) {
          completionsInfo.getOrCreateEndpointInfo(endpoint).getClassInfo().setQueryAnalysisEnabled(false);
        } else if (method == FetchMethod.QUERY_RESULTS) {
          completionsInfo.getOrCreateEndpointInfo(endpoint).getClassInfo().setQueryResultsFetchingEnabled(false);
        }
      }
    }
    return completionsInfo;
  }
 
 
  public JSONArray getPersonalAutocompletionsInfo() throws OpenIdException, SQLException, JSONException {
    int userId = getUserId();
    JSONArray propDataArray = getPersonalAutocompletionsInfo(userId, FetchType.PROPERTIES);
    JSONArray classDataArray = getPersonalAutocompletionsInfo(userId, FetchType.CLASSES);
    //need to concatenate both
    for (int i = 0; i < classDataArray.length(); i++) {
      propDataArray.put(classDataArray.get(i));
    }
    return propDataArray;
  }
 
  private JSONArray getPersonalAutocompletionsInfo(int userId, FetchType type) throws JSONException, OpenIdException, SQLException {
   
    String sql = "SELECT Method, endpoints.Endpoint, COUNT( Method ) AS Count " +
        "FROM CompletionEndpoints AS endpoints, " + type.getPluralCamelCase() + " " +
        "WHERE endpoints.UserId = ? " +
        "AND " + type.getPluralCamelCase() + ".EndpointId = endpoints.Id " +
        "GROUP BY " + type.getPluralCamelCase() + ".Method,  " + type.getPluralCamelCase() + ".EndpointId" +
        "";
    System.out.println(sql);
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, userId);
    ResultSet result = ps.executeQuery();
    HashMap<String, JSONObject> completionsInfo = new HashMap<String, JSONObject>();
    while (result.next()) {
      String endpoint = result.getString("Endpoint");
      if (completionsInfo.containsKey(endpoint)) {
        //only need to add the 'method count' thing (rest is already added to object;
        JSONObject dataObj = completionsInfo.get(endpoint);
        dataObj.put(result.getString("Method"), result.getString("Count"));
      } else {
        JSONObject dataObj = new JSONObject();
        dataObj.put(AutocompletionConfigCols.TYPE.getKey(), type.getSingular());
        dataObj.put(AutocompletionConfigCols.ENDPOINT.getKey(), endpoint);
        dataObj.put(result.getString("Method"), result.getString("Count"));
        completionsInfo.put(endpoint, dataObj);
      }
     
    }
   
   
    JSONArray dataArray = new JSONArray(completionsInfo.values());
    return dataArray;
  }
  /**
   * Flag the 'accessibility' (i.e. via http from the YASGUI server) status of an endpoint
   * @param endpointId
   * @param accessible
   * @throws SQLException
   */
  public void setEndpointAccessible(int endpointId, boolean accessible) throws SQLException {
    String sql = "INSERT INTO AccessibleEndpoints (`EndpointId`, `Accessible`) VALUES (?, ?)";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
    ps.setBoolean(2, accessible);
    ps.executeUpdate();
  }
 
 
  /**
   * Retrieve the endpoint ID for a given endpoint string. If the endpoint does not exist in db, create a new id
   * @param endpoint
   * @return
   * @throws SQLException
   */
  public int getEndpointId(String endpoint, EndpointPrivateFlag privateFlag) throws SQLException, EndpointIdException {
    endpoint = endpoint.trim();
    String selectSql = "SELECT Id FROM CompletionEndpoints WHERE Endpoint = ? ";
    boolean addUserId = false;
    switch (privateFlag) {
          case OWN:
            addUserId = true;
        selectSql += " AND UserId = ?";
        break;
          case OWN_AND_PUBLIC :
            addUserId = true;
            selectSql +=  " AND (UserId IS NULL OR UserId = ?)";
            break;
          case PUBLIC:
            selectSql += "AND UserId IS NULL";
            break;
          case EVERYTHING:
          default: //nothing to add
      }
    PreparedStatement ps = connect.prepareStatement(selectSql);
    ps.setString(1, endpoint);
   
    if (addUserId) {
      try {
        ps.setInt(2, getUserId());
      } catch (OpenIdException e) {
        //user is not logged in. just use -1 (i.e., id which is never used)
        ps.setInt(2, -1);
      }
    }
    ResultSet result = ps.executeQuery();
    int endpointId;
    if (result.next()) {
      endpointId = result.getInt("Id");
    } else {
      throw new EndpointIdException("No endpoint ID found in DB for provided endpoint string " + endpoint);
    }
    return endpointId;
  }
 
  public int generateIdForEndpoint(String endpoint) throws SQLException, EndpointIdException {
    AccessibilityStatus accessibleStatus = Helper.checkEndpointAccessibility(endpoint);
    return generateIdForEndpoint(endpoint, accessibleStatus);
  }
 
  public int generateIdForEndpoint(String endpoint, AccessibilityStatus accessibilityStatus) throws SQLException, EndpointIdException {
    int userId = -1;
    try {
      userId = getUserId();
    } catch (OpenIdException e) {
      //user nog logged in
    }
    String insertSql = "INSERT INTO CompletionEndpoints (Endpoint, UserId) VALUES (?, ?)";
    PreparedStatement psUpdate = connect.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
    psUpdate.setString(1, endpoint);
    if (accessibilityStatus == AccessibilityStatus.ACCESSIBLE) {
      psUpdate.setNull(2, Types.INTEGER);
    } else if (userId >= 0){
      //we need a user id for this one!
      psUpdate.setInt(2, userId);
    } else {
      throw new EndpointIdException("Unable to generate endpoint ID for endpoint " + endpoint + ". Is the user logged in?");
    }
    psUpdate.executeUpdate();
    ResultSet keys = psUpdate.getGeneratedKeys();
    keys.next();
    return keys.getInt(1);
  }
 
 
  public void setEndpointAccessible(int endpointId, AccessibilityStatus accessible) throws SQLException {
    setEndpointAccessible(endpointId, accessible == AccessibilityStatus.ACCESSIBLE);
  }
 
  /**
   * Checks whether this endpoint is accessible via http from the YASGUI server
   *
   * @param endpointId
   * @param allowActiveCheck
   * @return
   * @throws SQLException
   */
  public AccessibilityStatus isEndpointAccessible(int endpointId) throws SQLException {
    String sql = "SELECT `Accessible` "
        + "FROM AccessibleEndpoints  "
        + "WHERE EndpointId = ? ORDER BY Time LIMIT 1 ";
    PreparedStatement ps = connect.prepareStatement(sql);
    ps.setInt(1, endpointId);
    ResultSet result = ps.executeQuery();
    AccessibilityStatus accessibleStatus = AccessibilityStatus.UNCHECKED;
    if (result.next()) {
      if (result.getBoolean("Accessible")) {
        accessibleStatus = AccessibilityStatus.ACCESSIBLE;
      } else {
        accessibleStatus = AccessibilityStatus.INACCESSIBLE;
      }
    }
    return accessibleStatus;
  }


  public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException, JSONException, SQLException, IOException, ParseException {
    DbHelper dbHelper = new DbHelper(new File("src/main/webapp/"));
    if (dbHelper.lastFetchSuccesful(12, FetchType.PROPERTIES)) {
      System.out.println("accessible");
    } else {
      System.out.println("not accessible");
    }
//    dbHelper.setEndpointAccessible("httpsdf", true);
    System.out.println("" + dbHelper.getEndpointId("htddtpdsdf",EndpointPrivateFlag.EVERYTHING));
//    AutocompletionsInfo info = dbHelper.getAutocompletionInfo();
//    System.out.println(info.toString());
//    for (String endpoint: dbHelper.getDisabledEndpointsForCompletionsFetching(FetchType.CLASSES, FetchMethod.QUERY_ANALYSIS)) {
//      System.out.println(endpoint);
//    }
//    System.out.println((dbHelper.lastFetchesFailed("http://dbpedia.org/sparql", FetchType.PROPERTIES, 5)? "still fetching":"done fetching"));
  }




}
TOP

Related Classes of com.data2semantics.yasgui.server.db.DbHelper

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.