package rabbitescape.ui.swing;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.regex.Pattern;
import static rabbitescape.engine.i18n.Translation.t;
/**
* @brief retrieval and parsing. no swing.
*/
public class GitHubClient implements GitHubPageFetchNotifier
{
public final String baseURL = "https://api.github.com/repos/andybalaam/rabbit-escape/issues";
public final String acceptHeader = "Accept: application/vnd.github.v3+json";
private ArrayList<GitHubIssue> issues = null;
private String errMsg = "";
private int page = 1;
/** < .../issues?page=number */
private boolean gotAllPages = false;
/** < @brief do not query for more pages of issues */
public GitHubClient()
{
}
public void initialise()
{
String jsonIssues = apiCall( "" );
issues = parseIssues( jsonIssues );
}
public void fetchComments( GitHubIssue ghi )
{
String jsonComments = apiCall( "/" + ghi.getNumber() + "/comments" );
String[] commentBodies = GitHubJsonTools
.getStringValuesFromArrayOfObjects( jsonComments, "body" );
for ( int i = 0; i < commentBodies.length; i++ )
{
ghi.addToBody( commentBodies[i] );
}
}
public String getError()
{
return errMsg;
}
/**
* @param GitHubPageFetcher
* required in case more issues need fetching. This method can
* make a call back to the UI. This is necessary as it may be
* time consuming: the user needs a progress bar or something.
*/
public GitHubIssue getIssue( int index, GitHubPageFetcher ghpf )
{
if ( null == issues || index < 0 )
{
return null;
}
if ( index >= issues.size() )
{
if ( gotAllPages )
{
return null;
}
ghpf.notifyAndFetch( baseURL + "?page=" + ( ++page ),
acceptHeader,
t( "Fetching more issues." ),
this );
return null; // user waits and requests again
}
return issues.get( index );
}
public int getIndexOfNumber( int issueNumber )
{
for ( int i = 0; i < issues.size(); i++ )
{
GitHubIssue ghi = issues.get( i );
if ( ghi.getNumber() == issueNumber )
{
return i;
}
}
return -1;
}
private static ArrayList<GitHubIssue> parseIssues( String json )
{ // / @TODO this is extremely crufty: hacking out most of the URL to split
// on.
// This leaves the issue number as the first thing in the string.
Pattern issuePattern = Pattern
.compile( "\\{\"url\":\"https://api\\.github\\.com/repos/andybalaam/rabbit-escape/issues/" );
String[] jsonIssuesStrings = issuePattern.split( json );
ArrayList<GitHubIssue> ret = new ArrayList<GitHubIssue>();
for ( int i = 0; i < jsonIssuesStrings.length; i++ )
{
String jsonIssue = jsonIssuesStrings[i];
if ( !"0123456789".contains( jsonIssue.substring( 0, 1 ) ) )
{
continue;
}
GitHubIssue ghi = new GitHubIssue(
GitHubJsonTools.getIntValue( jsonIssue, "number" ),
GitHubJsonTools.getStringValue( jsonIssue, "title" ),
GitHubJsonTools.getStringValue( jsonIssue, "body" ),
GitHubJsonTools.getStringValuesFromArrayOfObjects( jsonIssue,
"labels.name" )
);
ret.add( ghi );
}
return ret;
}
private String apiCall( String endURL )
{
try
{
return HttpTools.get( baseURL + endURL, acceptHeader );
}
catch ( UnknownHostException eUH )
{
errMsg = t( "Can't reach github.com." );
}
catch ( Exception e )
{
e.printStackTrace();
}
return null;
}
@Override
public void setPage( String page )
{
ArrayList<GitHubIssue> extra = parseIssues( page );
issues.addAll( extra );
if ( 0 == extra.size() )
{
gotAllPages = true; // Github has no more to give
}
}
}