All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencastproject.external.util.statistics.QueryUtils Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License
 * at:
 *
 *   http://opensource.org/licenses/ecl2.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package org.opencastproject.external.util.statistics;

import org.opencastproject.statistics.api.DataResolution;
import org.opencastproject.statistics.api.StatisticsProvider;
import org.opencastproject.statistics.api.StatisticsService;
import org.opencastproject.statistics.api.TimeSeries;
import org.opencastproject.statistics.api.TimeSeriesProvider;
import org.opencastproject.statistics.export.api.DetailLevel;

import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public final class QueryUtils {

  private QueryUtils() {
  }

  public static class Query {
    private StatisticsProvider provider;
    private Parameters parameters;

    Query(StatisticsProvider provider, Parameters parameters) {
      this.provider = provider;
      this.parameters = parameters;
    }

    public StatisticsProvider getProvider() {
      return provider;
    }

    public Parameters getParameters() {
      return parameters;
    }
  }

  public static class QueryResult {
    private Query query;
    protected JSONObject data;

    QueryResult(Query query) {
      this.query = query;
      this.data = new JSONObject();
    }

    public JSONObject getData() {
      return data;
    }

    public JSONObject get() {
      JSONObject result = new JSONObject();
      // Add provider information
      JSONObject providerObj = new JSONObject();
      providerObj.put("identifier", query.getProvider().getId());
      providerObj.put("type", StatisticsProviderUtils.typeOf(query.getProvider()));
      providerObj.put("resourceType", ResourceTypeUtils.toString(query.getProvider().getResourceType()));
      result.put("provider", providerObj);

      // Add parameter information
      result.put("parameters", query.getParameters().get());

      // Add query result data
      result.put("data", getData());
      return result;
    }
  }

  public static class QueryResultTimeSeries extends QueryResult {

    QueryResultTimeSeries(Query query, TimeSeries timeseries) {
      super(query);
      data.put("labels", timeseries.getLabels());
      data.put("values", timeseries.getValues());
      if (timeseries.getTotal().isPresent()) {
        data.put("total", timeseries.getTotal().getAsDouble());
      }
    }
  }

  public static class Parameters {

    private String resourceId;
    private JSONObject raw;

    Parameters(String resourceId, JSONObject raw) {
      this.resourceId = resourceId;
      this.raw = raw;
    }

    public String getResourceId() {
      return resourceId;
    }

    public JSONObject get() {
      return raw;
    }

    void validate() { }
  }

   public static class TimeSeriesParameters extends Parameters {

    private Instant from;
    private Instant to;
    private DataResolution dataResolution;

    TimeSeriesParameters(String resourceId, JSONObject raw) {
      super(resourceId, raw);
    }

    public Instant getFrom() {
      return from;
    }

    void setFrom(String from) {
      try {
        this.from = Instant.parse(from);
      } catch (DateTimeParseException e) {
        throw new IllegalArgumentException("Parameter 'from' not in ISO 8601 UTC format");
      }
    }

    public Instant getTo() {
      return to;
    }

    void setTo(String to) {
      try {
        this.to = Instant.parse(to);
      } catch (DateTimeParseException e) {
        throw new IllegalArgumentException("Parameter 'to' not in ISO 8601 UTC format");
      }
    }

    public DataResolution getDataResolution() {
      return dataResolution;
    }

    void setDataResolution(String dataResolution) {
      Optional resolution = DataResolutionUtils.fromString(dataResolution);
      if (!resolution.isPresent()) {
        throw new IllegalArgumentException("Illegal value for 'resolution'");
      }
      this.dataResolution = resolution.get();
    }

    void validate() {
      super.validate();
      if (this.to.compareTo(this.from) <= 0) {
        throw new IllegalArgumentException("'from' date must be before 'to' date");
      }
    }
  }

  public static class ExportParameters extends TimeSeriesParameters {

    private DetailLevel detailLevel;

    ExportParameters(String resourceId, JSONObject raw) {
      super(resourceId, raw);
    }

    void setDetailLevel(String detailLevel) {
      Optional level = DetailLevelUtils.fromString(detailLevel);
      if (!level.isPresent()) {
        throw new IllegalArgumentException("Illegal value for 'detailLevel'");
      }
      this.detailLevel = level.get();
    }

    public DetailLevel getDetailLevel() {
      return this.detailLevel;
    }
  }

  public static List parse(String queryString, StatisticsService statisticsService) {

    if (StringUtils.isBlank(queryString)) {
      throw new IllegalArgumentException("No query data provided");
    }

    JSONParser parser = new JSONParser();
    JSONArray queriesJson;
    try {
      queriesJson = (JSONArray) parser.parse(queryString);
    } catch (ParseException e) {
      throw new IllegalArgumentException("JSON malformed");
    }

    List queries = new ArrayList<>();

    queriesJson.forEach(item -> {
        Query query = parseQuery((JSONObject) item, statisticsService);
        queries.add(query);
    });

    return queries;
  }

  public static Query parseQuery(String queryString, StatisticsService statisticsService) {
    if (StringUtils.isBlank(queryString)) {
      throw new IllegalArgumentException("No query data provided");
    }

    JSONParser parser = new JSONParser();
    JSONObject queryJson;
    try {
      queryJson = (JSONObject) parser.parse(queryString);
    } catch (ParseException e) {
      throw new IllegalArgumentException("JSON malformed");
    }
    return parseQuery(queryJson, statisticsService);

  }

  private static Query parseQuery(JSONObject queryJson, StatisticsService statisticsService) {

    // Get the mandatory provider identifier
    JSONObject providerJson = (JSONObject) queryJson.get("provider");
    String providerId = getField(providerJson, "identifier", "Identifier of provider is missing");

    Optional provider = statisticsService.getProvider(providerId);
    if (!provider.isPresent()) {
      throw new IllegalArgumentException("Provider not found");
    }

    // Get the query parameters
    JSONObject parametersJson = (JSONObject) queryJson.get("parameters");
    Parameters parameters = parseParameters(parametersJson, provider.get());

    return new Query(provider.get(), parameters);
  }

  public static Parameters parseParameters(JSONObject parametersJson, StatisticsProvider provider) {

    Parameters result;

    String resourceId = getField(parametersJson, "resourceId", "Parameter 'resourceId' is missing");

    // The other parameters are specific to statistics provider implementations
    if (provider instanceof TimeSeriesProvider) {
      TimeSeriesParameters p;
      if (parametersJson.containsKey("detailLevel")) {
        p = new ExportParameters(resourceId, parametersJson);
        ((ExportParameters)p).setDetailLevel(getField(parametersJson, "detailLevel", "Parameter 'detailLevel' is misisng"));
      } else {
        p = new TimeSeriesParameters(resourceId, parametersJson);
      }
      p.setFrom(getField(parametersJson, "from", "Parameter 'from' is missing"));
      p.setTo(getField(parametersJson, "to", "Parameter 'to' is missing"));
      p.setDataResolution(getField(parametersJson, "dataResolution", "Parameter 'dataResolution' is missing"));
      result = p;
    } else {
      result = new Parameters(resourceId, parametersJson);
      // Currently, we don't support other parameter types
    }
    result.validate();
    return result;
  }

  private static String getField(JSONObject object, String field, String exceptionMessage) {
    String value;
    try {
      value = (String) object.get(field);
    } catch (Exception e) {
      throw new IllegalArgumentException(exceptionMessage);
    }
    if (StringUtils.isBlank(value)) {
      throw new IllegalArgumentException(exceptionMessage);
    }
    return value;
  }

  public static JSONObject execute(Query query) {
    QueryResult result;
    StatisticsProvider provider = query.getProvider();
    if (provider instanceof TimeSeriesProvider) {
      TimeSeriesParameters p = (TimeSeriesParameters) query.getParameters();
      TimeSeriesProvider tsp = (TimeSeriesProvider) provider;
      TimeSeries timeseries = tsp.getValues(p.getResourceId(), p.getFrom(), p.getTo(), p.getDataResolution(),
          ZoneId.systemDefault());
      result = new QueryResultTimeSeries(query, timeseries);
    } else {
      result = new QueryResult(query);
    }
    return result.get();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy