Adds more than just a TA dialog #4
			
				
			
		
		
		
	| 
						 | 
					@ -31,21 +31,23 @@ public class Main {
 | 
				
			||||||
        // Command executor which will be used by all actions the user can do.
 | 
					        // Command executor which will be used by all actions the user can do.
 | 
				
			||||||
        CommandExecutor executor = new CommandExecutor();
 | 
					        CommandExecutor executor = new CommandExecutor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Main application model.
 | 
					        // Main application model is stored as a static variable that is accessible everywhere.
 | 
				
			||||||
        Organization organization = new Organization();
 | 
					        InitializerApp.organization = new Organization();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Initialize User Interface.
 | 
					        // Initialize User Interface.
 | 
				
			||||||
        InitializerApp app = new InitializerApp(executor, organization);
 | 
					        InitializerApp app = new InitializerApp(executor);
 | 
				
			||||||
        app.begin();
 | 
					        app.begin();
 | 
				
			||||||
        app.setAccessToken(userOptions.get("token"));
 | 
					        app.setAccessToken(userOptions.get("token"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Initialize executable commands.
 | 
					        // Initialize executable commands.
 | 
				
			||||||
        executor.registerCommand("read_students", new ReadStudentsFile(organization));
 | 
					        executor.registerCommand("read_students", new ReadStudentsFile(InitializerApp.organization));
 | 
				
			||||||
        executor.registerCommand("archive_all", new ArchiveRepos());
 | 
					        executor.registerCommand("archive_all", new ArchiveRepos());
 | 
				
			||||||
        executor.registerCommand("generate_assignments", new GenerateAssignmentsRepo());
 | 
					        executor.registerCommand("generate_assignments", new GenerateAssignmentsRepo());
 | 
				
			||||||
        executor.registerCommand("define_ta_teams", new DefineTaTeams(app));
 | 
					        executor.registerCommand("define_ta_teams", new DefineTaTeams(app));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        logger.info("GithubManager for Github Repositories in Educational Organizations. Program initialized.");
 | 
					        logger.info("GithubManager for Github Repositories in Educational Organizations.\n" +
 | 
				
			||||||
 | 
					                "© Andrew Lalis (2018), All rights reserved.\n" +
 | 
				
			||||||
 | 
					                "Program initialized.");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,13 @@ package nl.andrewlalis.git_api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
					import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
					import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
				
			||||||
import nl.andrewlalis.model.*;
 | 
					import nl.andrewlalis.model.Student;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.StudentTeam;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.TATeam;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.TeachingAssistant;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Error;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Severity;
 | 
				
			||||||
 | 
					import nl.andrewlalis.ui.view.InitializerApp;
 | 
				
			||||||
import org.apache.http.HttpResponse;
 | 
					import org.apache.http.HttpResponse;
 | 
				
			||||||
import org.apache.http.client.methods.HttpPatch;
 | 
					import org.apache.http.client.methods.HttpPatch;
 | 
				
			||||||
import org.apache.http.entity.StringEntity;
 | 
					import org.apache.http.entity.StringEntity;
 | 
				
			||||||
| 
						 | 
					@ -81,7 +87,7 @@ public class GithubManager {
 | 
				
			||||||
    public List<TeachingAssistant> getMembers() {
 | 
					    public List<TeachingAssistant> getMembers() {
 | 
				
			||||||
        List<TeachingAssistant> teachingAssistants = new ArrayList<>();
 | 
					        List<TeachingAssistant> teachingAssistants = new ArrayList<>();
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            for (GHUser member : this.organization.getMembers()) {
 | 
					            for (GHUser member : this.organization.listMembers().asList()) {
 | 
				
			||||||
                teachingAssistants.add(new TeachingAssistant(-1, member.getName(), member.getEmail(), member.getLogin()));
 | 
					                teachingAssistants.add(new TeachingAssistant(-1, member.getName(), member.getEmail(), member.getLogin()));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
| 
						 | 
					@ -91,34 +97,6 @@ public class GithubManager {
 | 
				
			||||||
        return teachingAssistants;
 | 
					        return teachingAssistants;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 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
 | 
					 | 
				
			||||||
     * - 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, TATeam teamAll, String assignmentsRepoName) throws Exception {
 | 
					 | 
				
			||||||
        this.setupAssignmentsRepo(assignmentsRepoName, "fuck the police", teamAll.getName());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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.getGithubTeam(), "advoop_2018");
 | 
					 | 
				
			||||||
        // TODO: Finish this method.
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets up the organization's assignments repository, and grants permissions to all teaching assistants.
 | 
					     * Sets up the organization's assignments repository, and grants permissions to all teaching assistants.
 | 
				
			||||||
     * @param assignmentsRepoName The name of the assignments repository.
 | 
					     * @param assignmentsRepoName The name of the assignments repository.
 | 
				
			||||||
| 
						 | 
					@ -131,6 +109,7 @@ public class GithubManager {
 | 
				
			||||||
        // Check if the repository already exists.
 | 
					        // Check if the repository already exists.
 | 
				
			||||||
        GHRepository existingRepo = this.organization.getRepository(assignmentsRepoName);
 | 
					        GHRepository existingRepo = this.organization.getRepository(assignmentsRepoName);
 | 
				
			||||||
        if (existingRepo != null) {
 | 
					        if (existingRepo != null) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.MINOR, "Assignments repository already existed, deleting it."));
 | 
				
			||||||
            existingRepo.delete();
 | 
					            existingRepo.delete();
 | 
				
			||||||
            logger.fine("Deleted pre-existing assignments repository.");
 | 
					            logger.fine("Deleted pre-existing assignments repository.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -155,46 +134,45 @@ public class GithubManager {
 | 
				
			||||||
     * @param team The student team to set up.
 | 
					     * @param team The student team to set up.
 | 
				
			||||||
     * @param taTeam The team of teaching assistants that is responsible for these students.
 | 
					     * @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.
 | 
					     * @param prefix The prefix to append to the front of the repo name.
 | 
				
			||||||
     * @throws IOException If an HTTP request fails.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void setupStudentTeam(StudentTeam team, GHTeam taTeam, String prefix) throws IOException {
 | 
					    public void setupStudentTeam(StudentTeam team, TATeam taTeam, String prefix) {
 | 
				
			||||||
        // First check that the assignments repo exists, otherwise no invitations can be sent.
 | 
					        // First check that the assignments repo exists, otherwise no invitations can be sent.
 | 
				
			||||||
        if (this.assignmentsRepo == null) {
 | 
					        if (this.assignmentsRepo == null) {
 | 
				
			||||||
            logger.warning("Assignments repository must be created before student repositories.");
 | 
					            logger.warning("Assignments repository must be created before student repositories.");
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        GHRepository repo = this.createRepository(team.generateUniqueName(prefix), taTeam, team.generateRepoDescription(), false, true, false);
 | 
					        GHRepository repo = this.createRepository(team.generateUniqueName(prefix), taTeam.getGithubTeam(), team.generateRepoDescription(), false, true, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (repo == null) {
 | 
					        if (repo == null) {
 | 
				
			||||||
            logger.severe("Repository for student team " + team.getId() + " could not be created.");
 | 
					            logger.severe("Repository for student team " + team.getId() + " could not be created.");
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.protectMasterBranch(repo, taTeam);
 | 
					        this.protectMasterBranch(repo, taTeam.getGithubTeam());
 | 
				
			||||||
        this.createDevelopmentBranch(repo);
 | 
					        this.createDevelopmentBranch(repo);
 | 
				
			||||||
 | 
					        this.addTATeamAsAdmin(repo, taTeam.getGithubTeam());
 | 
				
			||||||
 | 
					        this.inviteStudentsToRepos(team, repo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        taTeam.add(repo, GHOrganization.Permission.ADMIN);
 | 
					        team.setRepository(repo);
 | 
				
			||||||
        logger.fine("Added team " + taTeam.getName() + " as admin to repository: " + repo.getName());
 | 
					        team.setTaTeam(taTeam);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        List<GHUser> users = new ArrayList<>();
 | 
					 | 
				
			||||||
        for (Student student : team.getStudents()) {
 | 
					 | 
				
			||||||
            GHUser user = this.github.getUser(student.getGithubUsername());
 | 
					 | 
				
			||||||
            users.add(user);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        repo.addCollaborators(users);
 | 
					 | 
				
			||||||
        this.assignmentsRepo.addCollaborators(users);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Deletes all repositories in the organization.
 | 
					     * Deletes all repositories in the organization.
 | 
				
			||||||
     * @throws IOException if an error occurs with sending requests.
 | 
					     * @param substring The substring which repository names should contain to be deleted.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void deleteAllRepositories() throws IOException {
 | 
					    public void deleteAllRepositories(String substring) {
 | 
				
			||||||
        List<GHRepository> repositories = this.organization.listRepositories().asList();
 | 
					        List<GHRepository> repositories = this.organization.listRepositories().asList();
 | 
				
			||||||
        for (GHRepository repo : repositories) {
 | 
					        for (GHRepository repo : repositories) {
 | 
				
			||||||
            repo.delete();
 | 
					            if (repo.getName().contains(substring)) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    repo.delete();
 | 
				
			||||||
 | 
					                } catch (IOException e) {
 | 
				
			||||||
 | 
					                    InitializerApp.organization.addError(new Error(Severity.HIGH, "Could not delete repository: " + repo.getName()));
 | 
				
			||||||
 | 
					                    e.printStackTrace();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +180,7 @@ public class GithubManager {
 | 
				
			||||||
     * Archives all repositories whose name contains the given substring.
 | 
					     * Archives all repositories whose name contains the given substring.
 | 
				
			||||||
     * @param sub Any repository containing this substring will be archived.
 | 
					     * @param sub Any repository containing this substring will be archived.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void archiveAllRepositories(String sub) throws IOException {
 | 
					    public void archiveAllRepositories(String sub) {
 | 
				
			||||||
        List<GHRepository> repositories = this.organization.listRepositories().asList();
 | 
					        List<GHRepository> repositories = this.organization.listRepositories().asList();
 | 
				
			||||||
        for (GHRepository repo : repositories) {
 | 
					        for (GHRepository repo : repositories) {
 | 
				
			||||||
            if (repo.getName().contains(sub)) {
 | 
					            if (repo.getName().contains(sub)) {
 | 
				
			||||||
| 
						 | 
					@ -215,21 +193,61 @@ public class GithubManager {
 | 
				
			||||||
     * Archives a repository so that it can no longer be manipulated.
 | 
					     * Archives a repository so that it can no longer be manipulated.
 | 
				
			||||||
     * TODO: Change to using Github API instead of Apache HttpUtils.
 | 
					     * TODO: Change to using Github API instead of Apache HttpUtils.
 | 
				
			||||||
     * @param repo The repository to archive.
 | 
					     * @param repo The repository to archive.
 | 
				
			||||||
     * @throws IOException If an error occurs with the HTTP request.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void archiveRepository(GHRepository repo) throws IOException {
 | 
					    private void archiveRepository(GHRepository repo) {
 | 
				
			||||||
        HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.accessToken);
 | 
					        try {
 | 
				
			||||||
        CloseableHttpClient client = HttpClientBuilder.create().build();
 | 
					            HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.accessToken);
 | 
				
			||||||
        ObjectMapper mapper = new ObjectMapper();
 | 
					            CloseableHttpClient client = HttpClientBuilder.create().build();
 | 
				
			||||||
        ObjectNode root = mapper.createObjectNode();
 | 
					            ObjectMapper mapper = new ObjectMapper();
 | 
				
			||||||
        root.put("archived", true);
 | 
					            ObjectNode root = mapper.createObjectNode();
 | 
				
			||||||
        String json = mapper.writeValueAsString(root);
 | 
					            root.put("archived", true);
 | 
				
			||||||
        patch.setEntity(new StringEntity(json));
 | 
					            String json = mapper.writeValueAsString(root);
 | 
				
			||||||
        HttpResponse response = client.execute(patch);
 | 
					            patch.setEntity(new StringEntity(json));
 | 
				
			||||||
        if (response.getStatusLine().getStatusCode() != 200) {
 | 
					            HttpResponse response = client.execute(patch);
 | 
				
			||||||
            throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
 | 
					            if (response.getStatusLine().getStatusCode() != 200) {
 | 
				
			||||||
 | 
					                throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            logger.info("Archived repository: " + repo.getFullName());
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.HIGH, "Could not archive repository: " + repo.getName()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Invites students in a team to their repository, and the assignments repository.
 | 
				
			||||||
 | 
					     * @param team The team of students to invite as collaborators.
 | 
				
			||||||
 | 
					     * @param repo The repository created for the students.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void inviteStudentsToRepos(StudentTeam team, GHRepository repo) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            logger.finest("Adding students from team: " + team.getId() + " as collaborators.");
 | 
				
			||||||
 | 
					            List<GHUser> users = new ArrayList<>();
 | 
				
			||||||
 | 
					            for (Student student : team.getStudents()) {
 | 
				
			||||||
 | 
					                GHUser user = this.github.getUser(student.getGithubUsername());
 | 
				
			||||||
 | 
					                users.add(user);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            repo.addCollaborators(users);
 | 
				
			||||||
 | 
					            this.assignmentsRepo.addCollaborators(users);
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.HIGH, "Students in team: " + team + " could not be added as collaborators to assignments repo or their repository."));
 | 
				
			||||||
 | 
					            logger.warning("Could not add students as collaborators to assignments or their repo.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Adds a teaching assistant team as admins to a particular student repository.
 | 
				
			||||||
 | 
					     * @param studentRepo The student repository.
 | 
				
			||||||
 | 
					     * @param taTeam The team to give admin rights.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void addTATeamAsAdmin(GHRepository studentRepo, GHTeam taTeam) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            taTeam.add(studentRepo, GHOrganization.Permission.ADMIN);
 | 
				
			||||||
 | 
					            logger.fine("Added team " + taTeam.getName() + " as admin to repository: " + studentRepo.getName());
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.HIGH, "Could not add TA Team: " + taTeam.getName() + " as ADMIN to repository: " + studentRepo.getName()));
 | 
				
			||||||
 | 
					            logger.severe("Could not add TA Team: " + taTeam.getName() + " as admins to repository: " + studentRepo.getName());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        logger.info("Archived repository: " + repo.getFullName());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -248,6 +266,7 @@ public class GithubManager {
 | 
				
			||||||
            protectionBuilder.enable();
 | 
					            protectionBuilder.enable();
 | 
				
			||||||
            logger.fine("Protected master branch of repository: " + repo.getName());
 | 
					            logger.fine("Protected master branch of repository: " + repo.getName());
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.HIGH, "Could not protect master branch of repository: " + repo.getName()));
 | 
				
			||||||
            logger.severe("Could not protect master branch of repository: " + repo.getName());
 | 
					            logger.severe("Could not protect master branch of repository: " + repo.getName());
 | 
				
			||||||
            e.printStackTrace();
 | 
					            e.printStackTrace();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -263,6 +282,7 @@ public class GithubManager {
 | 
				
			||||||
            repo.createRef("refs/heads/development", sha1);
 | 
					            repo.createRef("refs/heads/development", sha1);
 | 
				
			||||||
            logger.fine("Created development branch of repository: " + repo.getName());
 | 
					            logger.fine("Created development branch of repository: " + repo.getName());
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.HIGH, "Could not create development branch of repository: " + repo.getName()));
 | 
				
			||||||
            logger.severe("Could not create development branch for repository: " + repo.getName() + '\n' + e.getMessage());
 | 
					            logger.severe("Could not create development branch for repository: " + repo.getName() + '\n' + e.getMessage());
 | 
				
			||||||
            e.printStackTrace();
 | 
					            e.printStackTrace();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -276,7 +296,7 @@ public class GithubManager {
 | 
				
			||||||
     * @param hasWiki Whether the repo has a wiki enabled.
 | 
					     * @param hasWiki Whether the repo has a wiki enabled.
 | 
				
			||||||
     * @param hasIssues Whether the repo has issues enabled.
 | 
					     * @param hasIssues Whether the repo has issues enabled.
 | 
				
			||||||
     * @param isPrivate Whether or not the repository is private.
 | 
					     * @param isPrivate Whether or not the repository is private.
 | 
				
			||||||
     * @return The repository that was created, or
 | 
					     * @return The repository that was created, or null if it could not be created.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private GHRepository createRepository(String name, GHTeam taTeam, String description, boolean hasWiki, boolean hasIssues, boolean isPrivate){
 | 
					    private GHRepository createRepository(String name, GHTeam taTeam, String description, boolean hasWiki, boolean hasIssues, boolean isPrivate){
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
| 
						 | 
					@ -286,12 +306,13 @@ public class GithubManager {
 | 
				
			||||||
            builder.issues(hasIssues);
 | 
					            builder.issues(hasIssues);
 | 
				
			||||||
            builder.description(description);
 | 
					            builder.description(description);
 | 
				
			||||||
            builder.gitignoreTemplate("Java");
 | 
					            builder.gitignoreTemplate("Java");
 | 
				
			||||||
            builder.private_(isPrivate); // TODO: Change this to true for production
 | 
					            builder.private_(isPrivate);
 | 
				
			||||||
            GHRepository repo = builder.create();
 | 
					            GHRepository repo = builder.create();
 | 
				
			||||||
            logger.fine("Created repository: " + repo.getName());
 | 
					            logger.fine("Created repository: " + repo.getName());
 | 
				
			||||||
            return repo;
 | 
					            return repo;
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            logger.severe("Could not create repository: " + name + '\n' + e.getMessage());
 | 
					            logger.severe("Could not create repository: " + name + '\n' + e.getMessage());
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.CRITICAL, "Could not create repository: " + name));
 | 
				
			||||||
            e.printStackTrace();
 | 
					            e.printStackTrace();
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,16 +1,17 @@
 | 
				
			||||||
package nl.andrewlalis.model;
 | 
					package nl.andrewlalis.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.sun.org.apache.xpath.internal.operations.Or;
 | 
					import nl.andrewlalis.model.error.Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Observable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This class represents the overarching model container for the entire application, and holds in memory all student
 | 
					 * This class represents the overarching model container for the entire application, and holds in memory all student
 | 
				
			||||||
 * teams created, teaching assistant teams, and any other state information that would be needed by the user interface
 | 
					 * teams created, teaching assistant teams, and any other state information that would be needed by the user interface
 | 
				
			||||||
 * or runtime executables.
 | 
					 * or runtime executables.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class Organization {
 | 
					public class Organization extends Observable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A list of all student teams in this organization. This is generated from a CSV file supplied after many students
 | 
					     * A list of all student teams in this organization. This is generated from a CSV file supplied after many students
 | 
				
			||||||
| 
						 | 
					@ -18,11 +19,18 @@ public class Organization {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private List<StudentTeam> studentTeams;
 | 
					    private List<StudentTeam> studentTeams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A queue of errors that accumulates as the program runs. These will be output to the user after execution of
 | 
				
			||||||
 | 
					     * critical sections, so that inevitable errors due to input imperfections are not overlooked.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private List<Error> errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a new Organization object with all instance variables initialized to empty values.
 | 
					     * Constructs a new Organization object with all instance variables initialized to empty values.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public Organization() {
 | 
					    public Organization() {
 | 
				
			||||||
        this.studentTeams = new ArrayList<>();
 | 
					        this.studentTeams = new ArrayList<>();
 | 
				
			||||||
 | 
					        this.errors = new ArrayList<>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -38,9 +46,25 @@ public class Organization {
 | 
				
			||||||
        return this.studentTeams;
 | 
					        return this.studentTeams;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<Error> getErrors() {
 | 
				
			||||||
 | 
					        return this.errors;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // SETTERS
 | 
					    // SETTERS
 | 
				
			||||||
    public void setStudentTeams(List<StudentTeam> teams) {
 | 
					    public void setStudentTeams(List<StudentTeam> teams) {
 | 
				
			||||||
        this.studentTeams = teams;
 | 
					        this.studentTeams = teams;
 | 
				
			||||||
 | 
					        this.setChanged();
 | 
				
			||||||
 | 
					        this.notifyObservers();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Adds an error to the list of accumulated errors.
 | 
				
			||||||
 | 
					     * @param newError The newly generated error to add.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void addError(Error newError) {
 | 
				
			||||||
 | 
					        this.errors.add(newError);
 | 
				
			||||||
 | 
					        this.setChanged();
 | 
				
			||||||
 | 
					        this.notifyObservers();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					package nl.andrewlalis.model.error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.text.DateFormat;
 | 
				
			||||||
 | 
					import java.text.SimpleDateFormat;
 | 
				
			||||||
 | 
					import java.util.Date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Represents an error that occurs, but does not stop the application while running. Different from an exception in that
 | 
				
			||||||
 | 
					 * errors are meant to be added to a list and processed at a later time, and not hinder the operations in the present.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class Error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The time at which this error occurred.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private long timestamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The severity of the error.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private Severity severity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A custom error message generated at the time of the error.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Constructs a new Error with a severity and message.
 | 
				
			||||||
 | 
					     * @param severity The severity of the message.
 | 
				
			||||||
 | 
					     * @param message The custom generated error message for this error.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public Error(Severity severity, String message) {
 | 
				
			||||||
 | 
					        this.timestamp = System.currentTimeMillis();
 | 
				
			||||||
 | 
					        this.severity = severity;
 | 
				
			||||||
 | 
					        this.message = message;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
 | 
				
			||||||
 | 
					        String dateString = df.format(new Date(this.timestamp));
 | 
				
			||||||
 | 
					        return dateString + ' ' + this.severity.toString() + ": " + this.message;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					package nl.andrewlalis.model.error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Represents the different levels of severity for errors.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public enum Severity {
 | 
				
			||||||
 | 
					    CRITICAL,       // Anything which happens and could have serious side-effects or massive implications system-wide.
 | 
				
			||||||
 | 
					    HIGH,           // Errors which should be at the top of priority to sort out after a procedure is executed.
 | 
				
			||||||
 | 
					    MEDIUM,         // Medium errors are, as the name implies, of a medium priority.
 | 
				
			||||||
 | 
					    LOW,            // Low severity errors are the smallest errors that should be processed soon to avoid issues.
 | 
				
			||||||
 | 
					    MINOR           // Minor errors are so insignificant that they may not even require user intervention.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,10 @@ package nl.andrewlalis.ui.control.command.executables;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nl.andrewlalis.git_api.GithubManager;
 | 
					import nl.andrewlalis.git_api.GithubManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An executable which opens up a dialog to allow a user to delegate how many student teams each TATeam gets to manage,
 | 
				
			||||||
 | 
					 * and actually generate the student repositories using the manager.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class GenerateStudentRepos extends GithubExecutable {
 | 
					public class GenerateStudentRepos extends GithubExecutable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,10 @@ package nl.andrewlalis.ui.control.command.executables;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nl.andrewlalis.model.Organization;
 | 
					import nl.andrewlalis.model.Organization;
 | 
				
			||||||
import nl.andrewlalis.model.StudentTeam;
 | 
					import nl.andrewlalis.model.StudentTeam;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Error;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Severity;
 | 
				
			||||||
import nl.andrewlalis.ui.control.command.Executable;
 | 
					import nl.andrewlalis.ui.control.command.Executable;
 | 
				
			||||||
 | 
					import nl.andrewlalis.ui.view.InitializerApp;
 | 
				
			||||||
import nl.andrewlalis.util.FileUtils;
 | 
					import nl.andrewlalis.util.FileUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
| 
						 | 
					@ -17,15 +20,6 @@ import java.util.List;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class ReadStudentsFile implements Executable {
 | 
					public class ReadStudentsFile implements Executable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * A reference to the application's organization model.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private Organization organization;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ReadStudentsFile(Organization organization) {
 | 
					 | 
				
			||||||
        this.organization = organization;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean execute(String[] args) {
 | 
					    public boolean execute(String[] args) {
 | 
				
			||||||
        if (args.length < 2) {
 | 
					        if (args.length < 2) {
 | 
				
			||||||
| 
						 | 
					@ -37,7 +31,7 @@ public class ReadStudentsFile implements Executable {
 | 
				
			||||||
        if (teams == null) {
 | 
					        if (teams == null) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.organization.setStudentTeams(teams);
 | 
					        InitializerApp.organization.setStudentTeams(teams);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,12 @@
 | 
				
			||||||
package nl.andrewlalis.ui.view;
 | 
					package nl.andrewlalis.ui.view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.sun.org.apache.xpath.internal.operations.Or;
 | 
					 | 
				
			||||||
import nl.andrewlalis.model.Organization;
 | 
					import nl.andrewlalis.model.Organization;
 | 
				
			||||||
import nl.andrewlalis.model.StudentTeam;
 | 
					 | 
				
			||||||
import nl.andrewlalis.ui.control.OutputTextHandler;
 | 
					import nl.andrewlalis.ui.control.OutputTextHandler;
 | 
				
			||||||
import nl.andrewlalis.ui.control.command.CommandExecutor;
 | 
					import nl.andrewlalis.ui.control.command.CommandExecutor;
 | 
				
			||||||
import nl.andrewlalis.ui.control.listeners.*;
 | 
					import nl.andrewlalis.ui.control.listeners.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.swing.*;
 | 
					import javax.swing.*;
 | 
				
			||||||
import java.awt.*;
 | 
					import java.awt.*;
 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
import java.util.logging.Logger;
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,19 +41,16 @@ public class InitializerApp extends JFrame {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The organization object, which contains all important state information.
 | 
					     * The organization object, which contains all important state information.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private Organization organization;
 | 
					    public static Organization organization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Constructs a new instance of the main application frame, with both an executor, and organization model.
 | 
					     * Constructs a new instance of the main application frame, with both an executor, and organization model.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param executor The command executor, which is passed to any action listeners, so that buttons in this interface
 | 
					     * @param executor The command executor, which is passed to any action listeners, so that buttons in this interface
 | 
				
			||||||
     *                 may execute commands in the same way that the command line can.
 | 
					     *                 may execute commands in the same way that the command line can.
 | 
				
			||||||
     * @param organization A reference to the application's organization model, which holds all important runtime state
 | 
					 | 
				
			||||||
     *                     information.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public InitializerApp(CommandExecutor executor, Organization organization) {
 | 
					    public InitializerApp(CommandExecutor executor) {
 | 
				
			||||||
        this.executor = executor;
 | 
					        this.executor = executor;
 | 
				
			||||||
        this.organization = organization;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // UI initialization.
 | 
					        // UI initialization.
 | 
				
			||||||
        ImageIcon icon = new ImageIcon(getClass().getResource("/image/icon.png"));
 | 
					        ImageIcon icon = new ImageIcon(getClass().getResource("/image/icon.png"));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,9 @@ package nl.andrewlalis.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nl.andrewlalis.model.Student;
 | 
					import nl.andrewlalis.model.Student;
 | 
				
			||||||
import nl.andrewlalis.model.StudentTeam;
 | 
					import nl.andrewlalis.model.StudentTeam;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Error;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.error.Severity;
 | 
				
			||||||
 | 
					import nl.andrewlalis.ui.view.InitializerApp;
 | 
				
			||||||
import org.apache.commons.csv.CSVFormat;
 | 
					import org.apache.commons.csv.CSVFormat;
 | 
				
			||||||
import org.apache.commons.csv.CSVRecord;
 | 
					import org.apache.commons.csv.CSVRecord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +39,7 @@ public class TeamGenerator {
 | 
				
			||||||
        logger.fine("Generating teams of size " + teamSize);
 | 
					        logger.fine("Generating teams of size " + teamSize);
 | 
				
			||||||
        if (teamSize < 1) {
 | 
					        if (teamSize < 1) {
 | 
				
			||||||
            logger.severe("Invalid team size.");
 | 
					            logger.severe("Invalid team size.");
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.CRITICAL, "Invalid team size while generating teams from CSV."));
 | 
				
			||||||
            throw new IllegalArgumentException("StudentTeam 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.");
 | 
					        logger.fine("Parsing CSV file.");
 | 
				
			||||||
| 
						 | 
					@ -47,6 +51,7 @@ public class TeamGenerator {
 | 
				
			||||||
            studentMap = readAllStudents(records, teamSize);
 | 
					            studentMap = readAllStudents(records, teamSize);
 | 
				
			||||||
        } catch (ArrayIndexOutOfBoundsException e) {
 | 
					        } catch (ArrayIndexOutOfBoundsException e) {
 | 
				
			||||||
            logger.severe("StudentTeam size does not match column count in records.");
 | 
					            logger.severe("StudentTeam size does not match column count in records.");
 | 
				
			||||||
 | 
					            InitializerApp.organization.addError(new Error(Severity.CRITICAL, "Team size does not match column count in records."));
 | 
				
			||||||
            throw new IllegalArgumentException("StudentTeam size does not match column count in records.");
 | 
					            throw new IllegalArgumentException("StudentTeam size does not match column count in records.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue