Half of features implemented #2
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -6,6 +6,8 @@ import nl.andrewlalis.model.Student;
 | 
			
		|||
import nl.andrewlalis.model.StudentTeam;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.Executable;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.executables.ArchiveRepos;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.executables.ReadStudentsFileToDB;
 | 
			
		||||
import nl.andrewlalis.ui.view.InitializerApp;
 | 
			
		||||
import nl.andrewlalis.util.CommandLine;
 | 
			
		||||
import nl.andrewlalis.util.Logging;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,18 +40,26 @@ public class Main {
 | 
			
		|||
            logger.severe("Unable to save log to file.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Command executor which will be used by all actions the user can do.
 | 
			
		||||
        CommandExecutor executor = new CommandExecutor();
 | 
			
		||||
 | 
			
		||||
        // Initialize User Interface.
 | 
			
		||||
        InitializerApp app = new InitializerApp(executor);
 | 
			
		||||
        app.begin();
 | 
			
		||||
 | 
			
		||||
        Database db = new Database("database/initializer.sqlite");
 | 
			
		||||
        db.initialize();
 | 
			
		||||
 | 
			
		||||
        executor.registerCommand("test", args1 -> {
 | 
			
		||||
            System.out.println("TESTING");
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
        executor.registerCommand("readstudents", new ReadStudentsFileToDB(db));
 | 
			
		||||
        executor.registerCommand("archiveall", new ArchiveRepos());
 | 
			
		||||
 | 
			
		||||
        // Initialize User Interface.
 | 
			
		||||
        InitializerApp app = new InitializerApp(executor);
 | 
			
		||||
        logger.info("GithubManager for Github Repositories in Educational Organizations. Program initialized.");
 | 
			
		||||
 | 
			
		||||
        app.begin();
 | 
			
		||||
 | 
			
		||||
        logger.info("GithubManager for Github Repositories in Educational Organizations.");
 | 
			
		||||
 | 
			
		||||
        // Get studentTeams from CSV file.
 | 
			
		||||
//        List<StudentTeam> studentTeams = getStudentTeamsFromCSV(userOptions.get("input"), Integer.parseInt(userOptions.get("teamsize")));
 | 
			
		||||
| 
						 | 
				
			
			@ -68,17 +78,6 @@ public class Main {
 | 
			
		|||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Initialize database.
 | 
			
		||||
//        Database db = new Database("database/initializer.sqlite");
 | 
			
		||||
//        db.initialize();
 | 
			
		||||
//        for (StudentTeam team : studentTeams) {
 | 
			
		||||
//            for (Student student : team.getStudents()) {
 | 
			
		||||
//                db.storeStudent(student);
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		|||
import jdk.nashorn.internal.ir.annotations.Ignore;
 | 
			
		||||
import nl.andrewlalis.model.Student;
 | 
			
		||||
import nl.andrewlalis.model.StudentTeam;
 | 
			
		||||
import nl.andrewlalis.model.TATeam;
 | 
			
		||||
import org.apache.http.HttpResponse;
 | 
			
		||||
import org.apache.http.client.methods.HttpPatch;
 | 
			
		||||
import org.apache.http.entity.StringEntity;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,18 +27,6 @@ public class GithubManager {
 | 
			
		|||
     * The assignments repository where students will get assignments from.
 | 
			
		||||
     */
 | 
			
		||||
    private GHRepository assignmentsRepo;
 | 
			
		||||
    private String assignmentsRepoName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The name of the team which contains all teaching assistants.
 | 
			
		||||
     */
 | 
			
		||||
    private String teachingAssistantsTeamName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The prefix used to prepend the names of student repositories.
 | 
			
		||||
     * Should ideally contain the current school year.
 | 
			
		||||
     */
 | 
			
		||||
    private String studentRepoPrefix;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Github object for API interactions.
 | 
			
		||||
| 
						 | 
				
			
			@ -54,12 +43,8 @@ public class GithubManager {
 | 
			
		|||
        logger.setParent(Logger.getGlobal());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public GithubManager(String organizationName, String accessToken, String assignmentsRepo, String teachingAssistantsTeamName, String studentRepoPrefix) {
 | 
			
		||||
        this.assignmentsRepoName = assignmentsRepo;
 | 
			
		||||
        this.teachingAssistantsTeamName = teachingAssistantsTeamName;
 | 
			
		||||
        this.studentRepoPrefix = studentRepoPrefix;
 | 
			
		||||
    public GithubManager(String organizationName, String accessToken) {
 | 
			
		||||
        this.accessToken = accessToken;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            this.github = GitHub.connectUsingOAuth(accessToken);
 | 
			
		||||
            this.organization = this.github.getOrganization(organizationName);
 | 
			
		||||
| 
						 | 
				
			
			@ -80,57 +65,59 @@ public class GithubManager {
 | 
			
		|||
     * - adds students to repository
 | 
			
		||||
     * - adds all students to assignments repository.
 | 
			
		||||
     * @param studentTeams The list of student studentTeams.
 | 
			
		||||
     * @param teamAll The team of all teaching assistants.
 | 
			
		||||
     * @param assignmentsRepoName The name of the assignments repo.
 | 
			
		||||
     * @throws Exception If an error occurs while initializing the github repositories.
 | 
			
		||||
     */
 | 
			
		||||
    public void initializeGithubRepos(List<StudentTeam> studentTeams) throws Exception {
 | 
			
		||||
        GHTeam teamAll = this.organization.getTeamByName(this.teachingAssistantsTeamName);
 | 
			
		||||
 | 
			
		||||
        this.setupAssignmentsRepo(teamAll);
 | 
			
		||||
    public void initializeGithubRepos(List<StudentTeam> studentTeams, TATeam teamAll, String assignmentsRepoName) throws Exception {
 | 
			
		||||
        this.setupAssignmentsRepo(assignmentsRepoName, "fuck the police", teamAll);
 | 
			
		||||
 | 
			
		||||
        StudentTeam t = new StudentTeam();
 | 
			
		||||
        Student s = new Student(3050831, "Andrew Lalis", "andrewlalisofficial@gmail.com", "andrewlalis", null);
 | 
			
		||||
        t.addMember(s);
 | 
			
		||||
        t.setId(42);
 | 
			
		||||
 | 
			
		||||
        this.setupStudentTeam(t, teamAll);
 | 
			
		||||
        this.setupStudentTeam(t, teamAll, "advoop_2018");
 | 
			
		||||
        // TODO: Finish this method.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets up the organization's assignments repository, and grants permissions to all teaching assistants.
 | 
			
		||||
     * @param assignmentsRepoName The name of the assignments repository.
 | 
			
		||||
     * @param description The description of the repository.
 | 
			
		||||
     * @param allTeachingAssistants A team consisting of all teaching assistants.
 | 
			
		||||
     * @throws IOException If an HTTP request failed.
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("deprecation")
 | 
			
		||||
    private void setupAssignmentsRepo(GHTeam allTeachingAssistants) throws IOException {
 | 
			
		||||
    private void setupAssignmentsRepo(String assignmentsRepoName, String description, TATeam allTeachingAssistants) throws IOException {
 | 
			
		||||
        // Check if the repository already exists.
 | 
			
		||||
        GHRepository existingRepo = this.organization.getRepository(this.assignmentsRepoName);
 | 
			
		||||
        GHRepository existingRepo = this.organization.getRepository(assignmentsRepoName);
 | 
			
		||||
        if (existingRepo != null) {
 | 
			
		||||
            existingRepo.delete();
 | 
			
		||||
            logger.fine("Deleted pre-existing assignments repository.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create the repository.
 | 
			
		||||
        GHCreateRepositoryBuilder builder = this.organization.createRepository(this.assignmentsRepoName);
 | 
			
		||||
        GHCreateRepositoryBuilder builder = this.organization.createRepository(assignmentsRepoName);
 | 
			
		||||
        builder.description("Assignments repository for Advanced Object Oriented Programming");
 | 
			
		||||
        builder.wiki(false);
 | 
			
		||||
        builder.issues(true);
 | 
			
		||||
        builder.private_(false); // TODO: Make this true for production.
 | 
			
		||||
        builder.team(allTeachingAssistants);
 | 
			
		||||
        builder.team(allTeachingAssistants.getGithubTeam());
 | 
			
		||||
        builder.gitignoreTemplate("Java");
 | 
			
		||||
        this.assignmentsRepo = builder.create();
 | 
			
		||||
        logger.info("Created assignments repository.");
 | 
			
		||||
 | 
			
		||||
        // Protect the master branch.
 | 
			
		||||
        GHBranchProtectionBuilder protectionBuilder = this.assignmentsRepo.getBranch("master").enableProtection();
 | 
			
		||||
        protectionBuilder.includeAdmins(false);
 | 
			
		||||
        protectionBuilder.restrictPushAccess();
 | 
			
		||||
        protectionBuilder.teamPushAccess(allTeachingAssistants);
 | 
			
		||||
        protectionBuilder.addRequiredChecks("ci/circleci");
 | 
			
		||||
        protectionBuilder.enable();
 | 
			
		||||
        logger.fine("Protected master branch of assignments repository.");
 | 
			
		||||
        this.assignmentsRepo = this.createRepository(assignmentsRepoName, allTeachingAssistants, description, false, true, false);
 | 
			
		||||
 | 
			
		||||
        if (this.assignmentsRepo == null) {
 | 
			
		||||
            logger.severe("Could not create assignments repository.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.protectMasterBranch(this.assignmentsRepo, allTeachingAssistants);
 | 
			
		||||
 | 
			
		||||
        // Grant all teaching assistants write access.
 | 
			
		||||
        allTeachingAssistants.add(this.assignmentsRepo, GHOrganization.Permission.ADMIN);
 | 
			
		||||
        allTeachingAssistants.getGithubTeam().add(this.assignmentsRepo, GHOrganization.Permission.ADMIN);
 | 
			
		||||
        logger.fine("Gave admin rights to all teaching assistants in team: " + allTeachingAssistants.getName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -139,44 +126,27 @@ public class GithubManager {
 | 
			
		|||
     * repository as well.
 | 
			
		||||
     * @param team The student team to set up.
 | 
			
		||||
     * @param taTeam The team of teaching assistants that is responsible for these students.
 | 
			
		||||
     * @param prefix The prefix to append to the front of the repo name.
 | 
			
		||||
     * @throws IOException If an HTTP request fails.
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("deprecation")
 | 
			
		||||
    private void setupStudentTeam(StudentTeam team, GHTeam taTeam) throws IOException {
 | 
			
		||||
        String teamRepoName = team.generateUniqueName(this.studentRepoPrefix);
 | 
			
		||||
 | 
			
		||||
        Student[] students = team.getStudents();
 | 
			
		||||
        StringBuilder description = new StringBuilder("Group ");
 | 
			
		||||
        description.append(team.getId()).append(": ");
 | 
			
		||||
 | 
			
		||||
        for (Student s : students) {
 | 
			
		||||
            description.append(s.getName()).append(' ');
 | 
			
		||||
    private void setupStudentTeam(StudentTeam team, TATeam taTeam, String prefix) throws IOException {
 | 
			
		||||
        // First check that the assignments repo exists, otherwise no invitations can be sent.
 | 
			
		||||
        if (this.assignmentsRepo == null) {
 | 
			
		||||
            logger.warning("Assignments repository must be created before student repositories.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        GHCreateRepositoryBuilder builder = this.organization.createRepository(teamRepoName);
 | 
			
		||||
        builder.team(taTeam);
 | 
			
		||||
        builder.wiki(false);
 | 
			
		||||
        builder.issues(true);
 | 
			
		||||
        builder.description(description.toString());
 | 
			
		||||
        builder.gitignoreTemplate("Java");
 | 
			
		||||
        builder.private_(false); // TODO: Change this to true for production
 | 
			
		||||
        GHRepository repo = builder.create();
 | 
			
		||||
        logger.info("Created repository: " + repo.getName());
 | 
			
		||||
        GHRepository repo = this.createRepository(team.generateUniqueName(prefix), taTeam, team.generateRepoDescription(), false, true, false);
 | 
			
		||||
 | 
			
		||||
        // Protect the master branch.
 | 
			
		||||
        GHBranchProtectionBuilder protectionBuilder = repo.getBranch("master").enableProtection();
 | 
			
		||||
        protectionBuilder.includeAdmins(false);
 | 
			
		||||
        protectionBuilder.teamPushAccess(taTeam);
 | 
			
		||||
        protectionBuilder.addRequiredChecks("ci/circleci");
 | 
			
		||||
        protectionBuilder.enable();
 | 
			
		||||
        logger.fine("Protected master branch of repository: " + repo.getName());
 | 
			
		||||
        if (repo == null) {
 | 
			
		||||
            logger.severe("Repository for student team " + team.getId() + " could not be created.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create development branch.
 | 
			
		||||
        String sha1 = repo.getBranch(repo.getDefaultBranch()).getSHA1();
 | 
			
		||||
        repo.createRef("refs/heads/development", sha1);
 | 
			
		||||
        logger.fine("Created development branch of repository: " + repo.getName());
 | 
			
		||||
        this.protectMasterBranch(repo, taTeam);
 | 
			
		||||
        this.createDevelopmentBranch(repo);
 | 
			
		||||
 | 
			
		||||
        taTeam.add(repo, GHOrganization.Permission.ADMIN);
 | 
			
		||||
        taTeam.getGithubTeam().add(repo, GHOrganization.Permission.ADMIN);
 | 
			
		||||
        logger.fine("Added team " + taTeam.getName() + " as admin to repository: " + repo.getName());
 | 
			
		||||
 | 
			
		||||
        List<GHUser> users = new ArrayList<>();
 | 
			
		||||
| 
						 | 
				
			
			@ -234,4 +204,68 @@ public class GithubManager {
 | 
			
		|||
        logger.info("Archived repository: " + repo.getFullName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Protects the master branch of a given repository, and gives admin rights to the given team.
 | 
			
		||||
     * @param repo The repository to protect the master branch of.
 | 
			
		||||
     * @param team The team which gets admin rights to the master branch.
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("deprecation")
 | 
			
		||||
    private void protectMasterBranch(GHRepository repo, TATeam team) {
 | 
			
		||||
        try {
 | 
			
		||||
            GHBranchProtectionBuilder protectionBuilder = repo.getBranch("master").enableProtection();
 | 
			
		||||
            protectionBuilder.includeAdmins(false);
 | 
			
		||||
            protectionBuilder.restrictPushAccess();
 | 
			
		||||
            protectionBuilder.teamPushAccess(team.getGithubTeam());
 | 
			
		||||
            protectionBuilder.addRequiredChecks("ci/circleci");
 | 
			
		||||
            protectionBuilder.enable();
 | 
			
		||||
            logger.fine("Protected master branch of repository: " + repo.getName());
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a development branch for the given repository.
 | 
			
		||||
     * @param repo The repository to create a development branch for.
 | 
			
		||||
     */
 | 
			
		||||
    private void createDevelopmentBranch(GHRepository repo) {
 | 
			
		||||
        try {
 | 
			
		||||
            String sha1 = repo.getBranch(repo.getDefaultBranch()).getSHA1();
 | 
			
		||||
            repo.createRef("refs/heads/development", sha1);
 | 
			
		||||
            logger.fine("Created development branch of repository: " + repo.getName());
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.severe("Could not create development branch for repository: " + repo.getName() + '\n' + e.getMessage());
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new github repository.
 | 
			
		||||
     * @param name The name of the repository.
 | 
			
		||||
     * @param taTeam The team to give admin rights.
 | 
			
		||||
     * @param description The description of the repository.
 | 
			
		||||
     * @param hasWiki Whether the repo has a wiki enabled.
 | 
			
		||||
     * @param hasIssues Whether the repo has issues enabled.
 | 
			
		||||
     * @param isPrivate Whether or not the repository is private.
 | 
			
		||||
     * @return The repository that was created, or
 | 
			
		||||
     */
 | 
			
		||||
    private GHRepository createRepository(String name, TATeam taTeam, String description, boolean hasWiki, boolean hasIssues, boolean isPrivate){
 | 
			
		||||
        try {
 | 
			
		||||
            GHCreateRepositoryBuilder builder = this.organization.createRepository(name);
 | 
			
		||||
            builder.team(taTeam.getGithubTeam());
 | 
			
		||||
            builder.wiki(hasWiki);
 | 
			
		||||
            builder.issues(hasIssues);
 | 
			
		||||
            builder.description(description);
 | 
			
		||||
            builder.gitignoreTemplate("Java");
 | 
			
		||||
            builder.private_(isPrivate); // TODO: Change this to true for production
 | 
			
		||||
            GHRepository repo = builder.create();
 | 
			
		||||
            logger.fine("Created repository: " + repo.getName());
 | 
			
		||||
            return repo;
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.severe("Could not create repository: " + name + '\n' + e.getMessage());
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,9 +52,22 @@ public class StudentTeam extends Team{
 | 
			
		|||
    public String generateUniqueName(String prefix) {
 | 
			
		||||
        StringBuilder sb = new StringBuilder(prefix);
 | 
			
		||||
        sb.append("_team_").append(this.id);
 | 
			
		||||
        for (Student s : (Student[]) this.getMembers()) {
 | 
			
		||||
        for (Student s : this.getStudents()) {
 | 
			
		||||
            sb.append('_').append(s.getNumber());
 | 
			
		||||
        }
 | 
			
		||||
        return sb.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a description for the repository, based on the students' names and group number.
 | 
			
		||||
     * @return A description for the students' repository.
 | 
			
		||||
     */
 | 
			
		||||
    public String generateRepoDescription() {
 | 
			
		||||
        StringBuilder sb = new StringBuilder();
 | 
			
		||||
        sb.append("Group ").append(this.id).append(": ");
 | 
			
		||||
        for (Student s : this.getStudents()) {
 | 
			
		||||
            sb.append(s.getName()).append(' ');
 | 
			
		||||
        }
 | 
			
		||||
        return sb.toString();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,7 @@
 | 
			
		|||
package nl.andrewlalis.model;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonCreator;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonProperty;
 | 
			
		||||
import org.kohsuke.github.GHOrganization;
 | 
			
		||||
import org.kohsuke.github.GHTeam;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +24,11 @@ public class TATeam {
 | 
			
		|||
     */
 | 
			
		||||
    private int id;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The Github team associated with this team.
 | 
			
		||||
     */
 | 
			
		||||
    private GHTeam githubTeam;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a team without any teaching assistant members.
 | 
			
		||||
     * @param name The name of the team.
 | 
			
		||||
| 
						 | 
				
			
			@ -58,4 +62,11 @@ public class TATeam {
 | 
			
		|||
        return this.name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public GHTeam getGithubTeam() {
 | 
			
		||||
        return this.githubTeam;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setGithubTeam(GHTeam team) {
 | 
			
		||||
        this.githubTeam = team;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,6 @@
 | 
			
		|||
package nl.andrewlalis.model.database;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.model.Person;
 | 
			
		||||
import nl.andrewlalis.model.Student;
 | 
			
		||||
import nl.andrewlalis.model.TeachingAssistant;
 | 
			
		||||
import nl.andrewlalis.model.Team;
 | 
			
		||||
import nl.andrewlalis.model.*;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.DriverManager;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,8 +21,8 @@ public class Database {
 | 
			
		|||
    private static final int TEAM_TYPE_TA = 1;
 | 
			
		||||
    private static final int TEAM_TYPE_TA_ALL = 2;
 | 
			
		||||
 | 
			
		||||
    private static final int TEAM_NONE = 0;
 | 
			
		||||
    private static final int TEAM_TA_ALL = 1;
 | 
			
		||||
    private static final int TEAM_NONE = 1000000;
 | 
			
		||||
    private static final int TEAM_TA_ALL = 1000001;
 | 
			
		||||
 | 
			
		||||
    private static final int ERROR_TYPE_TEAM = 0;
 | 
			
		||||
    private static final int ERROR_TYPE_PERSON = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +154,25 @@ public class Database {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stores a list of student teams in the database.
 | 
			
		||||
     * @param teams The list of teams to store.
 | 
			
		||||
     * @return True if successful, or false if an error occurred.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean storeStudentTeams(List<StudentTeam> teams) {
 | 
			
		||||
        for (StudentTeam team : teams) {
 | 
			
		||||
            if (!this.storeTeam(team, TEAM_TYPE_STUDENT)) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            for (Student student : team.getStudents()) {
 | 
			
		||||
                if (!this.storeStudent(student, team.getId())) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stores a student without a team.
 | 
			
		||||
     * @param student The student to store.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,9 @@ import java.util.Date;
 | 
			
		|||
import java.util.logging.Handler;
 | 
			
		||||
import java.util.logging.LogRecord;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A custom handler for printing log messages to the user interface text output pane.
 | 
			
		||||
 */
 | 
			
		||||
public class OutputTextHandler extends Handler {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
package nl.andrewlalis.ui.control.command;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +34,7 @@ public class CommandExecutor {
 | 
			
		|||
     */
 | 
			
		||||
    public void registerCommand(String commandName, Executable executable) {
 | 
			
		||||
        this.commands.put(commandName, executable);
 | 
			
		||||
        logger.fine("Registered command: " + commandName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +42,7 @@ public class CommandExecutor {
 | 
			
		|||
     * @param commandString The String command and any arguments that go with it.
 | 
			
		||||
     */
 | 
			
		||||
    public void executeString(String commandString) {
 | 
			
		||||
        String[] words = commandString.trim().toLowerCase().split(" ");
 | 
			
		||||
        String[] words = commandString.trim().split(" ");
 | 
			
		||||
        if (words.length < 1) {
 | 
			
		||||
            logger.warning("No command supplied.");
 | 
			
		||||
            return;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,9 +52,19 @@ public class CommandExecutor {
 | 
			
		|||
        if (words.length > 1) {
 | 
			
		||||
            System.arraycopy(words, 1, args, 0, words.length - 1);
 | 
			
		||||
        }
 | 
			
		||||
        this.executeCommand(commandName, args);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Executes a command with the given name, and given arguments.
 | 
			
		||||
     * @param commandName The name of the command. A command must be registered using registerCommand before it can be
 | 
			
		||||
     *                    called here.
 | 
			
		||||
     * @param args The list of arguments to provide to the command as needed by the executable that was registered.
 | 
			
		||||
     */
 | 
			
		||||
    public void executeCommand(String commandName, String[] args) {
 | 
			
		||||
        if (this.commands.containsKey(commandName)) {
 | 
			
		||||
            logger.info(commandName + ' ' + Arrays.toString(args));
 | 
			
		||||
            this.commands.get(commandName).execute(args);
 | 
			
		||||
            logger.info(commandString);
 | 
			
		||||
        } else {
 | 
			
		||||
            logger.warning(commandName + " is not a valid command.");
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
package nl.andrewlalis.ui.control.command.executables;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.git_api.GithubManager;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents the action archive all repositories with a certain substring in their name.
 | 
			
		||||
 * It takes the following arguments:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Organization name
 | 
			
		||||
 * 2. Access Token
 | 
			
		||||
 * 3. Repo substring to archive by
 | 
			
		||||
 */
 | 
			
		||||
public class ArchiveRepos extends GithubExecutable {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected boolean executeWithManager(GithubManager manager, String[] args) {
 | 
			
		||||
        if (args.length < 1) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            manager.archiveAllRepositories(args[0]);
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
package nl.andrewlalis.ui.control.command.executables;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.git_api.GithubManager;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.Executable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents an executable which interacts with github, and therefore needs access to a Github
 | 
			
		||||
 * manager to execute.
 | 
			
		||||
 *
 | 
			
		||||
 * Requires two arguments:
 | 
			
		||||
 * 1. The organization name.
 | 
			
		||||
 * 2. The organization's access token.
 | 
			
		||||
 */
 | 
			
		||||
public abstract class GithubExecutable implements Executable {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean execute(String[] args) {
 | 
			
		||||
        if (args.length < 2) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        String[] extraArgs = new String[args.length-2];
 | 
			
		||||
        System.arraycopy(args, 2, extraArgs, 0, args.length-2);
 | 
			
		||||
        GithubManager manager = new GithubManager(args[0], args[1]);
 | 
			
		||||
        return this.executeWithManager(manager, extraArgs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Executes a command and provides a github manager with which to perform operations.
 | 
			
		||||
     * @param manager The GithubManager used to perform actions on the repositories.
 | 
			
		||||
     * @param args Any additional arguments provided to the executable.
 | 
			
		||||
     * @return True if successful, or false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    protected abstract boolean executeWithManager(GithubManager manager, String[] args);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
package nl.andrewlalis.ui.control.command.executables;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.model.StudentTeam;
 | 
			
		||||
import nl.andrewlalis.model.database.Database;
 | 
			
		||||
import nl.andrewlalis.ui.control.command.Executable;
 | 
			
		||||
import nl.andrewlalis.util.FileUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Execute this class to read students from a supplied filename and teamsize, and store their
 | 
			
		||||
 * information in the database.
 | 
			
		||||
 */
 | 
			
		||||
public class ReadStudentsFileToDB implements Executable {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The database used to store the students.
 | 
			
		||||
     */
 | 
			
		||||
    private Database db;
 | 
			
		||||
 | 
			
		||||
    public ReadStudentsFileToDB(Database db) {
 | 
			
		||||
        this.db = db;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean execute(String[] args) {
 | 
			
		||||
        if (args.length < 2) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        String filename = args[0];
 | 
			
		||||
        int teamSize = Integer.parseUnsignedInt(args[1]);
 | 
			
		||||
        List<StudentTeam> teams = FileUtils.getStudentTeamsFromCSV(filename, teamSize);
 | 
			
		||||
        return this.db.storeStudentTeams(teams);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ public class CommandFieldKeyListener implements KeyListener {
 | 
			
		|||
    /**
 | 
			
		||||
     * This is responsible for parsing and running entered commands.
 | 
			
		||||
     */
 | 
			
		||||
    CommandExecutor executor;
 | 
			
		||||
    private CommandExecutor executor;
 | 
			
		||||
 | 
			
		||||
    public CommandFieldKeyListener(CommandExecutor executor) {
 | 
			
		||||
        this.executor = executor;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import nl.andrewlalis.ui.control.OutputTextHandler;
 | 
			
		|||
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
import java.awt.*;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +29,13 @@ public class InitializerApp extends JFrame {
 | 
			
		|||
     */
 | 
			
		||||
    private OutputTextPane outputTextPane;
 | 
			
		||||
 | 
			
		||||
    private JTextField organizationField = new JTextField();
 | 
			
		||||
    private JTextField accessTokenField = new JTextField();
 | 
			
		||||
    private JTextField assignmentsRepoField = new JTextField();
 | 
			
		||||
    private JTextField teachingAssistantsField = new JTextField();
 | 
			
		||||
    private JTextField studentRepoField = new JTextField();
 | 
			
		||||
    private JTextField teamSizeField = new JTextField();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The executor responsible for performing meaningful actions.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +61,9 @@ public class InitializerApp extends JFrame {
 | 
			
		|||
     */
 | 
			
		||||
    private void initLoggingHandler() {
 | 
			
		||||
        Logger logger = Logger.getGlobal();
 | 
			
		||||
        logger.addHandler(new OutputTextHandler(this.outputTextPane));
 | 
			
		||||
        OutputTextHandler handler = new OutputTextHandler(this.outputTextPane);
 | 
			
		||||
        handler.setLevel(Level.FINE);
 | 
			
		||||
        logger.addHandler(handler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -68,12 +78,42 @@ public class InitializerApp extends JFrame {
 | 
			
		|||
 | 
			
		||||
        mainPanel.add(this.initCommandPanel(), BorderLayout.CENTER);
 | 
			
		||||
        mainPanel.add(this.initRepoPanel(), BorderLayout.WEST);
 | 
			
		||||
        mainPanel.add(this.initGithubManagerPanel(), BorderLayout.EAST);
 | 
			
		||||
 | 
			
		||||
        this.setContentPane(mainPanel);
 | 
			
		||||
 | 
			
		||||
        this.initLoggingHandler();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return A JPanel containing input for all fields needed to connect to github, plus some commonly used buttons
 | 
			
		||||
     * which perform actions, as shortcuts for command actions.
 | 
			
		||||
     */
 | 
			
		||||
    private JPanel initGithubManagerPanel() {
 | 
			
		||||
        JPanel githubManagerPanel = new JPanel(new BorderLayout());
 | 
			
		||||
 | 
			
		||||
        // Information input (org name, key, etc.)
 | 
			
		||||
        JPanel infoInputPanel = new JPanel();
 | 
			
		||||
        infoInputPanel.setLayout(new BoxLayout(infoInputPanel, BoxLayout.PAGE_AXIS));
 | 
			
		||||
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("Organization Name", this.organizationField));
 | 
			
		||||
        this.organizationField.setText("InitializerTesting");
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("Access Token", this.accessTokenField));
 | 
			
		||||
        this.accessTokenField.setText("d3699963f23cee85fe44c42f66057acc98c9ec7a");
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("Assignments Repo Name", this.assignmentsRepoField));
 | 
			
		||||
        this.assignmentsRepoField.setText("assignments_2018");
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("TA-All Team Name", this.teachingAssistantsField));
 | 
			
		||||
        this.teachingAssistantsField.setText("teaching-assistants");
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("Student Repo Prefix", this.studentRepoField));
 | 
			
		||||
        this.studentRepoField.setText("advoop_2018");
 | 
			
		||||
        infoInputPanel.add(generateTextFieldPanel("Team Size", this.teamSizeField));
 | 
			
		||||
        this.teamSizeField.setText("2");
 | 
			
		||||
 | 
			
		||||
        githubManagerPanel.add(infoInputPanel, BorderLayout.NORTH);
 | 
			
		||||
 | 
			
		||||
        return githubManagerPanel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return A JPanel containing the command prompt field and output text pane.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +123,7 @@ public class InitializerApp extends JFrame {
 | 
			
		|||
        this.outputTextPane = new OutputTextPane();
 | 
			
		||||
        JScrollPane scrollPane = new JScrollPane(this.outputTextPane);
 | 
			
		||||
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
 | 
			
		||||
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 | 
			
		||||
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 | 
			
		||||
        // Text enter field and label.
 | 
			
		||||
        JPanel textEnterPanel = new JPanel(new BorderLayout());
 | 
			
		||||
        textEnterPanel.setBorder(BorderFactory.createLoweredBevelBorder());
 | 
			
		||||
| 
						 | 
				
			
			@ -111,4 +151,18 @@ public class InitializerApp extends JFrame {
 | 
			
		|||
        return repoPanel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a text input field panel.
 | 
			
		||||
     * @param labelText The text for the label above the panel.
 | 
			
		||||
     * @param textField A reference to the text field that is used in the panel.
 | 
			
		||||
     * @return A JPanel containing the label and text field.
 | 
			
		||||
     */
 | 
			
		||||
    private JPanel generateTextFieldPanel(String labelText, JTextField textField) {
 | 
			
		||||
        JPanel newPanel = new JPanel(new BorderLayout());
 | 
			
		||||
        newPanel.add(new JLabel(labelText), BorderLayout.NORTH);
 | 
			
		||||
        newPanel.add(textField);
 | 
			
		||||
        newPanel.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2));
 | 
			
		||||
        return newPanel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,13 +47,13 @@ public class FileUtils {
 | 
			
		|||
     * @return A list of student teams.
 | 
			
		||||
     */
 | 
			
		||||
    public static List<StudentTeam> getStudentTeamsFromCSV(String filename, int teamSize) {
 | 
			
		||||
        List<StudentTeam> studentTeams = null;
 | 
			
		||||
        List<StudentTeam> studentTeams;
 | 
			
		||||
        try {
 | 
			
		||||
            studentTeams = TeamGenerator.generateFromCSV(filename, teamSize);
 | 
			
		||||
            logger.fine("Teams created:\n" + studentTeams);
 | 
			
		||||
            return studentTeams;
 | 
			
		||||
        } catch (IOException | ArrayIndexOutOfBoundsException e) {
 | 
			
		||||
            logger.severe("Unable to generate studentTeams from CSV file, exiting.");
 | 
			
		||||
            logger.severe("Unable to generate studentTeams from CSV file, exiting. " + e.getMessage());
 | 
			
		||||
            System.exit(1);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,8 @@ VALUES (0, 'student_team'),
 | 
			
		|||
       (3, 'none');
 | 
			
		||||
 | 
			
		||||
INSERT INTO teams (id, team_type_id)
 | 
			
		||||
VALUES (0, 3), -- None team for all students or TA's without a team.
 | 
			
		||||
       (1, 2); -- Team for all teaching assistants.
 | 
			
		||||
VALUES (1000000, 3), -- None team for all students or TA's without a team.
 | 
			
		||||
       (1000001, 2); -- Team for all teaching assistants.
 | 
			
		||||
 | 
			
		||||
INSERT INTO error_types (id, name)
 | 
			
		||||
VALUES (0, 'team_error'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue