/*
* Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0
*
* 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.rakam.analysis;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.rakam.report.QueryExecution;
import org.rakam.report.QueryResult;
import org.rakam.report.realtime.AggregationType;
import org.rakam.server.http.annotations.ApiParam;
import org.rakam.util.RakamException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import static com.google.common.base.Preconditions.checkNotNull;
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static org.rakam.report.realtime.AggregationType.COUNT;
import static org.rakam.util.ValidationUtil.checkCollection;
public interface EventExplorer
{
QueryExecution analyze(String project, List<String> collections, Measure measureType, Reference grouping, Reference segment, String filterExpression, Instant startDate, Instant endDate);
CompletableFuture<QueryResult> getEventStatistics(String project, Optional<Set<String>> collections, Optional<String> dimension, Instant startDate, Instant endDate);
Map<String, List<String>> getExtraDimensions(String project);
default String getIntermediateForApproximateUniqueFunction()
{
throw new UnsupportedOperationException();
}
default String getFinalForApproximateUniqueFunction()
{
throw new UnsupportedOperationException();
}
enum TimestampTransformation
{
HOUR_OF_DAY("Date category", "Hour of day"),
DAY_OF_MONTH("Date category", "Day of month"),
WEEK_OF_YEAR("Date category", "Week of year"),
MONTH_OF_YEAR("Date category", "Month of year"),
QUARTER_OF_YEAR("Date category", "Quarter of year"),
DAY_PART("Date category", "Day part"),
DAY_OF_WEEK("Date category", "Day of week"),
HOUR("Date period", "Hour"),
DAY("Date period", "Day"), WEEK("Date period", "Week"),
MONTH("Date period", "Month"), YEAR("Date period", "Year");
private final String prettyName;
private final String category;
TimestampTransformation(String category, String name)
{
this.prettyName = name;
this.category = category;
}
@JsonCreator
public static TimestampTransformation fromString(String key)
{
try {
return key == null ? null : valueOf(key.toUpperCase());
}
catch (IllegalArgumentException e) {
throw new RakamException("Invalid date range value: " + key, BAD_REQUEST);
}
}
public String getPrettyName()
{
return prettyName;
}
public String getCategory()
{
return category;
}
public static Optional<TimestampTransformation> fromPrettyName(String name)
{
for (TimestampTransformation transformation : values()) {
if (transformation.getPrettyName().equals(name)) {
return Optional.of(transformation);
}
}
return Optional.empty();
}
}
class Measure
{
public final String column;
public final AggregationType aggregation;
@JsonCreator
public Measure(@ApiParam(value = "column", required = false) String column,
@ApiParam("aggregation") AggregationType aggregation)
{
if (column == null && aggregation != COUNT) {
throw new IllegalArgumentException("measure column is required if aggregation is not COUNT");
}
this.column = column;
this.aggregation = Objects.requireNonNull(aggregation, "aggregation is null");
}
}
class Reference
{
public final ReferenceType type;
public final String value;
@JsonCreator
public Reference(@ApiParam("type") ReferenceType type,
@ApiParam("value") String value)
{
this.type = checkNotNull(type, "type is null");
this.value = checkNotNull(value, "value is null");
}
}
enum ReferenceType
{
COLUMN, REFERENCE;
@JsonCreator
public static ReferenceType get(String name)
{
return valueOf(name.toUpperCase());
}
@JsonProperty
public String value()
{
return name();
}
}
class OLAPTable
{
public final Set<String> collections;
public final Set<String> dimensions;
public final Set<AggregationType> aggregations;
public final Set<String> measures;
public final String tableName;
@JsonCreator
public OLAPTable(@ApiParam("collections") Set<String> collections,
@ApiParam("dimensions") Set<String> dimensions,
@ApiParam("aggregations") Set<AggregationType> aggregations,
@ApiParam("measures") Set<String> measures,
@ApiParam("tableName") String tableName)
{
checkCollection(tableName);
if (measures.isEmpty()) {
throw new RakamException("There must be at least one measure", BAD_REQUEST);
}
if(collections.isEmpty()) {
throw new RakamException("There must be at least one collection", BAD_REQUEST);
}
this.collections = collections;
this.dimensions = dimensions;
this.aggregations = aggregations;
this.measures = measures;
this.tableName = tableName;
}
}
}