Skip to content

Commit 2987ba5

Browse files
author
Fabrice Bibonne
authored
Merge pull request #107 from InseeFr/103-Service-identification-Iris
Feat: WS for Iris
2 parents b66c01d + 815b72f commit 2987ba5

23 files changed

Lines changed: 1159 additions & 93 deletions

pom.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@
6969
<version>${jersey.version}</version>
7070
</dependency>
7171

72-
73-
7472
<!-- LOGS -->
7573
<dependency>
7674
<groupId>org.apache.logging.log4j</groupId>

src/main/java/fr/insee/rmes/api/classifications/ClassificationApi.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import javax.ws.rs.core.Response;
1717
import javax.ws.rs.core.Response.Status;
1818

19+
import io.swagger.v3.oas.annotations.extensions.Extension;
20+
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
1921
import org.apache.commons.lang3.StringUtils;
2022

2123
import fr.insee.rmes.api.AbstractMetadataApi;
@@ -37,8 +39,7 @@
3739
@Tag(name = "nomenclatures", description = "Nomenclatures API")
3840
public class ClassificationApi extends AbstractMetadataApi {
3941

40-
41-
@Hidden
42+
4243
@GET
4344
@Path("/{code}/postes")
4445
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })

src/main/java/fr/insee/rmes/api/geo/AbstractGeoApi.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import java.lang.reflect.Constructor;
1818
import java.lang.reflect.InvocationTargetException;
1919
import java.util.List;
20+
import java.util.Objects;
21+
import java.util.stream.Collectors;
22+
import java.util.stream.Stream;
2023

2124
public abstract class AbstractGeoApi extends AbstractMetadataApi {
2225

@@ -135,7 +138,11 @@ else if (StringUtils.equalsAnyIgnoreCase(header, MediaType.APPLICATION_JSON)) {
135138
}
136139

137140
protected Response generateBadRequestResponse() {
138-
return Response.status(Status.BAD_REQUEST).entity("").build();
141+
return generateBadRequestResponse("");
142+
}
143+
144+
protected Response generateBadRequestResponse(String erreurMessage) {
145+
return Response.status(Status.BAD_REQUEST).entity(erreurMessage).build();
139146
}
140147

141148
// Method to find a list of projections

src/main/java/fr/insee/rmes/api/geo/ConstGeoApi.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class ConstGeoApi {
1010

1111
public static final String PATH_CIRCO_TER = PATH_SEPARATOR + "circonscriptionTerritoriale";
1212
public static final String PATH_CANTON = PATH_SEPARATOR + "canton";
13+
public static final String PATH_IRIS=PATH_SEPARATOR + "iris";
1314
public static final String PATH_COMMUNE = PATH_SEPARATOR + "commune";
1415
public static final String PATH_CANTON_OU_VILLE = PATH_SEPARATOR + "cantonOuVille";
1516
public static final String PATH_PAYS = PATH_SEPARATOR + "pays";
@@ -28,7 +29,7 @@ public class ConstGeoApi {
2829
public static final String PATH_LISTE_CANTON_OU_VILLE= PATH_SEPARATOR +"cantonsEtVilles";
2930
public static final String PATH_INTERCO= PATH_SEPARATOR + "intercommunalite";
3031
public static final String PATH_BASSINDEVIE= PATH_SEPARATOR + "bassinDeVie2022";
31-
32+
public static final String PATH_LISTE_IRIS = PATH_SEPARATOR + "iris";
3233
public static final String PATH_LISTE_COMMUNE = PATH_SEPARATOR + "communes";
3334
public static final String PATH_LISTE_PAYS = PATH_SEPARATOR + "pays";
3435
public static final String PATH_LISTE_CANTON = PATH_SEPARATOR + "cantons";
@@ -59,6 +60,9 @@ public class ConstGeoApi {
5960
public static final String PATTERN_DISTRICT ="9[78][1-9]{3}";
6061
public static final String PATTERN_INTERCO ="2[0-4][0-9]{7}";
6162
public static final String PATTERN_CANTON = "(([0-9]{2})|(2[0-9AB])|(97[1-6]))([0-9]{2})";
63+
64+
public static final String PATTERN_IRIS="[0-9][0-9AB][0-9]{7}";
65+
public static final String PATTERN_IRIS_DESCRIPTION= "Code Insee de l’Iris (9 caractères)";
6266
public static final String PATTERN_PAYS = "99[0-9]{3}";
6367
public static final String PATTERN_REGION = "[0-9]{2}";
6468
public static final String PATTERN_ZONE_EMPLOI = "[0-9]{4}";
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package fr.insee.rmes.api.geo.territoire;
2+
3+
import fr.insee.rmes.api.geo.AbstractGeoApi;
4+
import fr.insee.rmes.api.geo.ConstGeoApi;
5+
import fr.insee.rmes.modeles.geo.territoire.CodeIris;
6+
import fr.insee.rmes.modeles.geo.territoire.Iris;
7+
import fr.insee.rmes.modeles.geo.territoire.PseudoIris;
8+
import fr.insee.rmes.modeles.geo.territoire.Territoire;
9+
import fr.insee.rmes.modeles.geo.territoires.Territoires;
10+
import fr.insee.rmes.queries.geo.GeoQueries;
11+
import fr.insee.rmes.utils.*;
12+
import io.swagger.v3.oas.annotations.Operation;
13+
import io.swagger.v3.oas.annotations.Parameter;
14+
import io.swagger.v3.oas.annotations.media.Content;
15+
import io.swagger.v3.oas.annotations.media.Schema;
16+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
17+
import io.swagger.v3.oas.annotations.tags.Tag;
18+
19+
import javax.ws.rs.*;
20+
import javax.ws.rs.core.HttpHeaders;
21+
import javax.ws.rs.core.MediaType;
22+
import javax.ws.rs.core.Response;
23+
24+
25+
@Path(ConstGeoApi.PATH_GEO)
26+
@Tag(name = ConstGeoApi.TAG_NAME, description = ConstGeoApi.TAG_DESCRIPTION)
27+
public class IrisApi extends AbstractGeoApi {
28+
private static final String CODE_PATTERN = "/{code:}";
29+
private static final String LITTERAL_PARAMETER_TYPE_DESCRIPTION = "Filtre sur le type de territoire renvoyé.";
30+
31+
private static final String LITTERAL_RESPONSE_DESCRIPTION = "Iris";
32+
private static final String LITTERAL_ID_OPERATION = "getcogiris";
33+
private static final String LITTERAL_CODE_EXAMPLE = "010040101";
34+
private static final String LITTERAL_PARAMETER_DATE_DESCRIPTION =
35+
"Filtre pour renvoyer l'Iris active à la date donnée. Par défaut, c’est la date courante. (Format : 'AAAA-MM-JJ')";
36+
private static final String LITTERAL_OPERATION_SUMMARY =
37+
"Informations sur un Iris identifié par son code (neuf chiffres pour la métropole ou 2A/2B plus 7 chiffres pour la Corse)";
38+
39+
40+
private final IrisUtils irisUtils;
41+
42+
public IrisApi() {
43+
// Constructeur par défaut
44+
this.irisUtils = new IrisUtils();
45+
}
46+
47+
protected IrisApi(SparqlUtils sparqlUtils, CSVUtils csvUtils, ResponseUtils responseUtils, IrisUtils irisUtils) {
48+
super(sparqlUtils, csvUtils, responseUtils);
49+
this.irisUtils = irisUtils;
50+
}
51+
52+
@Path(ConstGeoApi.PATH_IRIS + CODE_PATTERN)
53+
@GET
54+
@Produces({
55+
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML
56+
})
57+
@Operation(operationId = LITTERAL_ID_OPERATION, summary = LITTERAL_OPERATION_SUMMARY, responses = {
58+
@ApiResponse(
59+
content = @Content(schema = @Schema(implementation = Iris.class)),
60+
description = LITTERAL_RESPONSE_DESCRIPTION)
61+
62+
})
63+
public Response getByCode(
64+
@Parameter(
65+
description = ConstGeoApi.PATTERN_IRIS_DESCRIPTION,
66+
required = true,
67+
schema = @Schema(
68+
pattern = ConstGeoApi.PATTERN_IRIS,
69+
type = Constants.TYPE_STRING, example = LITTERAL_CODE_EXAMPLE)) @PathParam(Constants.CODE) String code,
70+
@Parameter(hidden = true) @HeaderParam(HttpHeaders.ACCEPT) String header,
71+
@Parameter(
72+
description = LITTERAL_PARAMETER_DATE_DESCRIPTION,
73+
schema = @Schema(type = Constants.TYPE_STRING, format = Constants.FORMAT_DATE)) @QueryParam(
74+
value = Constants.PARAMETER_DATE) String date) {
75+
76+
var codeIris = CodeIris.of(code);
77+
if (codeIris.isInvalid()) {
78+
return generateBadRequestResponse(ConstGeoApi.ERREUR_PATTERN);
79+
}
80+
if (!this.verifyParameterDateIsRightWithoutHistory(date)) {
81+
return this.generateBadRequestResponse();
82+
}
83+
84+
return getResponseForIrisOrPseudoIris(codeIris, header, date);
85+
}
86+
87+
private Response getResponseForIrisOrPseudoIris(CodeIris codeIris, String header, String date) {
88+
if (irisUtils.hasIrisDescendant(codeIris.codeCommune())) {
89+
return getResponseForIris(codeIris, header, date);
90+
} else {
91+
return getResponseForPseudoIris(codeIris, header, date);
92+
}
93+
94+
}
95+
96+
private Response getResponseForPseudoIris(CodeIris codeIris, String header, String date) {
97+
if (codeIris.isPseudoIrisCode()) {
98+
return this.generateResponseATerritoireByCode(
99+
sparqlUtils.executeSparqlQuery(
100+
GeoQueries.getIrisByCodeAndDate(codeIris.code(), this.formatValidParameterDateIfIsNull(date))),
101+
header,
102+
new PseudoIris(codeIris.code()));
103+
} else {
104+
return Response.status(Response.Status.NOT_FOUND).entity("").build();
105+
}
106+
}
107+
108+
private Response getResponseForIris(CodeIris codeIris, String header, String date) {
109+
if (codeIris.isPseudoIrisCode()) {
110+
return Response.status(Response.Status.NOT_FOUND).entity("").build();
111+
} else {
112+
Territoire territoire = new Iris(codeIris.code());
113+
return this.generateResponseATerritoireByCode(
114+
sparqlUtils.executeSparqlQuery(
115+
GeoQueries.getIrisByCodeAndDate(codeIris.code(), this.formatValidParameterDateIfIsNull(date))),
116+
header,
117+
territoire);
118+
}
119+
}
120+
121+
122+
@Path(ConstGeoApi.PATH_LISTE_IRIS)
123+
@GET
124+
@Produces({
125+
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML
126+
})
127+
@Operation(
128+
operationId = LITTERAL_ID_OPERATION + ConstGeoApi.ID_OPERATION_LISTE,
129+
summary = "Informations sur toutes les iris actifs à la date donnée. Par défaut, c’est la date courante.",
130+
responses = {
131+
@ApiResponse(
132+
content = @Content(schema = @Schema(type = ARRAY, implementation = Territoire.class)),
133+
description = LITTERAL_RESPONSE_DESCRIPTION)
134+
})
135+
public Response getListe(
136+
@Parameter(hidden = true) @HeaderParam(HttpHeaders.ACCEPT) String header,
137+
@Parameter(
138+
description = "Filtre pour renvoyer les Iris ou faux-Iris à la date donnée. Par défaut, c’est la date courante. (Format : 'AAAA-MM-JJ')",
139+
schema = @Schema(type = Constants.TYPE_STRING, format = Constants.FORMAT_DATE)) @QueryParam(
140+
value = Constants.PARAMETER_DATE) String date,
141+
@Parameter(description = "les Iris (et pseudo-iris) des collectivités d'outre-mer",
142+
required = true,
143+
schema = @Schema(type = Constants.TYPE_BOOLEAN, allowableValues = {"true", "false"}, example = "false", defaultValue = "false"))
144+
@QueryParam(
145+
value = Constants.PARAMETER_STRING) Boolean com
146+
) {
147+
148+
if (!this.verifyParameterDateIsRightWithHistory(date)) {
149+
return this.generateBadRequestResponse();
150+
} else {
151+
return this
152+
.generateResponseListOfTerritoire(
153+
sparqlUtils
154+
.executeSparqlQuery(GeoQueries.getListIris(this.formatValidParameterDateIfIsNull(date), this.formatValidParameterBooleanIfIsNull(com))),
155+
header,
156+
Territoires.class,
157+
Territoire.class);
158+
}
159+
}
160+
161+
162+
@Path(ConstGeoApi.PATH_IRIS + CODE_PATTERN + ConstGeoApi.PATH_ASCENDANT)
163+
@GET
164+
@Produces({
165+
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML
166+
})
167+
@Operation(
168+
operationId = LITTERAL_ID_OPERATION + ConstGeoApi.ID_OPERATION_ASCENDANTS,
169+
summary = "Informations concernant les territoires qui contiennent l'Iris",
170+
responses = {
171+
@ApiResponse(
172+
content = @Content(schema = @Schema(type = ARRAY, implementation = Territoire.class)),
173+
description = LITTERAL_RESPONSE_DESCRIPTION)
174+
})
175+
public Response getAscendants(
176+
@Parameter(
177+
description = ConstGeoApi.PATTERN_IRIS_DESCRIPTION,
178+
required = true,
179+
schema = @Schema(
180+
pattern = ConstGeoApi.PATTERN_IRIS,
181+
type = Constants.TYPE_STRING, example = LITTERAL_CODE_EXAMPLE)) @PathParam(Constants.CODE) String code,
182+
@Parameter(hidden = true) @HeaderParam(HttpHeaders.ACCEPT) String header,
183+
@Parameter(
184+
description = "Filtre pour renvoyer les territoires contenant l'iris actif à la date donnée. Par défaut, c’est la date courante. (Format : 'AAAA-MM-JJ')",
185+
schema = @Schema(type = Constants.TYPE_STRING, format = Constants.FORMAT_DATE)) @QueryParam(
186+
value = Constants.PARAMETER_DATE) String date,
187+
@Parameter(
188+
description = LITTERAL_PARAMETER_TYPE_DESCRIPTION,
189+
schema = @Schema(type = Constants.TYPE_STRING)) @QueryParam(
190+
value = Constants.PARAMETER_TYPE) String typeTerritoire) {
191+
192+
if (!this.verifyParametersTypeAndDateAreValid(typeTerritoire, date)) {
193+
return this.generateBadRequestResponse();
194+
} else {
195+
return this
196+
.generateResponseListOfTerritoire(
197+
sparqlUtils
198+
.executeSparqlQuery(
199+
GeoQueries
200+
.getAscendantsIris(
201+
code,
202+
this.formatValidParameterDateIfIsNull(date),
203+
this.formatValidParametertypeTerritoireIfIsNull(typeTerritoire))),
204+
header,
205+
Territoires.class,
206+
Territoire.class);
207+
}
208+
}
209+
210+
}

src/main/java/fr/insee/rmes/modeles/geo/EnumTypeGeographie.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package fr.insee.rmes.modeles.geo;
22

3-
import java.util.Optional;
4-
import java.util.stream.Stream;
5-
63
import fr.insee.rmes.modeles.geo.territoire.*;
74
import fr.insee.rmes.modeles.geo.territoires.*;
85
import fr.insee.rmes.utils.Constants;
96

7+
import java.util.Optional;
8+
import java.util.stream.Stream;
9+
1010
public enum EnumTypeGeographie {
1111

1212
COMMUNE("Commune", Commune.class,Communes.class, Constants.NONE),
@@ -25,8 +25,8 @@ public enum EnumTypeGeographie {
2525
DISTRICT("District",District.class,Districts.class,Constants.NONE),
2626
CIRCONSCRIPTION_TERRITORIALE("CirconscriptionTerritoriale",CirconscriptionTerritoriale.class,CirconscriptionsTerritoriales.class,Constants.NONE),
2727
INTERCOMMUNALITE("Intercommunalite",Intercommunalite.class,Intercommunalites.class,Constants.NONE),
28-
BASSINDEVIE("BassinDeVie2022",BassinDeVie2022.class,BassinsDeVie2022.class,Constants.NONE);
29-
28+
BASSINDEVIE("BassinDeVie2022",BassinDeVie2022.class,BassinsDeVie2022.class,Constants.NONE),
29+
IRIS("Iris", Iris.class,Iriss.class,Constants.NONE);
3030

3131
private String typeObjetGeo;
3232
private Class<? extends Territoire> classNameOfGeoType;

src/main/java/fr/insee/rmes/modeles/geo/IntituleSansArticle.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
11
package fr.insee.rmes.modeles.geo;
22

3-
import javax.xml.bind.annotation.XmlAccessType;
4-
import javax.xml.bind.annotation.XmlAccessorType;
5-
import javax.xml.bind.annotation.XmlAttribute;
6-
import javax.xml.bind.annotation.XmlRootElement;
7-
import javax.xml.bind.annotation.XmlValue;
8-
93
import com.fasterxml.jackson.annotation.JsonProperty;
104
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
115
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
6+
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
127
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
13-
148
import io.swagger.v3.oas.annotations.media.Schema;
159

10+
import javax.xml.bind.annotation.*;
11+
1612
@Schema(description="Intitulé sans son article et article associé")
1713
@XmlAccessorType(XmlAccessType.PROPERTY)
1814
@JsonPropertyOrder({"intituleSansArticle", "typeArticle"})
19-
@XmlRootElement(name="IntituleSansArticle")
15+
@XmlRootElement(name = "IntituleSansArticle")
16+
@JacksonXmlRootElement(localName = "IntituleSansArticle")
2017
public class IntituleSansArticle {
2118

22-
//@Schema(example = "Aigle")
23-
@XmlValue
19+
@Schema(example = "Aigle")
20+
//@XmlValue
2421
private String label = null;
2522

2623
@Schema(example = "5")
2724
private String typeArticle = null;
2825

2926

3027
@JacksonXmlText
31-
// @JsonProperty("intituleSansArticle")
32-
// @JacksonXmlProperty(localName="intituleSansArticle")
28+
@JsonProperty("intituleSansArticle")
29+
@JacksonXmlProperty(localName="IntituleSansArticle")
3330
@Schema(example = "Aigle")
3431
@XmlValue
3532
public String getIntituleSansArticle() {

0 commit comments

Comments
 (0)