/*
* Copyright 2016 Benjamin Sautner
*
* 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.nimbits.client.io;
import com.google.common.base.Optional;
import com.nimbits.client.enums.EntityType;
import com.nimbits.client.io.http.NimbitsClientException;
import com.nimbits.client.io.http.rest.RestClient;
import com.nimbits.client.model.calculation.Calculation;
import com.nimbits.client.model.category.Category;
import com.nimbits.client.model.entity.Entity;
import com.nimbits.client.model.hal.ValueContainer;
import com.nimbits.client.model.instance.Instance;
import com.nimbits.client.model.point.Point;
import com.nimbits.client.model.schedule.Schedule;
import com.nimbits.client.model.subscription.Subscription;
import com.nimbits.client.model.summary.Summary;
import com.nimbits.client.model.sync.Sync;
import com.nimbits.client.model.user.User;
import com.nimbits.client.model.value.Value;
import com.nimbits.client.model.webhook.WebHook;
import com.nimbits.server.gson.GsonFactory;
import retrofit.Callback;
import retrofit.ErrorHandler;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;
import retrofit.converter.GsonConverter;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* A simpler java client for interacting with the V3 REST API using hal+json
* and basic authentication
*/
@SuppressWarnings("unused")
public class Nimbits {
private final RestClient api;
private final int NOT_FOUND = 404;
protected Nimbits(final String email, final String token, String instance) {
RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json");
request.addHeader("Authorization", "Basic " + email + ":" + token); //TODO BASE64 encode this
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(instance)
.setRequestInterceptor(requestInterceptor)
.setConverter(new GsonConverter(GsonFactory.getInstance(false)))
.setErrorHandler(new ErrorHandler() {
@Override
public Throwable handleError(RetrofitError retrofitError) {
throw new NimbitsClientException("Error in Rest Adapter", retrofitError);
}
})
.build();
api = restAdapter.create(RestClient.class);
}
@Deprecated
public void connect() {
}
/**
* @return the authentication user from /service/v3/me
* @Param should the returned object contain a list of children one level down
*/
public User getMe(boolean includeChildren) {
return api.getMe(includeChildren);
}
/**
* @return the authentication user from /service/v3/me
* @Param should the returned object contain a list of children one level down
*/
public User getMe() {
return api.getMe(true);
}
/**
* if you are using an admin id, you can add users here.
*
* @param newUser a complete user object without an id or uuid
* @return
*/
public User addUser(User newUser) {
return api.addUser(newUser);
}
//READ Data
/**
* @param entity
* @param start
* @param end
* @param mask nullable - if present, will be used to filter values based on the mask string - can be null, string or regex
* @return
*/
public List<Value> getValues(Entity entity, Date start, Date end, String mask) {
return api.getData(entity.getId(), start.getTime(), end.getTime(), mask);
}
public List<Value> getValues(Entity entity, Date start, Date end, Integer count, String mask) {
return api.getData(entity.getId(), start.getTime(), end.getTime(), mask, count);
}
public List<Value> getValues(Entity entity, Integer count) {
return api.getData(entity.getId(), count);
}
/**
* @param entity
* @param start
* @param end
* @return
*/
public List<Value> getValues(Entity entity, Date start, Date end) {
return api.getData(entity.getId(), start.getTime(), end.getTime());
}
public Value getSnapshot(Point point) {
ValueContainer valueContainer = api.getSnapshot(point.getId());
return valueContainer.getSnapshot();
}
public Value getSnapshot(String pointName) {
Optional<Point> pointOptional = findPointByName(pointName);
if (pointOptional.isPresent()) {
ValueContainer valueContainer = api.getSnapshot(pointOptional.get().getId());
return valueContainer.getSnapshot();
} else {
throw new RuntimeException("Point Not Found");
}
}
public Value getSnapshot(Entity entity) {
ValueContainer valueContainer = api.getSnapshot(entity.getId());
return valueContainer.getSnapshot();
}
//Write Data
/**
* Record a series of values to a data point
*
* @param entity
* @param values
*/
public void recordValues(Entity entity, List<Value> values) {
api.recordData(entity.getId(), values, new Callback<Void>() {
@Override
public void success(Void aVoid, Response response) {
}
@Override
public void failure(RetrofitError retrofitError) {
throw new RuntimeException(retrofitError);
}
});
}
private Value recordValuesSync(Entity entity, Value value) {
return api.recordSnapshotSync(entity.getId(), value);
}
public void recordValue(Point point, Value newValue) {
recordValues(point, Collections.singletonList(newValue));
}
public void recordValue(String pointName, Value newValue) {
Optional<Point> point = findPointByName(pointName);
if (point.isPresent()) {
recordValues(point.get(), Collections.singletonList(newValue));
} else {
throw new RuntimeException("Point Not Found");
}
}
//DELETE Entities
public void deleteEntity(Entity entity) {
api.deleteEntity(entity.getId(), new Callback<Void>() {
@Override
public void success(Void aVoid, Response response) {
}
@Override
public void failure(RetrofitError retrofitError) {
throw new RuntimeException(retrofitError);
}
});
}
//Create Entity methods
/**
* Add an entity as a child of a parent
*
* @param parent
* @param point
* @return
*/
@Deprecated //we'll be creating individual methods for creating different types of entities
public Entity addEntity(Entity parent, Point point) {
Entity e = api.addEntity(parent.getId(), point);
return e;
}
public Category addCategory(Entity parent, Category category) {
return api.addCategory(parent.getId(), category);
}
public WebHook addWebHook(Entity parent, WebHook webHook) {
return api.addWebhook(parent.getId(), webHook);
}
public Subscription addSubscription(Entity parent, Subscription subscription) {
return api.addSubscription(parent.getId(), subscription);
}
public Sync addSync(Entity parent, Sync e) {
return api.addSync(parent.getId(), e);
}
public Calculation addCalc(Entity parent, Calculation e) {
return api.addCalc(parent.getId(), e);
}
public Summary addSummary(Entity parent, Summary e) {
return api.addSummary(parent.getId(), e);
}
/**
* Add an point as a child of a parent
*
* @param parent
* @param point
* @return
*/
public Point addPoint(Entity parent, Point point) {
return api.addPoint(parent.getId(), point);
}
public List<Point> getNearbyPoints(Point localPoint, double meters) {
return api.getNearbyPoints(localPoint.getId(), meters);
}
public Instance addInstance(Entity parent, Instance instance) {
return api.addInstance(parent.getId(), instance);
}
public Schedule addSchedule(Entity parent, Schedule s) {
return api.addSchedule(parent.getId(), s);
}
//find entity methods
/**
* get all children under an entity
*
* @param parent
* @return
*/
public List<Entity> getChildren(Entity parent) {
if (parent != null) {
return api.getChildren(parent.getId());
} else {
return Collections.emptyList();
}
}
public Optional<Point> findPointByName(String pointName) {
try {
Point p = api.findPoint(pointName, EntityType.point.getCode());
return Optional.of(p);
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
}
else {
throw ex;
}
}
}
public Optional<Category> findCategory(String name) {
try {
Category p = api.findCategory(name, EntityType.category.getCode());
return Optional.of(p);
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<WebHook> findWebHook(String name) {
try {
WebHook p = api.findWebHook(name, EntityType.webhook.getCode());
return Optional.of(p);
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<Subscription> findSubscription(String name) {
try {
Subscription p = api.findSubscription(name, EntityType.subscription.getCode());
return Optional.of(p);
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<Sync> findSync(String name) {
try {
Sync p = api.findSync(name, EntityType.sync.getCode());
return Optional.of(p);
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<Calculation> findCalculation(String name) {
try {
return Optional.of(api.findCalculation(name, EntityType.calculation.getCode()));
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<Instance> findInstance(String name) {
try {
return Optional.of(api.findInstance(name, EntityType.instance.getCode()));
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Optional<Summary> findSummary(String name) {
try {
return Optional.of(api.findSummary(name, EntityType.summary.getCode()));
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Point getPoint(String uuid) {
return api.getPoint(uuid);
}
public boolean entityExists(String uuid) {
Entity e;
try {
e = api.getEntity(uuid);
return (e != null);
} catch (Exception ex) {
return false;
}
}
public Optional<User> findUser(String email) {
try {
return Optional.of(api.findUser(email, EntityType.user.getCode()));
} catch (NimbitsClientException ex) {
if (ex.getCause() instanceof RetrofitError && ((RetrofitError)ex.getCause()).getResponse() != null && NOT_FOUND == ((RetrofitError)ex.getCause()).getResponse().getStatus()) {
return Optional.absent();
} else {
throw ex;
}
}
}
public Entity updateEntitySync(Entity entity) {
return api.updateEntitySync(entity.getId(), entity);
}
public void updateEntity(Entity entity) {
api.updateEntity(entity.getId(), entity, new Callback<Void>() {
@Override
public void success(Void aVoid, Response response) {
}
@Override
public void failure(RetrofitError retrofitError) {
}
});
}
/**
* @param entity a valid entity with a key and updated values
* @param callback returnes success or error
*/
public void updateEntity(Entity entity, Callback<Void> callback) {
api.updateEntity(entity.getId(), entity, callback);
}
public void setSnapshot(String pointName, Value value, Callback<Void> callback) {
Point p = api.findPoint(pointName, EntityType.point.getCode());
api.setSnapshot(p.getId(), value, callback);
}
public Value recordValueSync(String pointName, Value value) {
Optional<Point> point = findPointByName(pointName);
if (point.isPresent()) {
return recordValuesSync(point.get(), value);
} else {
throw new RuntimeException("Point Not Found");
}
}
public User getUser(String email) {
return api.getUser(email);
}
public void deleteUser(String email) {
api.deleteUser(email, new Callback<Void>() {
@Override
public void success(Void aVoid, Response response) {
System.out.println("Delete User OK");
}
@Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});
}
public static class Builder {
private String email;
private String token;
private String instance;
public Builder email(String email) {
this.email = email;
return this;
}
public Builder token(String token) {
this.token = token;
return this;
}
public Builder instance(String instance) {
this.instance = instance;
return this;
}
public Nimbits create() {
return new Nimbits(email, token, instance);
}
}
@Deprecated //user Builder()
private static class NimbitsBuilder {
private String email;
private String token;
private String instance;
public NimbitsBuilder email(String email) {
this.email = email;
return this;
}
public NimbitsBuilder token(String token) {
this.token = token;
return this;
}
public NimbitsBuilder instance(String instance) {
this.instance = instance;
return this;
}
public Nimbits create() {
return new Nimbits(email, token, instance);
}
}
}