/*
* Copyright 2010 Nabeel Mukhtar
*
* 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.github.api.v2.services.impl;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import com.github.api.v2.schema.Discussion;
import com.github.api.v2.schema.Gist;
import com.github.api.v2.schema.Issue;
import com.github.api.v2.schema.Job;
import com.github.api.v2.schema.Language;
import com.github.api.v2.schema.Organization;
import com.github.api.v2.schema.Permission;
import com.github.api.v2.schema.Repository;
import com.github.api.v2.schema.SchemaEntity;
import com.github.api.v2.schema.Tree;
import com.github.api.v2.services.AsyncResponseHandler;
import com.github.api.v2.services.GitHubException;
import com.github.api.v2.services.GitHubService;
import com.github.api.v2.services.constant.ApplicationConstants;
import com.github.api.v2.services.constant.GitHubApiUrls.GitHubApiUrlBuilder;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
/**
* The Class BaseGitHubService.
*/
public abstract class BaseGitHubService extends GitHubApiGateway implements GitHubService {
/** The Constant UTF_8_CHAR_SET. */
protected static final Charset UTF_8_CHAR_SET = Charset.forName(ApplicationConstants.CONTENT_ENCODING);
/** The parser. */
protected final JsonParser parser = new JsonParser();
/** The handlers. */
private List<AsyncResponseHandler<List<? extends SchemaEntity>>> handlers = new ArrayList<AsyncResponseHandler<List<? extends SchemaEntity>>>();
/**
* Instantiates a new base git hub service.
*/
public BaseGitHubService() {
// by default we compress contents
requestHeaders.put("Accept-Encoding", "gzip, deflate");
}
/**
* Instantiates a new base git hub service.
*
* @param apiVersion
* the api version
*/
public BaseGitHubService(String apiVersion) {
setApiVersion(apiVersion);
}
/**
* Unmarshall.
*
* @param typeToken
* the type token
* @param response
* the response
*
* @return the t
*/
@SuppressWarnings("unchecked")
protected <T> T unmarshall(TypeToken<T> typeToken, JsonElement response) {
Gson gson = getGsonBuilder().create();
return (T) gson.fromJson(response, typeToken.getType());
}
/**
* Notify observers.
*
* @param response
* the response
*/
protected void notifyObservers(List<? extends SchemaEntity> response) {
for(AsyncResponseHandler<List<? extends SchemaEntity>> handler : handlers) {
handler.handleResponse(response);
}
}
/* (non-Javadoc)
* @see com.google.code.stackexchange.client.query.StackExchangeApiQuery#addResonseHandler(com.google.code.stackexchange.client.AsyncResponseHandler)
*/
/**
* Adds the resonse handler.
*
* @param handler
* the handler
*/
public void addResonseHandler(AsyncResponseHandler<List<? extends SchemaEntity>> handler) {
handlers.add(handler);
}
/**
* Gets the gson builder.
*
* @return the gson builder
*/
protected GsonBuilder getGsonBuilder() {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat(ApplicationConstants.DATE_FORMAT);
builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
builder.registerTypeAdapter(Issue.State.class, new JsonDeserializer<Issue.State>() {
@Override
public Issue.State deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Issue.State.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Repository.Visibility.class, new JsonDeserializer<Repository.Visibility>() {
@Override
public Repository.Visibility deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return (arg0.getAsBoolean())? Repository.Visibility.PRIVATE : Repository.Visibility.PUBLIC;
}
});
builder.registerTypeAdapter(Gist.Visibility.class, new JsonDeserializer<Gist.Visibility>() {
@Override
public Gist.Visibility deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return (arg0.getAsBoolean())? Gist.Visibility.PUBLIC : Gist.Visibility.PRIVATE;
}
});
builder.registerTypeAdapter(Language.class, new JsonDeserializer<Language>() {
@Override
public Language deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Language.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Tree.Type.class, new JsonDeserializer<Tree.Type>() {
@Override
public Tree.Type deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Tree.Type.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Organization.Type.class, new JsonDeserializer<Organization.Type>() {
@Override
public Organization.Type deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Organization.Type.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Discussion.Type.class, new JsonDeserializer<Discussion.Type>() {
@Override
public Discussion.Type deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Discussion.Type.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Permission.class, new JsonDeserializer<Permission>() {
@Override
public Permission deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Permission.fromValue(arg0.getAsString());
}
});
builder.registerTypeAdapter(Job.Type.class, new JsonDeserializer<Job.Type>() {
@Override
public Job.Type deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
return Job.Type.fromValue(arg0.getAsString());
}
});
return builder;
}
/**
* Unmarshall.
*
* @param jsonContent
* the json content
*
* @return the json object
*/
protected JsonObject unmarshall(InputStream jsonContent) {
try {
JsonElement element = parser.parse(new InputStreamReader(jsonContent, UTF_8_CHAR_SET));
if (element.isJsonObject()) {
return element.getAsJsonObject();
} else {
throw new GitHubException("Unknown content found in response." + element);
}
} catch (Exception e) {
throw new GitHubException(e);
} finally {
closeStream(jsonContent);
}
}
/**
* Creates the git hub api url builder.
*
* @param urlFormat
* the url format
*
* @return the git hub api url builder
*/
protected GitHubApiUrlBuilder createGitHubApiUrlBuilder(String urlFormat) {
return new GitHubApiUrlBuilder(urlFormat);
}
}