Half of features implemented #2
19
pom.xml
19
pom.xml
|
@ -21,6 +21,10 @@
|
|||
</build>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<jackson.version>2.9.6</jackson.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@ -48,6 +52,21 @@
|
|||
<artifactId>httpclient</artifactId>
|
||||
<version>RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -1,7 +1,7 @@
|
|||
package nl.andrewlalis;
|
||||
|
||||
import nl.andrewlalis.git_api.Initializer;
|
||||
import nl.andrewlalis.model.Team;
|
||||
import nl.andrewlalis.model.StudentTeam;
|
||||
import nl.andrewlalis.util.Logging;
|
||||
import nl.andrewlalis.util.TeamGenerator;
|
||||
|
||||
|
@ -33,16 +33,16 @@ public class Main {
|
|||
|
||||
logger.info("Initializer for Github Repositories in Educational Organizations.");
|
||||
|
||||
// Get teams from CSV file.
|
||||
List<Team> teams = null;
|
||||
// Get studentTeams from CSV file.
|
||||
List<StudentTeam> studentTeams = null;
|
||||
try {
|
||||
teams = TeamGenerator.generateFromCSV(
|
||||
studentTeams = TeamGenerator.generateFromCSV(
|
||||
userOptions.get("input"),
|
||||
Integer.parseInt(userOptions.get("teamsize"))
|
||||
);
|
||||
logger.info("Teams created: " + teams);
|
||||
logger.info("Teams created: " + studentTeams);
|
||||
} catch (IOException | ArrayIndexOutOfBoundsException e) {
|
||||
logger.severe("Unable to generate teams from CSV file, exiting.");
|
||||
logger.severe("Unable to generate studentTeams from CSV file, exiting.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class Main {
|
|||
userOptions.get("token"),
|
||||
"assignments"
|
||||
);
|
||||
initializer.initializeGithubRepos(teams);
|
||||
initializer.initializeGithubRepos(studentTeams);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,62 @@
|
|||
package nl.andrewlalis.git_api;
|
||||
|
||||
import nl.andrewlalis.model.Team;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import nl.andrewlalis.model.StudentTeam;
|
||||
import nl.andrewlalis.model.TATeam;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class is responsible for initializing the Github repositories and setting permissions, adding teams, etc.
|
||||
*/
|
||||
public class Initializer {
|
||||
|
||||
/**
|
||||
* The name of the organization to operate on.
|
||||
*/
|
||||
private String organizationName;
|
||||
|
||||
/**
|
||||
* The oauth access token needed for the request.
|
||||
*/
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* The object which simplifies creating REST URL's for most of the requests.
|
||||
*/
|
||||
private URLBuilder urlBuilder;
|
||||
|
||||
/**
|
||||
* The name of the assignments repository where students will get assignments from.
|
||||
*/
|
||||
private String assignmentsRepo;
|
||||
|
||||
/**
|
||||
* The logger for outputting debug info.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(Initializer.class.getName());
|
||||
static {
|
||||
logger.setParent(Logger.getGlobal());
|
||||
}
|
||||
|
||||
public Initializer(String organizationName, String accessToken, String assignmentsRepo) {
|
||||
this.organizationName = organizationName;
|
||||
this.accessToken = accessToken;
|
||||
|
@ -31,26 +65,61 @@ public class Initializer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes the github repository for all teams given.
|
||||
* Initializes the github repository for all studentTeams given.
|
||||
*
|
||||
* Creates for the entire organization:
|
||||
* - an assignments repository with protected master branch and TA permissions.
|
||||
* Creates for each team:
|
||||
* - a repository
|
||||
* - protected master branch
|
||||
* - development branch
|
||||
* - adds students to repository
|
||||
* - creates assignments repository
|
||||
* - adds all students to assignments repository.
|
||||
* @param teams The list of student teams.
|
||||
* @param studentTeams The list of student studentTeams.
|
||||
*/
|
||||
public void initializeGithubRepos(List<Team> teams) {
|
||||
public void initializeGithubRepos(List<StudentTeam> studentTeams) {
|
||||
listMemberTeams();
|
||||
//this.createRepository(this.assignmentsRepo, )
|
||||
}
|
||||
|
||||
private boolean createRepository(String repositoryName, TATeam taTeam) {
|
||||
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
|
||||
nvps.add(new BasicNameValuePair("name", repositoryName));
|
||||
nvps.add(new BasicNameValuePair("private", "True"));
|
||||
nvps.add(new BasicNameValuePair("has_issues", "True"));
|
||||
nvps.add(new BasicNameValuePair("has_wiki", "True"));
|
||||
nvps.add(new BasicNameValuePair("team_id", taTeam.getId()));
|
||||
nvps.add(new BasicNameValuePair("auto_init", "False"));
|
||||
nvps.add(new BasicNameValuePair("gitignore_template", "Java"));
|
||||
HttpClient client = HttpClientBuilder.create().build();
|
||||
HttpPost post = new HttpPost(this.urlBuilder.buildRepoURL());
|
||||
try {
|
||||
post.setEntity(new StringEntity(nvps.toString()));
|
||||
post.setHeader("Content-type", "application/json");
|
||||
HttpResponse response = client.execute(post);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of all teams in the organization, meaning all teaching assistant teams.
|
||||
* @return A list of all teams in the organization.
|
||||
*/
|
||||
private Map<String, String> listMemberTeams() {
|
||||
CloseableHttpClient client = HttpClients.createDefault();
|
||||
HttpGet get = new HttpGet(this.urlBuilder.buildTeamURL());
|
||||
try (CloseableHttpResponse response = client.execute(get)) {
|
||||
System.out.println(response.getStatusLine());
|
||||
StatusLine line = response.getStatusLine();
|
||||
logger.finest("Response code from listing member teams: " + line.getStatusCode());
|
||||
logger.finest("Response entity: " + response.getEntity().toString());
|
||||
HashMap<String,Object> result =
|
||||
new ObjectMapper().readValue(response.getEntity().getContent(), HashMap.class);
|
||||
for (Map.Entry<String, Object> e : result.entrySet()) {
|
||||
logger.finest(e.getKey() + ": " + e.getValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public class URLBuilder {
|
|||
+ this.organizationName
|
||||
+ '/'
|
||||
+ repoName
|
||||
+ "/git/refs/heads/master?acces_token="
|
||||
+ "/git/refs/heads/master?access_token="
|
||||
+ this.accessToken;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package nl.andrewlalis.model;
|
||||
|
||||
/**
|
||||
* A generic object that students, teaching assistants, and professors can extend from. This covers all the basic
|
||||
* functionality that applies to anyone in the system.
|
||||
*/
|
||||
public abstract class Person {
|
||||
|
||||
/**
|
||||
* The unique identification number for this person. (P- or S-Number)
|
||||
*/
|
||||
protected int number;
|
||||
|
||||
/**
|
||||
* The person's first and last name.
|
||||
*/
|
||||
protected String name;
|
||||
|
||||
/**
|
||||
* The person's email address.
|
||||
*/
|
||||
protected String emailAddress;
|
||||
|
||||
/**
|
||||
* The person's github username.
|
||||
*/
|
||||
protected String githubUsername;
|
||||
|
||||
/**
|
||||
* Constructs a Person from all the basic information needed.
|
||||
* @param number Either an S- or P-Number without the letter prefix.
|
||||
* @param name The first, middle (if applicable) and last name.
|
||||
* @param emailAddress The email address. (Either university or personal.)
|
||||
* @param githubUsername The person's github username.
|
||||
*/
|
||||
public Person(int number, String name, String emailAddress, String githubUsername){
|
||||
this.number = number;
|
||||
this.name = name;
|
||||
this.emailAddress = emailAddress;
|
||||
this.githubUsername = githubUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors
|
||||
*/
|
||||
public int getNumber(){
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getEmailAddress(){
|
||||
return this.emailAddress;
|
||||
}
|
||||
|
||||
public String getGithubUsername(){
|
||||
return this.githubUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if two persons are the same. This is defined as:
|
||||
* Two persons are equal if at least one of their personal data points is identical. Because each of the data points
|
||||
* should be unique to this person alone, if there is any conflict, assume that they are equal.
|
||||
* @param o The object to compare to.
|
||||
* @return True if the two persons share personal data, or false if all data is unique among the two.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Person)) {
|
||||
return false;
|
||||
}
|
||||
Person p = (Person)o;
|
||||
return p.getNumber() == this.getNumber()
|
||||
|| p.getEmailAddress().equals(this.getEmailAddress())
|
||||
|| p.getGithubUsername().equals(this.getGithubUsername())
|
||||
|| p.getName().equalsIgnoreCase(this.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the person as a basic comma-separated string object.
|
||||
* @return A comma-separated String object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getName() + ", " + this.getNumber() + ", " + this.getEmailAddress() + ", " + this.getGithubUsername();
|
||||
}
|
||||
}
|
|
@ -1,66 +1,34 @@
|
|||
package nl.andrewlalis.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents one student's github information.
|
||||
*/
|
||||
public class Student {
|
||||
|
||||
/**
|
||||
* The student's S-number.
|
||||
*/
|
||||
private int number;
|
||||
|
||||
/**
|
||||
* The student's name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The student's email.
|
||||
*/
|
||||
private String emailAddress;
|
||||
|
||||
/**
|
||||
* The student's github username.
|
||||
*/
|
||||
private String githubUsername;
|
||||
public class Student extends Person {
|
||||
|
||||
/**
|
||||
* A list of partners that the student has said that they would like to be partners with.
|
||||
*/
|
||||
private List<Integer> preferredPartners;
|
||||
|
||||
/**
|
||||
* Constructs a student similarly to a Person, but with an extra preferredPartners list.
|
||||
* @param number The student's S-Number.
|
||||
* @param name The student's name.
|
||||
* @param emailAddress The student's email address.
|
||||
* @param githubUsername The student's github username.
|
||||
* @param preferredPartners A list of this student's preferred partners, as a list of integers representing the
|
||||
* other students' numbers.
|
||||
*/
|
||||
public Student(int number, String name, String emailAddress, String githubUsername, List<Integer> preferredPartners) {
|
||||
this.number = number;
|
||||
this.name = name;
|
||||
this.emailAddress = emailAddress;
|
||||
this.githubUsername = githubUsername;
|
||||
super(number, name, emailAddress, githubUsername);
|
||||
this.preferredPartners = preferredPartners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.number + " - " + this.name + " - " + this.emailAddress + " - " + this.githubUsername;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public String getGithubUsername() {
|
||||
return githubUsername;
|
||||
}
|
||||
|
||||
public List<Integer> getPreferredPartners() {
|
||||
return preferredPartners;
|
||||
return this.preferredPartners;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,23 +36,12 @@ public class Student {
|
|||
* @param studentMap A mapping from student number to student for all students who have signed up.
|
||||
* @return A team with unknown id, comprised of this student's preferred partners.
|
||||
*/
|
||||
public Team getPreferredTeam(Map<Integer, Student> studentMap) {
|
||||
Team t = new Team();
|
||||
public StudentTeam getPreferredTeam(Map<Integer, Student> studentMap) {
|
||||
StudentTeam t = new StudentTeam();
|
||||
for (int partnerNumber : this.getPreferredPartners()) {
|
||||
t.addStudent(studentMap.get(partnerNumber));
|
||||
}
|
||||
t.addStudent(this);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object s) {
|
||||
if (!(s instanceof Student)) {
|
||||
return false;
|
||||
}
|
||||
Student student = (Student) s;
|
||||
return student.getNumber() == this.getNumber()
|
||||
|| student.getEmailAddress().equals(this.getEmailAddress())
|
||||
|| student.getGithubUsername().equals(this.getGithubUsername());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.List;
|
|||
/**
|
||||
* Represents one or more students' collective information.
|
||||
*/
|
||||
public class Team {
|
||||
public class StudentTeam {
|
||||
|
||||
/**
|
||||
* The list of students in this team.
|
||||
|
@ -18,7 +18,7 @@ public class Team {
|
|||
*/
|
||||
private int id;
|
||||
|
||||
public Team() {
|
||||
public StudentTeam() {
|
||||
this.students = new ArrayList<>();
|
||||
this.id = -1;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public class Team {
|
|||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("Team: ");
|
||||
StringBuilder sb = new StringBuilder("StudentTeam: ");
|
||||
sb.append(this.id).append('\n');
|
||||
for (Student s : this.students) {
|
||||
sb.append('\t').append(s.toString()).append('\n');
|
||||
|
@ -134,8 +134,8 @@ public class Team {
|
|||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Team) {
|
||||
Team t = (Team) o;
|
||||
if (o instanceof StudentTeam) {
|
||||
StudentTeam t = (StudentTeam) o;
|
||||
if (t.getStudentCount() != this.getStudentCount()) {
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package nl.andrewlalis.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TATeam {
|
||||
|
||||
private List<TeachingAssistant> teachingAssistants;
|
||||
|
||||
public TATeam(List<TeachingAssistant> teachingAssistants) {
|
||||
this.teachingAssistants = teachingAssistants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique identification for this TA team.
|
||||
* @return A string representing the id of this team.
|
||||
*/
|
||||
public String getId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package nl.andrewlalis.model;
|
||||
|
||||
public class TeachingAssistant extends Person {
|
||||
|
||||
/**
|
||||
* Constructs a Teaching Assistant from all the basic information needed, much like its parent, Person.
|
||||
*
|
||||
* @param number Either an S- or P-Number without the letter prefix.
|
||||
* @param name The first, middle (if applicable) and last name.
|
||||
* @param emailAddress The email address. (Either university or personal.)
|
||||
* @param githubUsername The person's github username.
|
||||
*/
|
||||
public TeachingAssistant(int number, String name, String emailAddress, String githubUsername) {
|
||||
super(number, name, emailAddress, githubUsername);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package nl.andrewlalis.util;
|
||||
|
||||
import nl.andrewlalis.model.Student;
|
||||
import nl.andrewlalis.model.Team;
|
||||
import nl.andrewlalis.model.StudentTeam;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
|
@ -32,11 +32,11 @@ public class TeamGenerator {
|
|||
* @throws IOException If the file is unable to be read.
|
||||
* @throws IllegalArgumentException If an invalid teamsize is given.
|
||||
*/
|
||||
public static List<Team> generateFromCSV(String filename, int teamSize) throws IOException, IllegalArgumentException {
|
||||
public static List<StudentTeam> generateFromCSV(String filename, int teamSize) throws IOException, IllegalArgumentException {
|
||||
logger.info("Generating teams of size " + teamSize);
|
||||
if (teamSize < 1) {
|
||||
logger.severe("Invalid team size.");
|
||||
throw new IllegalArgumentException("Team size must be greater than or equal to 1. Got " + teamSize);
|
||||
throw new IllegalArgumentException("StudentTeam size must be greater than or equal to 1. Got " + teamSize);
|
||||
}
|
||||
logger.fine("Parsing CSV file.");
|
||||
Iterable<CSVRecord> records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(new FileReader(filename));
|
||||
|
@ -46,8 +46,8 @@ public class TeamGenerator {
|
|||
try {
|
||||
studentMap = readAllStudents(records, teamSize);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
logger.severe("Team size does not match column count in records.");
|
||||
throw new IllegalArgumentException("Team size does not match column count in records.");
|
||||
logger.severe("StudentTeam size does not match column count in records.");
|
||||
throw new IllegalArgumentException("StudentTeam size does not match column count in records.");
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,28 +72,28 @@ public class TeamGenerator {
|
|||
* @param teamSize The preferred maximum size for a team.
|
||||
* @return A list of teams, most of which are of teamSize size.
|
||||
*/
|
||||
private static List<Team> generateAllValidTeams(Map<Integer, Student> studentMap, int teamSize) {
|
||||
private static List<StudentTeam> generateAllValidTeams(Map<Integer, Student> studentMap, int teamSize) {
|
||||
List<Student> singleStudents = new ArrayList<>(studentMap.values());
|
||||
List<Team> teams = new ArrayList<>();
|
||||
List<StudentTeam> studentTeams = new ArrayList<>();
|
||||
|
||||
int teamCount = 1;
|
||||
// For each student, try to make a team from its preferred partners.
|
||||
for (Map.Entry<Integer, Student> e : studentMap.entrySet()) {
|
||||
Team t = e.getValue().getPreferredTeam(studentMap);
|
||||
StudentTeam t = e.getValue().getPreferredTeam(studentMap);
|
||||
logger.finest("Checking if student's preferred team is valid: " + t.getStudents());
|
||||
// Check if the team is of a valid size, and is not a duplicate.
|
||||
// Note that at this stage, singles are treated as teams of 1, and thus not valid for any teamSize > 1.
|
||||
if (t.isValid(teamSize) && !teams.contains(t)) {
|
||||
// Note that at this stage, singles are treated as studentTeams of 1, and thus not valid for any teamSize > 1.
|
||||
if (t.isValid(teamSize) && !studentTeams.contains(t)) {
|
||||
// Once we know this team is completely valid, we remove all the students in it from the list of singles.
|
||||
t.setId(teamCount++);
|
||||
singleStudents.removeAll(t.getStudents());
|
||||
teams.add(t);
|
||||
studentTeams.add(t);
|
||||
logger.fine("Created team: " + t);
|
||||
}
|
||||
}
|
||||
|
||||
teams.addAll(mergeSingleStudents(singleStudents, teamSize, teamCount));
|
||||
return teams;
|
||||
studentTeams.addAll(mergeSingleStudents(singleStudents, teamSize, teamCount));
|
||||
return studentTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,10 +104,10 @@ public class TeamGenerator {
|
|||
* @param teamIndex The current number used in assigning an id to the team.
|
||||
* @return A list of teams comprising of single students.
|
||||
*/
|
||||
private static List<Team> mergeSingleStudents(List<Student> singleStudents, int teamSize, int teamIndex) {
|
||||
List<Team> teams = new ArrayList<>();
|
||||
private static List<StudentTeam> mergeSingleStudents(List<Student> singleStudents, int teamSize, int teamIndex) {
|
||||
List<StudentTeam> studentTeams = new ArrayList<>();
|
||||
while (!singleStudents.isEmpty()) {
|
||||
Team t = new Team();
|
||||
StudentTeam t = new StudentTeam();
|
||||
t.setId(teamIndex++);
|
||||
logger.fine("Creating new team of single students: " + t);
|
||||
while (t.getStudentCount() < teamSize && !singleStudents.isEmpty()) {
|
||||
|
@ -115,10 +115,10 @@ public class TeamGenerator {
|
|||
logger.finest("Single student: " + s);
|
||||
t.addStudent(s);
|
||||
}
|
||||
teams.add(t);
|
||||
studentTeams.add(t);
|
||||
logger.fine("Created team: " + t);
|
||||
}
|
||||
return teams;
|
||||
return studentTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue