diff --git a/wilayah-indonesia/.gitignore b/wilayah-indonesia/.gitignore index 7155cfb..f7d9b2b 100644 --- a/wilayah-indonesia/.gitignore +++ b/wilayah-indonesia/.gitignore @@ -1,4 +1,5 @@ /.idea /resources/* /target -maps.iml \ No newline at end of file +maps.iml +*.iml diff --git a/wilayah-indonesia/indonesia.iml b/wilayah-indonesia/indonesia.iml index b3d2be7..9ff5543 100644 --- a/wilayah-indonesia/indonesia.iml +++ b/wilayah-indonesia/indonesia.iml @@ -12,8 +12,10 @@ - - + + + + \ No newline at end of file diff --git a/wilayah-indonesia/pom.xml b/wilayah-indonesia/pom.xml index f86cfff..3a42ccb 100644 --- a/wilayah-indonesia/pom.xml +++ b/wilayah-indonesia/pom.xml @@ -23,12 +23,12 @@ com.google.code.gson gson - 2.7 + 2.8.8 org.projectlombok lombok - 1.18.16 + 1.18.20 provided @@ -38,6 +38,17 @@ log4j 1.2.17 + + org.slf4j + slf4j-api + 1.7.12 + + + org.slf4j + slf4j-log4j12 + 1.7.12 + runtime + diff --git a/wilayah-indonesia/src/main/java/wilayah/indonesia/Loader.java b/wilayah-indonesia/src/main/java/wilayah/indonesia/Loader.java index b699cfa..69d160b 100644 --- a/wilayah-indonesia/src/main/java/wilayah/indonesia/Loader.java +++ b/wilayah-indonesia/src/main/java/wilayah/indonesia/Loader.java @@ -1,32 +1,39 @@ package wilayah.indonesia; -import java.io.*; -import org.apache.log4j.Logger; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.var; /** * Created by yusuf on 24/10/16. */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class Loader { - final static Logger logger = Logger.getLogger(Loader.class); /** * Load a file content to string using BufferedInputStream since it fast - * @param file - * @return - * @throws Exception + * + * @param file file path + * @return content string + * @throws IOException throws if failed to load the file */ - public static String read(String file) throws Exception { + public static String read(String file) throws IOException { final long start = System.currentTimeMillis(); - final InputStream in = new BufferedInputStream(new FileInputStream(file)); - int bytesRead = 0; - String line = ""; - final byte[] buf = new byte[50130]; - while ((bytesRead = in.read(buf)) != -1) { - line += new String(buf, 0, bytesRead); + try (final InputStream in = new BufferedInputStream(new FileInputStream(file))) { + var bytesRead = 0; + var line = new StringBuilder(); + final byte[] buf = new byte[50130]; + while ((bytesRead = in.read(buf)) != -1) { + line.append(new String(buf, 0, bytesRead)); + } + log.debug("Load {} took {} ms", file, (System.currentTimeMillis() - start)); + return line.toString(); } - in.close(); - - logger.debug("Load " + file + " took " + (System.currentTimeMillis() - start) + " ms"); - return line; } } diff --git a/wilayah-indonesia/src/main/java/wilayah/indonesia/Location.java b/wilayah-indonesia/src/main/java/wilayah/indonesia/Location.java index 6a75145..e07db96 100644 --- a/wilayah-indonesia/src/main/java/wilayah/indonesia/Location.java +++ b/wilayah-indonesia/src/main/java/wilayah/indonesia/Location.java @@ -2,135 +2,138 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.List; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; import wilayah.indonesia.model.District; import wilayah.indonesia.model.Province; import wilayah.indonesia.model.Regency; import wilayah.indonesia.model.Village; -import org.apache.log4j.Logger; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; /** * Created by yusuf on 24/10/16. */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class Location { public enum TREE_LEVEL { PROVINCE, REGENCY, DISTRICT, VILLAGE } - final static Logger logger = Logger.getLogger(Location.class); - - private static final Type PROVINCES = new TypeToken>() {}.getType(); - private static final Type REGENCIES = new TypeToken>() {}.getType(); - private static final Type DISTRICT = new TypeToken>() {}.getType(); - private static final Type VILLAGE = new TypeToken>() {}.getType(); + private static final String EMPTY_JSON = "[{}]"; + private static final Type PROVINCES = TypeToken.getParameterized(List.class, Province.class) + .getType(); + private static final Type REGENCIES = TypeToken.getParameterized(List.class, Regency.class) + .getType(); + private static final Type DISTRICT = TypeToken.getParameterized(List.class, District.class) + .getType(); + private static final Type VILLAGE = TypeToken.getParameterized(List.class, Village.class) + .getType(); public static final Gson gson = new Gson(); + public static final String PROVINCE_TREE_PATH = "./resources/list_of_area/indonesia-region.min.json"; + public static final String PROVINCE_PATH = "./resources/list_of_area/provinces.json"; + public static final String REGENCY_PATH = "./resources/list_of_area/regencies.json"; + public static final String DISTRICT_PATH = "./resources/list_of_area/districts.json"; + public static final String VILLAGE_PATH = "./resources/list_of_area/villages.json"; + + public static List provinces() throws IOException, LocationException { + return gson.fromJson(Loader.read(PROVINCE_PATH), PROVINCES); + } - public static List Provinces() throws Exception { - String provinces = Loader.read("./resources/list_of_area/provinces.json"); - return gson.fromJson(provinces, PROVINCES); + @Deprecated + public static List Provinces() throws IOException, LocationException { + return provinces(); } - public static List Regencies() throws Exception { - String regencies = Loader.read("./resources/list_of_area/regencies.json"); - return gson.fromJson(regencies, REGENCIES); + public static List regencies() throws IOException, LocationException { + return gson.fromJson(Loader.read(REGENCY_PATH), REGENCIES); } - public static List Districts() throws Exception { - String districts = Loader.read("./resources/list_of_area/districts.json"); - return gson.fromJson(districts, DISTRICT); + @Deprecated + public static List Regencies() throws IOException, LocationException { + return regencies(); } - public static List Villages() throws Exception { - String villages = Loader.read("./resources/list_of_area/villages.json"); - return gson.fromJson(villages, VILLAGE); + public static List districts() throws IOException, LocationException { + return gson.fromJson(Loader.read(DISTRICT_PATH), DISTRICT); } - public static List ProvinceTrees() throws Exception { - String treeStr = Loader.read("./resources/list_of_area/indonesia-region.min.json"); - List tree = gson.fromJson(treeStr, PROVINCES); - return tree; + @Deprecated + public static List Districts() throws IOException, LocationException { + return districts(); } - public static List ProvinceTrees(TREE_LEVEL tree_level) throws Exception { - String provincesStr = "[{}]"; - String regenciesStr = "[{}]"; - String districtsStr = "[{}]"; - String villagesStr = "[{}]"; + public static List villages() throws IOException, LocationException { + return gson.fromJson(Loader.read(VILLAGE_PATH), VILLAGE); + } - switch (tree_level) { - case PROVINCE: - provincesStr = Loader.read("./resources/list_of_area/provinces.json"); - break; + @Deprecated + public static List Villages() throws IOException, LocationException { + return villages(); + } - case REGENCY: - provincesStr = Loader.read("./resources/list_of_area/provinces.json"); - regenciesStr = Loader.read("./resources/list_of_area/regencies.json"); - break; + public static List provinceTrees() throws IOException, LocationException { + return gson.fromJson(Loader.read(PROVINCE_TREE_PATH), PROVINCES); + } - case DISTRICT: - provincesStr = Loader.read("./resources/list_of_area/provinces.json"); - regenciesStr = Loader.read("./resources/list_of_area/regencies.json"); - districtsStr = Loader.read("./resources/list_of_area/districts.json"); - break; + public static List provinceTrees(final TREE_LEVEL treeLevel) + throws IOException, LocationException { + + if (treeLevel == null) { + throw new LocationException(); + } + + final String provincesStr = Loader.read(PROVINCE_PATH); + String regenciesStr = EMPTY_JSON; + String districtsStr = EMPTY_JSON; + String villagesStr = EMPTY_JSON; + switch (treeLevel) { case VILLAGE: - provincesStr = Loader.read("./resources/list_of_area/provinces.json"); - regenciesStr = Loader.read("./resources/list_of_area/regencies.json"); - districtsStr = Loader.read("./resources/list_of_area/districts.json"); - villagesStr = Loader.read("./resources/list_of_area/villages.json"); + villagesStr = Loader.read(VILLAGE_PATH); + // fallthrough + case DISTRICT: + districtsStr = Loader.read(DISTRICT_PATH); + // fallthrough + case REGENCY: + regenciesStr = Loader.read(REGENCY_PATH); + // fallthrough + case PROVINCE: break; - default: - provincesStr = Loader.read("./resources/list_of_area/provinces.json"); - break; } - List provinces = gson.fromJson(provincesStr, PROVINCES); List regencies = gson.fromJson(regenciesStr, REGENCIES); List districts = gson.fromJson(districtsStr, DISTRICT); List villages = gson.fromJson(villagesStr, VILLAGE); final long start = System.currentTimeMillis(); - List newProvinces = new ArrayList<>(); - provinces.forEach(p -> { - - List newRegencies = new ArrayList<>(); - regencies.forEach(r -> { - if(p.getId().equals( r.getProvince_id() )) { - - List newDistricts = new ArrayList<>(); - districts.forEach(d -> { - if(r.getId().equals( d.getRegency_id() )) { - - List newVillages = new ArrayList<>(); - villages.forEach(v -> { - if(d.getId().equals( v.getDistrict_id() )) { - newVillages.add(v); - } - }); - - d.setVillages(newVillages); - newDistricts.add(d); - } - }); - - r.setDistricts(newDistricts); - newRegencies.add(r); - } - }); - - p.setRegencies(newRegencies); - newProvinces.add(p); - }); - - logger.debug("Mapping location tree dependency took " + (System.currentTimeMillis() - start) + " ms"); + + final List newProvinces = provinces.stream() + .map(province -> Utils.setChild(province, regencies, districts, villages)) + .collect(Collectors.toList()); + + log.debug("Mapping location tree dependency took {} ms", + (System.currentTimeMillis() - start)); return newProvinces; } + @Deprecated + public static List ProvinceTrees() throws IOException, LocationException { + return provinceTrees(); + } + + @Deprecated + public static List ProvinceTrees(final TREE_LEVEL treeLevel) + throws IOException, LocationException { + return provinceTrees(treeLevel); + } + } diff --git a/wilayah-indonesia/src/main/java/wilayah/indonesia/LocationException.java b/wilayah-indonesia/src/main/java/wilayah/indonesia/LocationException.java new file mode 100644 index 0000000..be6890a --- /dev/null +++ b/wilayah-indonesia/src/main/java/wilayah/indonesia/LocationException.java @@ -0,0 +1,12 @@ +package wilayah.indonesia; + + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class LocationException extends RuntimeException { + + public LocationException(String message) { + super(message); + } +} diff --git a/wilayah-indonesia/src/main/java/wilayah/indonesia/Utils.java b/wilayah-indonesia/src/main/java/wilayah/indonesia/Utils.java new file mode 100644 index 0000000..9d4699e --- /dev/null +++ b/wilayah-indonesia/src/main/java/wilayah/indonesia/Utils.java @@ -0,0 +1,54 @@ +package wilayah.indonesia; + +import java.util.List; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import wilayah.indonesia.model.District; +import wilayah.indonesia.model.Province; +import wilayah.indonesia.model.Regency; +import wilayah.indonesia.model.Village; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class Utils { + + public static District setChild(final District district, final List villages) { + + district.setVillages( + villages.stream() + .filter(village -> district.getId() + .equals(village.getDistrict_id())) + .collect(Collectors.toList())); + return district; + } + + public static Regency setChild( + final Regency regency, + final List districts, + final List villages) { + + regency.setDistricts( + districts.stream() + .filter( + district -> regency.getId() + .equals(district.getRegency_id())) + .map(district -> setChild(district, villages)) + .collect(Collectors.toList())); + return regency; + } + + public static Province setChild( + final Province province, + final List regencies, + final List districts, + final List villages) { + + province.setRegencies( + regencies.stream() + .filter(regency -> province.getId() + .equals(regency.getProvince_id())) + .map(regency -> setChild(regency, districts, villages)) + .collect(Collectors.toList())); + return province; + } +} diff --git a/wilayah-indonesia/src/test/java/wilayah/IndonesiaMapTest.java b/wilayah-indonesia/src/test/java/wilayah/IndonesiaMapTest.java index 0cef51f..5194a38 100644 --- a/wilayah-indonesia/src/test/java/wilayah/IndonesiaMapTest.java +++ b/wilayah-indonesia/src/test/java/wilayah/IndonesiaMapTest.java @@ -1,35 +1,92 @@ package wilayah; +import java.io.IOException; +import lombok.SneakyThrows; +import lombok.val; +import org.apache.log4j.BasicConfigurator; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import wilayah.indonesia.Loader; import wilayah.indonesia.Location; -import wilayah.indonesia.model.Province; -import org.junit.*; - -import java.util.List; +import wilayah.indonesia.LocationException; /** * Created by yusuf on 06/11/16. */ public class IndonesiaMapTest { - public IndonesiaMapTest() { + @BeforeClass + public static void prepareDefault() { + BasicConfigurator.resetConfiguration(); + BasicConfigurator.configure(); } @Test - public void Loader() throws Exception { - org.apache.log4j.BasicConfigurator.configure(); - List p1 = Location.ProvinceTrees(Location.TREE_LEVEL.VILLAGE); + public void throwable() { + Assert.assertThrows(LocationException.class, () -> { + Location.provinceTrees(null); + }); + } + + @SneakyThrows + @Test + public void provinceTrees() { + val p1 = Location.provinceTrees(Location.TREE_LEVEL.VILLAGE); Assert.assertEquals("DI YOGYAKARTA", p1.get(13).getName()); Assert.assertEquals("KABUPATEN KULON PROGO", p1.get(13).getRegencies().get(0).getName()); - Assert.assertEquals("TEMON", p1.get(13).getRegencies().get(0).getDistricts().get(0).getName()); - Assert.assertEquals("JANGKARAN", p1.get(13).getRegencies().get(0).getDistricts().get(0).getVillages().get(0).getName()); + Assert.assertEquals("TEMON", + p1.get(13).getRegencies().get(0).getDistricts().get(0).getName()); + Assert.assertEquals("JANGKARAN", + p1.get(13).getRegencies().get(0).getDistricts().get(0).getVillages().get(0).getName()); - List p2 = Location.ProvinceTrees(); + val p2 = Location.provinceTrees(); Assert.assertEquals("DI YOGYAKARTA", p2.get(13).getName()); Assert.assertEquals("KABUPATEN KULON PROGO", p2.get(13).getRegencies().get(0).getName()); - Assert.assertEquals("TEMON", p2.get(13).getRegencies().get(0).getDistricts().get(0).getName()); - Assert.assertEquals("JANGKARAN", p2.get(13).getRegencies().get(0).getDistricts().get(0).getVillages().get(0).getName()); + Assert.assertEquals("TEMON", + p2.get(13).getRegencies().get(0).getDistricts().get(0).getName()); + Assert.assertEquals("JANGKARAN", + p2.get(13).getRegencies().get(0).getDistricts().get(0).getVillages().get(0).getName()); + } + + @SneakyThrows + @Test + public void province() { + val p3 = Location.provinces(); + Assert.assertFalse(p3.isEmpty()); + } + + @SneakyThrows + @Test + public void regency() { + val p4 = Location.regencies(); + Assert.assertFalse(p4.isEmpty()); + } + + @SneakyThrows + @Test + public void district() { + val p5 = Location.districts(); + Assert.assertFalse(p5.isEmpty()); + } + + @SneakyThrows + @Test + public void village() { + + val p6 = Location.villages(); + Assert.assertFalse(p6.isEmpty()); + } + + @SneakyThrows + @Test + public void Loader() { + Assert.assertThrows(IOException.class, () -> { + Loader.read("xyz"); + }); + Assert.assertNotNull(Loader.read(Location.PROVINCE_PATH)); } }