/* * Copyright (c) 2013 Google Inc. * * 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 com.google.cloud.backend.android; import android.util.Base64; import com.google.cloud.backend.android.mobilebackend.model.QueryDto; import com.google.gson.Gson; /** * A query object to execute it with {@link CloudBackend}. See * {@link CloudBackendTest#testList()} for detailed usage. * */ public class CloudQuery { private static final Gson gson = new Gson(); /** * An enum for specifying sort order of the query. */ public enum Order { ASC, DESC }; /** * An enum to specify scope of query. */ public enum Scope { /** * PAST: query will be executed only for the entities that have been stored * in past, and will not be executed when the entities will be updated in * future. */ PAST, /** * FUTURE: query will be executed only when entities are updated in future, * and will not be executed against the current entities. */ FUTURE, /** * FUTURE_AND_PAST: query will be executed for the current entities and * future updates. */ FUTURE_AND_PAST } private F filter; private final QueryDto queryDto; /** * Creates an instance of {@link CloudQuery}. * * @param kindName * Name of the kind that this query will execute with. */ public CloudQuery(String kindName) { this.queryDto = new QueryDto(); this.queryDto.setKindName(kindName); this.queryDto.setScope(Scope.PAST.name()); } /** * Creates an instance of {@link CloudQuery} from the values of the specified * CloudQuery. queryDto field will be deep copied, and filter field will be * shallow copied. * * @param cq * {@link CloudQuery} that will be used for instantiation. */ public CloudQuery(CloudQuery cq) { this.queryDto = copyQueryDto(cq.queryDto); this.filter = cq.filter; } private QueryDto copyQueryDto(QueryDto cq) { QueryDto ncq = new QueryDto(); ncq.setFilterDto(cq.getFilterDto()); ncq.setKindName(cq.getKindName()); ncq.setLimit(cq.getLimit()); ncq.setQueryId(cq.getQueryId()); ncq.setRegId(cq.getRegId()); ncq.setScope(cq.getScope()); ncq.setSortAscending(cq.getSortAscending()); ncq.setSortedPropertyName(cq.getSortedPropertyName()); ncq.setSubscriptionDurationSec(cq.getSubscriptionDurationSec()); return ncq; } /** * Sets registration id. * * @param regId */ protected void setRegId(String regId) { this.queryDto.setRegId(regId); } /** * Returns a kind name of this query. * * @return kind name */ public String getKindName() { return this.queryDto.getKindName(); } /** * Set Sort property name and sort order to this query. * * @param propertyName * Name of the target name. * @param sortOrder * {@link Order} of this sort. * @return {@link CloudQuery} */ public CloudQuery setSort(String propertyName, Order sortOrder) { this.queryDto.setSortedPropertyName(propertyName); this.queryDto.setSortAscending(sortOrder == Order.ASC); return this; } /** * Set Limit number on the result set to this query. * * @param limit * Max number of lines for the query result set. * @return {@link CloudQuery} */ public CloudQuery setLimit(int limit) { this.queryDto.setLimit(limit); return this; } /** * Creates a {@link QueryDto} for this CloudQuery. * * @return {@link QueryDto} for this CloudQuery */ protected QueryDto convertToQueryDto() { // generate FilterDto if (filter != null) { this.queryDto.setFilterDto(filter.getFilterDto()); } return this.queryDto; } /** * Returns {@link F} (filter) for this query. * * @return {@link F} */ public F getFilter() { return filter; } /** * Sets a filter {@link F} for this query. * * @param filter * @return {@link CloudQuery} */ public CloudQuery setFilter(F filter) { this.filter = filter; return this; } /** * Sets a {@link Scope} of this query. * * @param scope * {@link Scope} of this query. * @return {@link CloudQuery} */ public CloudQuery setScope(Scope scope) { this.queryDto.setScope(scope.name()); return this; } /** * Returns {@link Scope} of this query. * * @return */ public Scope getScope() { return Scope.valueOf(this.queryDto.getScope()); } /** * Returns true if this query is a continuous query. * * @return */ public boolean isContinuous() { return (getScope() == Scope.FUTURE || getScope() == Scope.FUTURE_AND_PAST); } /** * Sets subscription duration (in sec) for this query. * * @param duration */ public void setSubscriptionDurationSec(int duration) { this.queryDto.setSubscriptionDurationSec(duration); } @Override public String toString() { return "CloudQuery (" + this.queryDto.getKindName() + "/" + getScope() + "): filter: " + filter; } /** * Sets the specified queryId to this query. This method will be used when * developer want to control identity of each query explicitly, such as * grouping multiple {@link CloudQuery} as one query and map it to one * handler. * * @param queryId * {@link String} that identifies each query */ public void setQueryId(String queryId) { this.queryDto.setQueryId(queryId); } /** * Returns queryId of this query. Unless developer sets it by * {@link #setQueryId(String)} explicitly, this method will return an ID based * on the query condition. It means the same ID will be returned for multiple * {@link CloudQuery}s if they have the same query condition. * * @return */ public String getQueryId() { setDefaultQueryIdIfNeeded(); return this.queryDto.getQueryId(); } private void setDefaultQueryIdIfNeeded() { if (this.queryDto.getQueryId() == null) { int queryHash = (gson.toJson(queryDto) + gson.toJson(filter)).hashCode(); String queryId = Base64.encodeToString(String.valueOf(queryHash).getBytes(), Base64.NO_PADDING | Base64.NO_WRAP); this.queryDto.setQueryId(queryId); } } }