Created
May 11, 2018 16:42
-
-
Save thegabriele97/61666c04d6fd82400d25e96ade1ca6fd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package schools; | |
import static java.util.stream.Collectors.counting; | |
import static java.util.stream.Collectors.groupingBy; | |
import static java.util.stream.Collectors.toList; | |
import java.io.BufferedReader; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.util.Collection; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
//import static java.util.Comparator.*; | |
/** | |
* Represents the region and serves as a facade class | |
* for the package. | |
* | |
* It provides factory methods for creating instances of | |
* {@link Community}, {@link Municipality}, {@link School}, and {@link Branch} | |
* | |
*/ | |
public class Region { | |
private static final int FIELD_PROVINCE = 0; | |
private static final int FIELD_MUNI = 1; | |
private static final int FIELD_GRADE = 2; | |
private static final int FIELD_DESCRIPTION = 3; | |
private static final int FIELD_COD_BRANCH = 4; | |
private static final int FIELD_COD_SCHOOl = 5; | |
private static final int FIELD_SCHOOL_NAME = 6; | |
private static final int FIELD_ADDRESS = 7; | |
private static final int FIELD_CAP = 8; | |
private static final int FIELD_COMMUNITY_HILL = 9; | |
private static final int FIELD_COMMUNITY_MOUNT = 10; | |
private String name; | |
private Map<String, Community> listOfCommunity; | |
private Map<String, Municipality> listOfMunicipality; | |
private Map<String, School> listOfSchool; | |
private Map<Integer, Branch> listOfBranch; | |
/** | |
* Creates a new region with the given name. | |
* @param name the name of the region | |
*/ | |
public Region(String name){ | |
this.name = name; | |
this.listOfCommunity = new HashMap<>(); | |
this.listOfMunicipality = new HashMap<>(); | |
this.listOfSchool = new HashMap<>(); | |
this.listOfBranch = new HashMap<>(); | |
} | |
/** | |
* Getter method | |
* @return the name of the region | |
*/ | |
public String getName(){ | |
return name; | |
} | |
/** | |
* Retrieves all schools in the region | |
* @return collection of schools | |
*/ | |
public Collection<School> getSchools() { | |
return listOfSchool.values(); | |
} | |
/** | |
* Retrieves all the communities | |
* @return the collection of all communities | |
*/ | |
public Collection<Community> getCommunities() { | |
return listOfCommunity.values(); | |
} | |
/** | |
* Retrieves all municipalities in the region | |
* @return the collection of municipalities | |
*/ | |
public Collection<Municipality> getMunicipalies() { | |
return listOfMunicipality.values(); | |
} | |
// factory methods | |
/** | |
* Factory method that build a new community of the given type. | |
* The type is {@link Community.Type} | |
* | |
* @param name name of the community | |
* @param type type of the community | |
* @return the new created community | |
*/ | |
public Community newCommunity(String name, Community.Type type){ | |
Community comm = new Community(name, type); | |
listOfCommunity.put(comm.getName(), comm); | |
return comm; | |
} | |
/** | |
* Factory method that build a new municipality. | |
* | |
* @param nome name of the municipality | |
* @param province province of the municipality | |
* @return the new created municipality | |
*/ | |
public Municipality newMunicipality(String nome, String province){ | |
return newMunicipality(nome, province, null); | |
} | |
/** | |
* Factory methods, that build a new municipality that | |
* is part of a community. | |
* | |
* @param nome name of the municipality | |
* @param province province of the municipality | |
* @param comunita community the municipality belongs to | |
* @return the new created municipality | |
*/ | |
public Municipality newMunicipality(String nome, String province, Community comunita){ | |
Municipality municipality = new Municipality(nome, province, comunita); | |
listOfMunicipality.put(municipality.getName() + municipality.getProvince(), municipality); | |
return municipality; | |
} | |
/** | |
* Factory method that creates a new school | |
* | |
* @param name name of the school | |
* @param code code of the school | |
* @param grade grade of the school (1 to 4) | |
* @param description description of the school | |
* | |
* @return a new school object | |
*/ | |
public School newSchool(String name, String code, int grade, String description){ | |
School sc = listOfSchool.get(code); | |
if (sc == null) { | |
sc = new School(code, name, grade, description); | |
listOfSchool.put(sc.getCode(), sc); | |
} | |
return sc; | |
} | |
/** | |
* Factory method that creates a new school branch | |
* | |
* @param regionalCode regional code of the branch | |
* @param municipality municipality where the branch is located | |
* @param address address of the branch | |
* @param zipCode zip code of the branch | |
* @param school school the branch is part of | |
* @return the new created branch | |
*/ | |
public Branch newBranch(int regionalCode, Municipality municipality, String address, int zipCode, School school) { | |
Branch branch = new Branch(regionalCode, municipality, address, zipCode, school); | |
listOfBranch.put(branch.getCode(), branch); | |
return branch; | |
} | |
/** | |
* Load data from a file. | |
* | |
* The file must be a CSV file and it is supposed to contain the following fields: | |
* <ul> | |
* <li>{@code "Provincia"}, (province) | |
* <li>{@code "Comune"}, (municipality) | |
* <li>{@code "Grado Scolastico"}, (school grade) | |
* <li>{@code "Descrizione Scuola"}, (school description) | |
* <li>{@code "Cod Sede"}, (branch code) | |
* <li>{@code "Cod Scuola"}, (school code) | |
* <li>{@code "Denominazione Scuola"}, (name of the school) | |
* <li>{@code "Indirizzo e n. civico"}, (address of the branch) | |
* <li>{@code "C.A.P."}, (zip code of the branch) | |
* <li>{@code "Comunita Collinare"}, (Hill community) | |
* <li>{@code "Comunita Montana"}, (Mountain community) | |
* </ul> | |
* | |
* @param file the path of the file | |
*/ | |
public void readData(String file) { | |
List<String> lines; | |
try(BufferedReader in = new BufferedReader(new FileReader(file))) { | |
lines = in.lines() | |
.skip(1) | |
.collect(toList()); | |
for (String record_str : lines) { | |
String[] record = record_str.split(","); | |
boolean isLastAComa = (record_str.charAt(record_str.length() - 1) == ','); | |
School school = listOfSchool.get(record[FIELD_COD_SCHOOl]); | |
if (school == null) { | |
school = newSchool(record[FIELD_SCHOOL_NAME], | |
record[FIELD_COD_SCHOOl], | |
Integer.valueOf(record[FIELD_GRADE]), | |
record[FIELD_DESCRIPTION]); | |
} | |
boolean isCommunityAvailable = record.length > FIELD_COMMUNITY_HILL; | |
Community community = null; | |
if (isCommunityAvailable) { | |
Community.Type type = (!isLastAComa) ? Community.Type.MONTANA : Community.Type.COLLINARE; | |
int field = (type == Community.Type.COLLINARE) ? FIELD_COMMUNITY_HILL : FIELD_COMMUNITY_MOUNT; | |
community = listOfCommunity.get(record[field]); | |
if (community == null) { | |
community = newCommunity(record[field], type); | |
} | |
} | |
Municipality municipality = listOfMunicipality.get(record[FIELD_MUNI] + record[FIELD_PROVINCE]); | |
if (municipality == null) { | |
municipality = newMunicipality(record[FIELD_MUNI], | |
record[FIELD_PROVINCE], | |
community); | |
} | |
Branch branch = listOfBranch.get(Integer.valueOf(record[FIELD_COD_BRANCH])); | |
if (branch == null) { | |
branch = newBranch(Integer.valueOf(record[FIELD_COD_BRANCH]), | |
municipality, | |
record[FIELD_ADDRESS], | |
Integer.valueOf(record[FIELD_CAP]), | |
school); | |
} | |
} | |
} catch(IOException e) { | |
System.err.println(e.getMessage()); | |
} | |
} | |
/** | |
* Counts how many schools there exist for each description | |
* @return a map of school count vs. description | |
*/ | |
public Map<String,Long>countSchoolsPerDescription(){ | |
return listOfSchool.values() | |
.stream() | |
.collect(groupingBy(School::getDescription, counting())); | |
} | |
/** | |
* Count how many school branches there exist for each municipality | |
* @return a map of branch count vs. municipality | |
*/ | |
public Map<String,Long>countBranchesPerMunicipality(){ | |
Map<Municipality, Long> map1 = listOfMunicipality.values() | |
.stream() | |
.flatMap(m -> m.getBranches().stream()) | |
.collect(groupingBy(Branch::getMunicipality, counting())); | |
Map<String, Long> newM = new HashMap<>(); | |
map1.forEach((k, v) -> newM.put(k.getName(), v)); | |
return newM; | |
} | |
/** | |
* Counts the number of school branches per municipality | |
* and groups them by province. | |
* @return a map of maps the inner reports count of branches vs. municipality | |
* the outer reports provinces as keys | |
*/ | |
public Map<String,Map<String,Long>>countBranchesPerMunicipalityPerProvince(){ | |
return listOfMunicipality.values() | |
.stream() | |
.flatMap(m -> m.getBranches().stream()) | |
.collect(groupingBy(b -> ((Branch)b).getMunicipality().getProvince(), | |
groupingBy(b -> ((Branch)b).getMunicipality().getName(), counting()))); | |
} | |
/** | |
* returns a list of strings with format | |
* {@code "### - XXXXXX"}, where | |
* {@code ###} represents the number of schools (not branches) | |
* and {@code XXXXXX} represents the name of the municipality. | |
* If a school has more than one branch in a municipality | |
* it must be counted only once. | |
* | |
* @return a collection of strings with the counts | |
*/ | |
public Collection<String> countSchoolsPerMunicipality(){ | |
return listOfBranch.values() | |
.stream() | |
.collect(groupingBy(Branch::getMunicipality, counting())) | |
.entrySet() | |
.stream() | |
.map(e -> e.getValue() + " - " + e.getKey().getName()) | |
.collect(toList()); | |
} | |
/** | |
* returns a list of strings with format | |
* {@code "### - XXXXXX"}, where | |
* {@code ###} represents the number of schools (not branches) | |
* and {@code XXXXXX} represents the name of the community. | |
* They are sorted by descending number of schools.s | |
* The list must contain only schools having at least | |
* a branch in a municipality part of a community. | |
* | |
* @return a collection of strings with the counts | |
*/ | |
public List<String> countSchoolsPerCommunity(){ | |
return listOfBranch.values() | |
.stream() | |
.filter(b -> ((Branch)b).getMunicipality().getCommunity().isPresent()) | |
.collect(groupingBy(b -> ((Branch)b).getMunicipality().getCommunity(), counting())) | |
.entrySet() | |
.stream() | |
.sorted(Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder())) | |
.map(e -> e.getValue() + " - " + e.getKey().get().getName()) | |
.collect(toList()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment