Skip to content

Instantly share code, notes, and snippets.

@diego-aslz
Created November 11, 2013 14:16
Show Gist options
  • Save diego-aslz/7413791 to your computer and use it in GitHub Desktop.
Save diego-aslz/7413791 to your computer and use it in GitHub Desktop.
package br.com.clouded.web.service.support;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.joda.time.DateTime;
import org.json.JSONArray;
import org.json.JSONException;
import br.com.clouded.droid.db.DBHelper;
import br.com.clouded.droid.gsonadapters.DateTimeTypeConverter;
import br.com.clouded.droid.models.specific.Server;
import br.com.clouded.droid.util.CloudroidSession;
import br.com.clouded.droid.util.CloudroidUtils;
import br.com.clouded.droid.util.SyncDateFormat;
import br.com.clouded.web.util.URLConsts;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Classe genérica de comunicação com o WEB Service. Cada serviço (especificação de {@link CloudedService }) se comunica com um, e apenas um,
* <i>controller</i> do servidor. Esta classe não pode ser instanciada, ela deve ser herdada e implementada.
*
* @author Diego Aguir Selzlein
*
*/
public abstract class CloudedService<T> {
protected HttpClient httpclient = new DefaultHttpClient();
protected Server server;
protected DBHelper dbHelper;
public CloudedService(DBHelper dbHelper, Server server) {
this.dbHelper = dbHelper;
this.server = server;
}
protected String stringFrom(HttpResponse response) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
return out.toString();
}
/**
* Converte a resposta HTTP em um vetor de bytes. Este método foi criado para evitar repetição de código.
* @param response Resposta HTTP.
* @return Vetor de bytes da resposta.
* @throws IOException
* @throws JSONException
*/
protected ByteArrayOutputStream bytesFrom(HttpResponse response) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
return out;
}
/**
* Método genérico que converte resposta HTTP recebida do servidor em um vetor de objetos JSON.
* Caso um objeto possua especificidades que devem ser tratadas, este método deve ser sobrescrito
* na classe que herda {@link CloudedService} para fazê-lo.
* @param response Resposta HTTP recebida do servidor.
* @return Vetor de objetos JSON.
* @throws IOException
* @throws JSONException
*/
protected JSONArray arrayFrom(HttpResponse response) throws IOException, JSONException {
return new JSONArray(bytesFrom(response).toString());
}
/**
* Deve ser implementado na classe que herda {@link CloudedService} para retornar o endereço do servidor
* de onde todos os objetos podem ser obtidos (correspondente à ação <i>index</i>.
* @param server Servidor de conexão.
* @return Endereço da ação <i>index</i> do <i>controller</i> correspondente a esta classe.
*/
protected abstract String urlIndex(Server server);
/**
* Deve ser implementado na classe que herda {@link CloudedService} para retornar o endereço do servidor
* para criação de novos objetos (correspondente à ação <i>create</i>.
* @param server Servidor de conexão.
* @return Endereço da ação <i>create</i> do <i>controller</i> correspondente a esta classe.
*/
protected String urlCreate(Server server) {
return null;
}
/**
* Deve ser implementado na classe que herda {@link CloudedService} para retornar o endereço do servidor
* de onde um o objeto pode ser obtido através de seu ID (correspondente à ação <i>show</i>.
* @param server Servidor de conexão.
* @param id ID do objeto cujo endereço deve ser retornado.
* @return Endereço da ação <i>show</i> do objeto de ID parametrizado do <i>controller</i> correspondente a esta classe.
*/
protected abstract String urlGet(Server server, long id);
/**
* Obtém do servidor objeto com ID parametrizado. Autenticação será feita com o <i>token</i> do usuário corrente em {@link CloudroidSession}.
* @param server Servidor de conexão.
* @param id ID do objeto desejado
* @return Objeto obtido.
* @throws Exception
*/
public T get(long id) throws Exception {
return get(id, CloudroidSession.getInstance().getCurrentUser().getToken());
}
/**
* Obtém do servidor objeto com ID parametrizado. Autenticação será feita com o <i>token</i> parametrizado.
* @param server Servidor de conexão.
* @param id ID do objeto desejado
* @param token <i>Token</i> de autenticação do usuário.
* @return Objeto obtido.
* @throws IOException
* @throws ClientProtocolException
* @throws Exception
*/
public T get(long id, String token) throws ClientProtocolException, IOException {
String uri = urlGet(server, id) + URLConsts.SUFIX + "?";
List<NameValuePair> params = new ArrayList<NameValuePair>();
addAuthParams(token, params);
uri += URLEncodedUtils.format(params, "utf-8");
HttpGet get = new HttpGet(uri);
HttpResponse r = httpclient.execute(get);
StatusLine statusLine = r.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK)
return fromJSON(stringFrom(r));
else
throw new RuntimeException("Erro de servidor. Por favor, contate os responsáveis" +
" pelo sistema.");
}
/**
* Obtém do servidor todos os objetos tratados por este serviço que foram atualizados a partir da data parametrizada.
* Autenticação será feita com o <i>token</i> parametrizado.
* @param server Servidor de conexão.
* @param base Data base para a busca.
* @param token <i>Token</i> de autenticação do usuário.
* @return
* @throws Exception
*/
public List<T> index(Date base, String token) throws Exception {
SyncDateFormat df = new SyncDateFormat();
String uri = urlIndex(server) + URLConsts.SUFIX + "?";
List<NameValuePair> params = new ArrayList<NameValuePair>();
addAuthParams(token, params);
params.add(new BasicNameValuePair("base", df.format(base)));
uri += URLEncodedUtils.format(params, "utf-8");
HttpGet get = new HttpGet(uri);
HttpResponse r = httpclient.execute(get);
StatusLine statusLine = r.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
List<T> result = new ArrayList<T>();
JSONArray ar = arrayFrom(r);
for (int i = 0; i < ar.length(); i++)
result.add(fromJSON(ar.getJSONObject(i).toString()));
return result;
} else
throw new Exception("Erro de servidor. Por favor, contate os responsáveis" +
" pelo sistema.");
}
protected void addAuthParams(String token, List<NameValuePair> params) {
params.add(new BasicNameValuePair("auth", token));
params.add(new BasicNameValuePair("device", CloudroidUtils.getDeviceId()));
}
public T create(T t, String token) throws Exception {
String uri = urlCreate(server) + URLConsts.SUFIX + "?";
List<NameValuePair> params = new ArrayList<NameValuePair>();
addAuthParams(token, params);
uri += URLEncodedUtils.format(params, "utf-8");
HttpPost post = new HttpPost(uri);
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
post.setEntity(new StringEntity(toJson(t)));
HttpResponse r = httpclient.execute(post);
StatusLine statusLine = r.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_CREATED) {
return fromJSON(stringFrom(r));
} else
throw new Exception("Erro de servidor. Por favor, contate os responsáveis" +
" pelo sistema.");
}
/**
* Deve ser implementado na classe que especializa {@link CloudedService} para retornar uma nova instância do objeto tratado por ela.
* @return Novo objeto da classe tratada por este serviço.
*/
protected abstract T newObject();
/**
* Retorna a classe a qual o serviço trata.
* @return
*/
public abstract Class<T> getClazz();
/**
* Deve ser sobrescrito nos serviços que herdam deste para personalizar a geração do JSON
* do objeto.
* @param builder
* @return
*/
public Gson writeGsonAdapters(GsonBuilder builder) {
builder.registerTypeAdapter(DateTime.class, new DateTimeTypeConverter());
return builder.create();
}
/**
* Converte o objeto parametrizado em JSON.
* @param t
* @return
*/
public String toJson(T t) {
Gson gson = writeGsonAdapters(new GsonBuilder());
return gson.toJson(t);
}
/**
* Carrega objeto a partir de uma String JSON.
* @param model
* @param json
* @return
*/
public T fromJSON(String json) {
Gson gson = writeGsonAdapters(new GsonBuilder());
return gson.fromJson(json, getClazz());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment