package nl.topicus.onderwijs.dashboard.modules.github;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import nl.topicus.onderwijs.dashboard.config.ISettings;
import nl.topicus.onderwijs.dashboard.datasources.Commits;
import nl.topicus.onderwijs.dashboard.datatypes.Commit;
import nl.topicus.onderwijs.dashboard.keys.Key;
import nl.topicus.onderwijs.dashboard.modules.AbstractService;
import nl.topicus.onderwijs.dashboard.modules.DashboardRepository;
import nl.topicus.onderwijs.dashboard.modules.ServiceConfiguration;
import org.eclipse.egit.github.core.RepositoryCommit;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.client.GsonUtils;
import org.eclipse.egit.github.core.service.CommitService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializer;
@Service
@ServiceConfiguration(interval = 1, unit = TimeUnit.MINUTES)
public class GitHubService extends AbstractService {
private static final Logger log = LoggerFactory
.getLogger(GitHubService.class);
private Map<String, RepositoryCommit> fullCommits = new HashMap<String, RepositoryCommit>();
private Map<Key, List<Commit>> commits = new HashMap<Key, List<Commit>>();
@Autowired
public GitHubService(ISettings settings) {
super(settings);
}
@Override
public void onConfigure(DashboardRepository repository) {
for (Key key : getSettings().getKeysWithConfigurationFor(
GitHubService.class)) {
commits.put(key, Collections.<Commit> emptyList());
repository.addDataSource(key, Commits.class, new CommitsImpl(key,
this));
}
try {
Field deserializersField = Gson.class
.getDeclaredField("deserializers");
deserializersField.setAccessible(true);
Object deserializers = deserializersField.get(GsonUtils.getGson());
Field deserializersMapField = deserializers.getClass()
.getDeclaredField("map");
deserializersMapField.setAccessible(true);
Map<Type, JsonDeserializer<?>> deserializersMap = (Map<Type, JsonDeserializer<?>>) deserializersMapField
.get(deserializers);
deserializersMap.put(Date.class, new GitHubDateFormatter());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
@Override
public void refreshData() {
Map<Key, List<Commit>> newCommits = new HashMap<Key, List<Commit>>();
Map<Key, Map<String, ?>> serviceSettings = getSettings()
.getServiceSettings(GitHubService.class);
for (Map.Entry<Key, Map<String, ?>> configEntry : serviceSettings
.entrySet()) {
try {
Key project = configEntry.getKey();
String owner = configEntry.getValue().get("owner").toString();
String repository = configEntry.getValue().get("repository")
.toString();
String username = (String) configEntry.getValue().get(
"username");
String password = (String) configEntry.getValue().get(
"password");
String token = (String) configEntry.getValue().get("token");
newCommits.put(
project,
fetchCommits(project, owner, repository, username,
password, token));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
commits = newCommits;
}
private List<Commit> fetchCommits(final Key project, String owner,
String repository, String username, String password, String token)
throws IOException {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -1);
Date oneDayAgo = cal.getTime();
CommitService commits = new CommitService();
if (token != null)
commits.getClient().setOAuth2Token(token);
else
commits.getClient().setCredentials(username, password);
final List<Commit> ret = new ArrayList<Commit>();
RepositoryId repositoryId = new RepositoryId(owner, repository);
for (RepositoryCommit curCommit : commits.pageCommits(repositoryId, 30)
.next()) {
if (curCommit.getCommit().getCommitter().getDate().after(oneDayAgo)) {
RepositoryCommit fullCommit = fullCommits.get(curCommit
.getSha());
if (fullCommit == null) {
fullCommit = commits.getCommit(repositoryId,
curCommit.getSha());
fullCommits.put(curCommit.getSha(), fullCommit);
}
curCommit = fullCommit;
}
ret.add(new Commit(project, curCommit));
}
return ret;
}
public List<Commit> getCommits(Key key) {
return commits.get(key);
}
}