Commit ffdae21a authored by Riegel's avatar Riegel
Browse files

Open Source release of CityDoctor GUI

parent a5a82382
Pipeline #10029 failed with stage
in 8 seconds
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.healer.genetic;
import static org.junit.Assert.assertFalse;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import org.junit.Test;
import Jama.EigenvalueDecomposition;
import de.hft.stuttgart.citydoctor2.check.AbstractCheck;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.Installation;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.math.CovarianceMatrix;
import de.hft.stuttgart.citydoctor2.math.OrthogonalRegressionPlane;
import de.hft.stuttgart.citydoctor2.math.Plane;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
import de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException;
import de.hft.stuttgart.citydoctor2.utils.Copy;
public class NonPlanarGenetic {
private static final int ERROR_PENALTY = 100000;
private Random r = new Random();
private Map<Integer, List<Long>> durationMap = new HashMap<>();
@Test
public void findVerticesForNonPlanarTest() throws CityGmlParseException, InvalidGmlFileException, IOException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setNumberOfRoundingPlacesInGlobalParameters(8);
config.setSchematronFilePathInGlobalParameters(null);
config.getParserConfiguration().setUseLowMemoryConsumption(false);
List<Path> gmlFiles = getPathsForGmlFiles();
for (Path gmlFile : gmlFiles) {
System.out.println("Parsing File: " + gmlFile);
CityDoctorModel model = CityGmlParser.parseCityGmlFile(gmlFile.toString(),
config.getParserConfiguration());
Checker c = new Checker(config, model);
c.runChecks();
List<CheckError> errors = new ArrayList<>();
model.createFeatureStream().forEach(co -> co.collectContainedErrors(errors));
assertFalse(errors.isEmpty());
NonPlanarPolygonDistancePlaneError planarError = null;
for (CheckError err : errors) {
if (err instanceof NonPlanarPolygonDistancePlaneError) {
planarError = (NonPlanarPolygonDistancePlaneError) err;
break;
}
}
if (planarError == null) {
throw new IllegalStateException("File " + gmlFile + " does not contain a planarity error");
}
CityObject feature = getFeature(planarError.getPolygon());
Polygon polygon = planarError.getPolygon();
// ensure a gml id has been generated
polygon.getGmlId();
int vertexCount = polygon.getExteriorRing().getVertices().size();
List<Vertex> subList = polygon.getExteriorRing().getVertices().subList(0, vertexCount - 1);
System.out.println("Computing polygon: " + polygon.getGmlId() + " with " + subList.size() + " Vertices");
FitnessEvaluation<PolygonVertexList> fitnessFunction = createFitnessEvaluationFunction(c, feature);
// complete calculation of all possibilities
if (subList.size() == 7) {
System.out.println();
}
Individual<PolygonVertexList> bestOfBoth = null;
if (subList.size() > 12) {
System.out.println("Skipping complete calculation, too many vertices");
bestOfBoth = doGeneticAlgorithmCalculation(polygon, subList, fitnessFunction);
} else {
bestOfBoth = doCompleteCalculation(polygon, fitnessFunction, vertexCount, subList);
}
System.out.println();
// abstands diff, ebene ohne punkt und normale ausgleichsebene
// if (bestOfBoth.getFitness() > -9000) {
// write only those that do not have errors in neighbor polygons
// errors in neighbors mean -10000 so check for higher than 9000 to be sure
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("result.txt"), StandardOpenOption.APPEND,
StandardOpenOption.CREATE)) {
for (int i = 0; i < bestOfBoth.getObject().getUseVertex().length; i++) {
boolean used = bestOfBoth.getObject().getUseVertex()[i];
Vertex v = bestOfBoth.getObject().getVertices().get(i);
int numberOfAdjacentPolygons = 0;
int numberOfPolygonsWithPlanarityIssues = 0;
int numberOfPolygonsWithOtherErrors = 0;
double distanceToPlane = planarError.getPlane().getDistance(v);
Set<Polygon> adjacentPolygons = v.getAdjacentPolygons(polygon.getParent());
numberOfAdjacentPolygons = adjacentPolygons.size();
for (Polygon adjacentPolygon : adjacentPolygons) {
List<CheckError> adjacentPolygonErrors = new ArrayList<>();
adjacentPolygon.collectContainedErrors(adjacentPolygonErrors);
// impossible to have duplicate errors so no Set filter on top
for (CheckError err : adjacentPolygonErrors) {
if (err instanceof NonPlanarPolygonDistancePlaneError) {
numberOfPolygonsWithPlanarityIssues++;
} else {
numberOfPolygonsWithOtherErrors++;
}
}
}
if (used) {
writer.write("1");
} else {
writer.write("0");
}
List<Vertex> vertices = new ArrayList<>();
for (Vertex vertexForPlan : subList) {
if (vertexForPlan == v) {
continue;
}
vertices.add(vertexForPlan);
}
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed);
Plane plane = OrthogonalRegressionPlane.calculatePlane(centroid, ed, eigenvalues);
double distanceDifferenceWithoutPoint = distanceToPlane - plane.getDistance(v);
writer.write(" 1:");
writer.write(Integer.toString(numberOfAdjacentPolygons));
writer.write(" 2:");
writer.write(Integer.toString(numberOfPolygonsWithPlanarityIssues));
writer.write(" 3:");
writer.write(Integer.toString(numberOfPolygonsWithOtherErrors));
writer.write(" 4:");
writer.write(Double.toString(distanceToPlane));
writer.write(" 5:");
writer.write(Double.toString(distanceDifferenceWithoutPoint));
writer.write('\n');
}
}
// }
}
for (Entry<Integer, List<Long>> e : durationMap.entrySet()) {
long sum = 0;
for (Long l : e.getValue()) {
sum += l;
}
System.out.println(e.getKey() + " Vertices took on average: " + (sum / (float) e.getValue().size()) + "ms");
}
}
private Individual<PolygonVertexList> doGeneticAlgorithmCalculation(Polygon polygon, List<Vertex> subList, FitnessEvaluation<PolygonVertexList> fitnessFunction)
throws IOException {
Mutation<PolygonVertexList> mutation = createMutationFunction();
Crossover<PolygonVertexList> crossOver = createCrossoverFunction();
Heuristic<PolygonVertexList> randomHeuristic = createHeursiticFunction(polygon, subList);
GeneticAlgorithm<PolygonVertexList> algo = GeneticAlgorithm.of(crossOver, mutation, randomHeuristic, fitnessFunction);
long startGen = System.currentTimeMillis();
algo.run();
long deltaGen = System.currentTimeMillis() - startGen;
System.out.println("Genetic Algo took: " + deltaGen + " ms");
durationMap.compute(subList.size(), (key, value) -> {
if (value == null) {
value = new ArrayList<>();
}
value.add(deltaGen);
return value;
});
PolygonVertexList result = algo.getResult().getObject();
printUsage(result.getUseVertex());
return algo.getResult();
}
private Heuristic<PolygonVertexList> createHeursiticFunction(Polygon polygon, List<Vertex> subList) {
Heuristic<PolygonVertexList> randomHeuristic = () -> {
PolygonVertexList vertexList = new PolygonVertexList(polygon, subList);
boolean[] useVertex = vertexList.getUseVertex();
for (int i = 0; i < useVertex.length; i++) {
useVertex[i] = r.nextBoolean();
}
validateIndividual(vertexList);
return vertexList;
};
return randomHeuristic;
}
private Crossover<PolygonVertexList> createCrossoverFunction() {
Crossover<PolygonVertexList> crossOver = (p1, p2) -> {
PolygonVertexList result = new PolygonVertexList(p1.getPolygon(), p1.getVertices());
int splitIndex = r.nextInt(p1.getUseVertex().length);
boolean[] array = result.getUseVertex();
for (int i = 0; i < splitIndex; i++) {
array[i] = p1.getUseVertex()[i];
}
for (int i = splitIndex; i < array.length; i++) {
array[i] = p2.getUseVertex()[i];
}
validateIndividual(result);
return result;
};
return crossOver;
}
private Mutation<PolygonVertexList> createMutationFunction() {
Mutation<PolygonVertexList> mutation = p -> {
int doSomethingValue = r.nextInt(100);
if (doSomethingValue > 50) {
// don't do anything
return p;
}
int index = r.nextInt(p.getUseVertex().length);
p.getUseVertex()[index] = !p.getUseVertex()[index];
validateIndividual(p);
return p;
};
return mutation;
}
private Individual<PolygonVertexList> doCompleteCalculation(Polygon polygon, FitnessEvaluation<PolygonVertexList> fitnessFunction, int vertexCount,
List<Vertex> subList) {
System.out.println("Doing complete calculation");
long startComplete = System.currentTimeMillis();
double highestFitness = Double.NEGATIVE_INFINITY;
int computeCount = 0;
PolygonVertexList bestIndividual = null;
for (int i = 7; i < Math.pow(2, vertexCount - 1) - 1; i++) {
PolygonVertexList individual = new PolygonVertexList(polygon, subList);
int usedVertexCount = 0;
boolean[] useVertices = individual.getUseVertex();
for (int j = 0; j < vertexCount - 1; j++) {
long l = (i >> j) & 1;
if (l == 1) {
usedVertexCount++;
useVertices[j] = true;
} else {
useVertices[j] = false;
}
}
if (usedVertexCount >= 3) {
double fitnessValue = fitnessFunction.evaluate(individual);
computeCount++;
if (fitnessValue > highestFitness) {
highestFitness = fitnessValue;
System.out.println("Best Fitness: " + highestFitness);
bestIndividual = individual;
}
}
if (usedVertexCount == vertexCount - 1) {
throw new IllegalStateException("All values should not be computed");
}
}
long deltaComplete = System.currentTimeMillis() - startComplete;
System.out.println("End. Best Fitness: " + highestFitness + " Individual: " + bestIndividual);
System.out.println("Computed " + computeCount + " individuals");
if (bestIndividual != null) {
printUsage(bestIndividual.getUseVertex());
}
System.out.println("Complete calculation took: " + deltaComplete + "ms");
durationMap.compute(subList.size(), (key, value) -> {
if (value == null) {
value = new ArrayList<>();
}
value.add(deltaComplete);
return value;
});
Individual<PolygonVertexList> bestResult = new Individual<PolygonVertexList>(bestIndividual);
bestResult.setFitness(highestFitness);
return bestResult;
}
private FitnessEvaluation<PolygonVertexList> createFitnessEvaluationFunction(Checker c, CityObject feature) {
FitnessEvaluation<PolygonVertexList> fitness = p -> {
List<Vertex> vertices = new ArrayList<>();
for (int i = 0; i < p.getVertices().size(); i++) {
if (p.getUseVertex()[i]) {
vertices.add(p.getVertices().get(i));
}
}
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
Vector3d eigenvalues = OrthogonalRegressionPlane.getEigenvalues(ed);
Plane plane = OrthogonalRegressionPlane.calculatePlane(centroid, ed, eigenvalues);
// check if it produces errors somewhere else
// first repair
// only repair clone
CityObject copy = Copy.copy(feature);
Polygon copyP = findPolygonInFeature(copy, p.getPolygon());
Set<Vertex> allVertices = new HashSet<>();
// collect all vertices, eliminating duplicates
collectVertices(copyP, allVertices);
// project each vertex to the plane and change the coordinates of existing
// vertices
for (Vertex v : allVertices) {
Vector3d newPoint = plane.projectPointToPlane(v);
v.setX(newPoint.getX());
v.setY(newPoint.getY());
v.setZ(newPoint.getZ());
}
// update edges
copy.prepareForChecking();
// recheck
c.executeChecksForCheckable(copy);
List<CheckError> remainingErrors = new ArrayList<>();
for (Polygon poly : collectNeighborPolygons(copyP)) {
poly.collectContainedErrors(remainingErrors);
}
double distanceSum = 0;
distanceSum = remainingErrors.size() * ERROR_PENALTY;
// check the distance of the original vertices to calculate distance
allVertices = new HashSet<>();
// collect all vertices, eliminating duplicates
collectVertices(p.getPolygon(), allVertices);
for (Vertex v : allVertices) {
double distance = plane.getDistance(v);
distanceSum += distance;
}
// negative, as higher is better but more distance is worse
return -distanceSum;
};
return fitness;
}
public long factorial(int n) {
long fact = 1;
for (int i = 2; i <= n; i++) {
fact = fact * i;
}
return fact;
}
private List<Path> getPathsForGmlFiles() throws IOException {
Path entry = Paths.get("C:/Job/CityGML Files/GE_P_NON_PLANAR_POLYGON_DISTANCE_PLANE");
List<Path> paths = new ArrayList<>();
Files.list(entry).forEach(path -> collectGmlFiles(path, paths));
return paths;
}
private void collectGmlFiles(Path path, List<Path> paths) {
if (Files.isRegularFile(path) && path.getFileName().toString().endsWith("gml")) {
paths.add(path);
} else if (Files.isDirectory(path)) {
try {
Files.list(path).forEach(p -> collectGmlFiles(p, paths));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
private void printUsage(boolean[] useVertex) {
System.out.println(createUseString(useVertex));
}
private String createUseString(boolean[] useVertex) {
StringBuilder builder = new StringBuilder();
for (boolean b : useVertex) {
if (b) {
builder.append('1');
} else {
builder.append('0');
}
}
return builder.toString();
}
private void validateIndividual(PolygonVertexList p) {
int index;
// count the number of used vertices
int useCount = 0;
for (boolean b : p.getUseVertex()) {
if (b) {
useCount++;
}
}
if (useCount < 3) {
// at least 3 points should be used
for (int i = 0; i < 3 - useCount; i++) {
index = r.nextInt(p.getUseVertex().length);
// search for a false index all the time
while (p.getUseVertex()[index]) {
index = r.nextInt(p.getUseVertex().length);
}
p.getUseVertex()[index] = true;
}
} else if (useCount == p.getVertices().size()) {
// not all vertices should be used
// flip one randomly back
index = r.nextInt(p.getUseVertex().length);
p.getUseVertex()[index] = false;
}
}
private Polygon findPolygonInFeature(CityObject copy, Polygon polygon) {
Polygon[] result = new Polygon[1];
copy.accept(new AbstractCheck() {
@Override
public void check(Polygon p) {
if (p.getGmlId().equals(polygon.getGmlId())) {
result[0] = p;
}
}
});
return result[0];
}
private CityObject getFeature(Polygon polygon) {
CityObject parent = polygon.getParent().getParent();
if (parent instanceof BoundarySurface) {
BoundarySurface bs = (BoundarySurface) parent;
parent = bs.getParent();
if (parent instanceof Installation) {
Installation bi = (Installation) parent;
parent = bi.getParent();
}
} else if (parent instanceof Installation) {
Installation bi = (Installation) parent;
parent = bi.getParent();
}
return parent;
}
private Set<Polygon> collectNeighborPolygons(Polygon polygon) {
Geometry geometry;
if (polygon.isLinkedTo()) {
geometry = polygon.getLinkedFromPolygon().getParent();
} else {
geometry = polygon.getParent();
}
Set<Polygon> polygons = new HashSet<>();
for (Vertex v : polygon.getExteriorRing().getVertices()) {
polygons.addAll(v.getAdjacentPolygons(geometry));
}
return polygons;
}
private void collectVertices(Polygon p, Set<Vertex> vertices) {
collectVertices(p.getExteriorRing(), vertices);
for (LinearRing lr : p.getInnerRings()) {
collectVertices(lr, vertices);
}
}
private void collectVertices(LinearRing ring, Set<Vertex> vertices) {
for (Vertex v : ring.getVertices()) {
vertices.add(v);
}
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.healer.genetic;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
public class PolygonVertexList {
private Polygon polygon;
private List<Vertex> vertices;
private boolean[] useVertex;
public PolygonVertexList(Polygon polygon, List<Vertex> vertices) {
this.polygon = polygon;
this.vertices = vertices;
useVertex = new boolean[vertices.size()];
}
public Polygon getPolygon() {
return polygon;
}
public List<Vertex> getVertices() {
return vertices;
}
public boolean[] getUseVertex() {
return useVertex;
}
}
package de.hft.stuttgart.citydoctor2.healer.genetic.gui;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import javafx.scene.image.Image;
public class ImageComparisonTest {
@Test
public void test() {
Image image = new Image(getClass().getResourceAsStream("genetic.png"));
assertEquals(1.0, ImageComparison.compare(image, image), 0.001);
}
}
<?xml version="1.0" encoding="utf-8"?>
<core:CityModel xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/2.0 http://schemas.opengis.net/citygml/2.0/cityGMLBase.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd">
<!--
Einfaches Gebäude mit Grundriss 3m x 5m und Satteldach, Traufhöhe 3m, Firsthöhe 4,5m
Modelliert mit Begrenzungsflächen (eine Dachfläche, 4 Wandflächen, 1 Grundfläche),
die Gebäudegeometrie als Solid, der auf die Polygone der Begrenzungsflächen referenziert
CityGML 2.0
Gebäudevolumen: 56,25 m3
10.5.2017
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.1"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.2"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.3"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.4"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.5"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.6"/>
<gml:surfaceMember xlink:href="#_Simple_BD.1_PG.7"/>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.2">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.2_LR.1">
<gml:posList srsDimension="3">
13.0 15.0 0.0
13.0 15.0 3.0
13.0 10.0 3.0
13.0 10.0 0.0
13.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_2">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.3">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.3_LR.1">
<gml:posList srsDimension="3">
10.0 15.0 0.0
10.0 15.0 3.0
11.5 15.0 4.5
13.0 15.0 3.0
13.0 15.0 0.0
10.0 15.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_3">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.4">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.4_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
10.0 15.0 3.0
10.0 15.0 0.0
10.0 10.0 0.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:WallSurface gml:id="_Simple_BD.1_WallSurface_4">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.5">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.5_LR.1">
<gml:posList srsDimension="3">
13.0 10.0 0.0
13.0 10.0 3.0
11.5 10.0 4.5
10.0 10.0 3.0
10.0 10.0 0.0
13.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:WallSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:RoofSurface gml:id="_Simple_BD.1_RoofSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.6">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.6_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 3.0
11.5 10.0 4.5
11.5 15.0 4.5
10.0 15.0 3.0
10.0 10.0 3.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.7">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.7_LR.1">
<gml:posList srsDimension="3">
11.5 10.0 4.5
13.0 10.0 3.0
13.0 15.0 3.0
11.5 15.0 4.5
11.5 10.0 4.5
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:RoofSurface>
</bldg:boundedBy>
<bldg:boundedBy>
<bldg:GroundSurface gml:id="_Simple_BD.1_GroundSurface_1">
<bldg:lod2MultiSurface>
<gml:MultiSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="_Simple_BD.1_PG.1">
<gml:exterior>
<gml:LinearRing gml:id="_Simple_BD.1_PG.1_LR.1">
<gml:posList srsDimension="3">
10.0 10.0 0.0
10.0 15.0 0.0
13.0 15.0 0.0
13.0 10.0 0.0
10.0 10.0 0.0
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</bldg:lod2MultiSurface>
</bldg:GroundSurface>
</bldg:boundedBy>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<core:CityModel xmlns:xAL="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:wtr="http://www.opengis.net/citygml/waterbody/2.0" xmlns:app="http://www.opengis.net/citygml/appearance/2.0" xmlns:tex="http://www.opengis.net/citygml/texturedsurface/2.0" xmlns:core="http://www.opengis.net/citygml/2.0" xmlns:veg="http://www.opengis.net/citygml/vegetation/2.0" xmlns:dem="http://www.opengis.net/citygml/relief/2.0" xmlns:tran="http://www.opengis.net/citygml/transportation/2.0" xmlns:bldg="http://www.opengis.net/citygml/building/2.0" xmlns:grp="http://www.opengis.net/citygml/cityobjectgroup/2.0" xmlns:tun="http://www.opengis.net/citygml/tunnel/2.0" xmlns:frn="http://www.opengis.net/citygml/cityfurniture/2.0" xmlns:brid="http://www.opengis.net/citygml/bridge/2.0" xmlns:gen="http://www.opengis.net/citygml/generics/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:luse="http://www.opengis.net/citygml/landuse/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/citygml/waterbody/2.0 http://schemas.opengis.net/citygml/waterbody/2.0/waterBody.xsd http://www.opengis.net/citygml/appearance/2.0 http://schemas.opengis.net/citygml/appearance/2.0/appearance.xsd http://www.opengis.net/citygml/texturedsurface/2.0 http://schemas.opengis.net/citygml/texturedsurface/2.0/texturedSurface.xsd http://www.opengis.net/citygml/vegetation/2.0 http://schemas.opengis.net/citygml/vegetation/2.0/vegetation.xsd http://www.opengis.net/citygml/relief/2.0 http://schemas.opengis.net/citygml/relief/2.0/relief.xsd http://www.opengis.net/citygml/transportation/2.0 http://schemas.opengis.net/citygml/transportation/2.0/transportation.xsd http://www.opengis.net/citygml/building/2.0 http://schemas.opengis.net/citygml/building/2.0/building.xsd http://www.opengis.net/citygml/cityobjectgroup/2.0 http://schemas.opengis.net/citygml/cityobjectgroup/2.0/cityObjectGroup.xsd http://www.opengis.net/citygml/tunnel/2.0 http://schemas.opengis.net/citygml/tunnel/2.0/tunnel.xsd http://www.opengis.net/citygml/cityfurniture/2.0 http://schemas.opengis.net/citygml/cityfurniture/2.0/cityFurniture.xsd http://www.opengis.net/citygml/bridge/2.0 http://schemas.opengis.net/citygml/bridge/2.0/bridge.xsd http://www.opengis.net/citygml/generics/2.0 http://schemas.opengis.net/citygml/generics/2.0/generics.xsd http://www.opengis.net/citygml/landuse/2.0 http://schemas.opengis.net/citygml/landuse/2.0/landUse.xsd">
<core:cityObjectMember>
<bldg:Building gml:id="CityDoctor_1554214838753_127">
<bldg:lod2Solid>
<gml:Solid>
<gml:exterior>
<gml:CompositeSurface>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838751_87">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838751_88">
<gml:posList srsDimension="3">14.287969134242111 6.980188861133052 11.705669515625218 8.176969134266791 11.854188861900461 17.075669515625194 8.176969134266791 11.854188861900461 17.075669515625194 8.513969134266326 6.604188861900462 11.705669515625218 9.511969134229538 6.669188861378921 11.705669515625218 14.287969134242111 6.980188861133052 11.705669515625218</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838751_89">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838751_90">
<gml:posList srsDimension="3">8.176969134266791 11.854188861900461 17.075669515625194 8.176969134266791 11.854188861900461 17.075669515625194 14.287969134242111 6.980188861133052 11.705669515625218 13.9599691342626 12.015188861282063 16.851669515625204 13.9599691342626 12.015188861282063 16.851669515625204 13.94496913424863 12.234188861788702 17.075669515625194 13.94496913424863 12.234188861788702 17.075669515625194 8.176969134266791 11.854188861900461 17.075669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838751_91">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838751_92">
<gml:posList srsDimension="3">7.835969134251889 17.16018886176635 11.705669515625218 10.890969134244905 14.697188861311865 14.390669515625191 13.94496913424863 12.234188861788702 17.075669515625194 13.94496913424863 12.234188861788702 17.075669515625194 13.59996913427657 17.532188861274612 11.705669515625218 7.835969134251889 17.16018886176635 11.705669515625218</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838751_93">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838751_94">
<gml:posList srsDimension="3">10.890969134244905 14.697188861311865 14.390669515625191 7.835969134251889 17.16018886176635 11.705669515625218 8.176969134266791 11.854188861900461 17.075669515625194 8.176969134266791 11.854188861900461 17.075669515625194 13.94496913424863 12.234188861788702 17.075669515625194 13.94496913424863 12.234188861788702 17.075669515625194 10.890969134244905 14.697188861311865 14.390669515625191</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838751_95">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_96">
<gml:posList srsDimension="3">14.287969134242111 6.980188861133052 16.845669515625204 13.9599691342626 12.015188861282063 16.851669515625204 13.9599691342626 12.015188861282063 16.851669515625204 9.511969134229538 6.669188861378921 11.705669515625218 14.287969134242111 6.980188861133052 16.845669515625204 14.287969134242111 6.980188861133052 16.845669515625204</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_97">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_98">
<gml:posList srsDimension="3">11.757969134272379 16.75918886122991 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191 9.761969134229538 16.627188861013842 14.390669515625191 9.761969134229538 16.627188861013842 14.390669515625191 9.892969134281692 14.631188861669493 14.390669515625191 9.892969134281692 14.631188861669493 14.390669515625191 11.888969134266326 14.76318886188556 14.390669515625191 11.888969134266326 14.76318886188556 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_99">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_100">
<gml:posList srsDimension="3">7.835969134251889 17.16018886176635 6.105669515625194 13.59996913427657 17.532188861274612 6.105669515625194 14.287969134242111 6.980188861133052 6.105669515625194 8.513969134266326 6.604188861900462 6.105669515625194 7.835969134251889 17.16018886176635 6.105669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_101">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_102">
<gml:posList srsDimension="3">13.59996913427657 17.532188861274612 11.705669515625218 7.835969134251889 17.16018886176635 11.705669515625218 8.513969134266326 6.604188861900462 11.705669515625218 9.511969134229538 6.669188861378921 11.705669515625218 14.287969134242111 6.980188861133052 11.705669515625218 13.59996913427657 17.532188861274612 11.705669515625218</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_103">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_104">
<gml:posList srsDimension="3">13.59996913427657 17.532188861274612 6.105669515625194 7.835969134251889 17.16018886176635 6.105669515625194 7.835969134251889 17.16018886176635 11.705669515625218 13.59996913427657 17.532188861274612 11.705669515625218 13.59996913427657 17.532188861274612 6.105669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_105">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_106">
<gml:posList srsDimension="3">14.287969134242111 6.980188861133052 6.105669515625194 13.59996913427657 17.532188861274612 6.105669515625194 13.59996913427657 17.532188861274612 11.705669515625218 14.287969134242111 6.980188861133052 11.705669515625218 14.287969134242111 6.980188861133052 6.105669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_107">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_108">
<gml:posList srsDimension="3">8.513969134266326 6.604188861900462 6.105669515625194 14.287969134242111 6.980188861133052 6.105669515625194 14.287969134242111 6.980188861133052 11.705669515625218 9.511969134229538 6.669188861378921 11.705669515625218 8.513969134266326 6.604188861900462 11.705669515625218 8.513969134266326 6.604188861900462 6.105669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_109">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_110">
<gml:posList srsDimension="3">7.835969134251889 17.16018886176635 6.105669515625194 8.513969134266326 6.604188861900462 6.105669515625194 8.513969134266326 6.604188861900462 11.705669515625218 7.835969134251889 17.16018886176635 11.705669515625218 7.835969134251889 17.16018886176635 6.105669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_111">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_112">
<gml:posList srsDimension="3">8.176969134266791 11.854188861900461 17.075669515625194 8.176969134266791 11.854188861900461 17.075669515625194 7.835969134251889 17.16018886176635 11.705669515625218 8.513969134266326 6.604188861900462 11.705669515625218 8.176969134266791 11.854188861900461 17.075669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_113">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_114">
<gml:posList srsDimension="3">13.94496913424863 12.234188861788702 17.075669515625194 13.94496913424863 12.234188861788702 17.075669515625194 13.9599691342626 12.015188861282063 16.851669515625204 13.9599691342626 12.015188861282063 16.851669515625204 14.287969134242111 6.980188861133052 11.705669515625218 13.59996913427657 17.532188861274612 11.705669515625218 13.94496913424863 12.234188861788702 17.075669515625194</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_115">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_116">
<gml:posList srsDimension="3">13.9599691342626 12.015188861282063 16.851669515625204 13.9599691342626 12.015188861282063 16.851669515625204 9.511969134229538 6.669188861378921 11.705669515625218 14.287969134242111 6.980188861133052 11.705669515625218 13.9599691342626 12.015188861282063 16.851669515625204</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_117">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_118">
<gml:posList srsDimension="3">13.9599691342626 12.015188861282063 16.851669515625204 13.9599691342626 12.015188861282063 16.851669515625204 14.287969134242111 6.980188861133052 16.845669515625204 14.287969134242111 6.980188861133052 16.845669515625204 14.287969134242111 6.980188861133052 11.705669515625218 13.9599691342626 12.015188861282063 16.851669515625204</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_119">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838752_120">
<gml:posList srsDimension="3">11.757969134272379 16.75918886122991 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191 11.757969134272379 16.75918886122991 12.36666951562519 9.761969134229538 16.627188861013842 12.3686695156252 9.761969134229538 16.627188861013842 14.390669515625191 9.761969134229538 16.627188861013842 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838752_121">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838753_122">
<gml:posList srsDimension="3">9.761969134229538 16.627188861013842 12.3686695156252 9.892969134281692 14.631188861669493 14.390669515625191 9.892969134281692 14.631188861669493 14.390669515625191 9.761969134229538 16.627188861013842 14.390669515625191 9.761969134229538 16.627188861013842 14.390669515625191 9.761969134229538 16.627188861013842 12.3686695156252</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838753_123">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838753_124">
<gml:posList srsDimension="3">14.287969134242111 6.980188861133052 11.705669515625218 14.287969134242111 6.980188861133052 16.845669515625204 14.287969134242111 6.980188861133052 16.845669515625204 14.287969134242111 6.980188861133052 16.845669515625204 9.511969134229538 6.669188861378921 11.705669515625218 14.287969134242111 6.980188861133052 11.705669515625218</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
<gml:surfaceMember>
<gml:Polygon gml:id="CityDoctor_1554214838753_125">
<gml:exterior>
<gml:LinearRing gml:id="CityDoctor_1554214838753_126">
<gml:posList srsDimension="3">11.757969134272379 16.75918886122991 12.36666951562519 11.757969134272379 16.75918886122991 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191 11.757969134272379 16.75918886122991 14.390669515625191 11.888969134266326 14.76318886188556 14.390669515625191 11.888969134266326 14.76318886188556 14.390669515625191 11.757969134272379 16.75918886122991 12.36666951562519</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:CompositeSurface>
</gml:exterior>
</gml:Solid>
</bldg:lod2Solid>
</bldg:Building>
</core:cityObjectMember>
</core:CityModel>
\ No newline at end of file
localhost:5432:*:postgres:admin
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.14.1</version>
</parent>
<artifactId>CityDoctorWebService</artifactId>
<packaging>war</packaging>
<name>CityDoctorWebService</name>
<dependencies>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorModel</artifactId>
</dependency>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorValidation</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.29</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.29</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.29</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.29</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
</dependencies>
<build>
<finalName>CityDoctorWebService</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package de.hft.stuttgart.citydoctor2.webservice;
public class AuthenticationException extends Exception {
private static final long serialVersionUID = 1734788211196618632L;
public AuthenticationException() {
super();
}
public AuthenticationException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public AuthenticationException(String message, Throwable cause) {
super(message, cause);
}
public AuthenticationException(String message) {
super(message);
}
public AuthenticationException(Throwable cause) {
super(cause);
}
}
package de.hft.stuttgart.citydoctor2.webservice;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.BuildingEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.ChecksEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.LoginEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.LogoutEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.ModelsEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.RegisterEndpoint;
import de.hft.stuttgart.citydoctor2.webservice.endpoints.ValidationEndpoint;
@ApplicationPath("/rest")
public class CityDoctorWebService extends ResourceConfig {
public CityDoctorWebService() {
register(LoginEndpoint.class);
register(RegisterEndpoint.class);
register(ModelsEndpoint.class);
register(MultiPartFeature.class);
register(BuildingEndpoint.class);
register(ValidationEndpoint.class);
register(LogoutEndpoint.class);
register(ChecksEndpoint.class);
}
}
package de.hft.stuttgart.citydoctor2.webservice;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.webservice.database.ModelQueries;
import de.hft.stuttgart.citydoctor2.webservice.utils.HibernateUtils;
@WebListener
public class ServletInitListener implements ServletContextListener {
private static Logger logger = LogManager.getLogger(ServletInitListener.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
HibernateUtils.init();
logger.info("Removing models in state 'parsing'");
ModelQueries.cleanup();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
HibernateUtils.shutdown();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
try {
DriverManager.deregisterDriver(driver);
logger.info("Deregistering JDBC driver: {}", driver);
} catch (SQLException e) {
logger.error("Error deregistering driver {}", driver);
logger.error("", e);
}
}
}
}
}
package de.hft.stuttgart.citydoctor2.webservice;
public class UnknownUserException extends Exception {
private static final long serialVersionUID = -8582004030128118170L;
public UnknownUserException() {
super();
}
public UnknownUserException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public UnknownUserException(String message, Throwable cause) {
super(message, cause);
}
public UnknownUserException(String message) {
super(message);
}
public UnknownUserException(Throwable cause) {
super(cause);
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import org.hibernate.Session;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import de.hft.stuttgart.citydoctor2.webservice.model.BuildingReference;
import de.hft.stuttgart.citydoctor2.webservice.model.BuildingReferenceWithErrorIndicator;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebBuilding;
public class BuildingQueries {
private BuildingQueries() {
// only static use
}
public static void persistBuilding(WebBuilding buildingRef, EntityManager manager) {
manager.getTransaction().begin();
try {
manager.persist(buildingRef);
} finally {
manager.getTransaction().commit();
}
}
public static List<BuildingReference> getBuildingsForModel(int from, int modelId, EntityManager manager) {
Session session = manager.unwrap(Session.class);
try {
session.getTransaction().begin();
Query<BuildingReference> query = session.createQuery("SELECT new de.hft.stuttgart.citydoctor2."
+ "webservice.model.BuildingReference(b.id, b.gmlId, b.modelWidth) FROM WebBuilding b WHERE model.id = ?1",
BuildingReference.class);
query.setParameter(1, modelId);
query.setMaxResults(20);
query.setFirstResult(from);
return query.getResultList();
} finally {
session.getTransaction().commit();
}
}
public static List<String> getBuildingsForSearchString(String s, int modelId, EntityManager manager) {
FullTextEntityManager textEntityManager = Search.getFullTextEntityManager(manager);
textEntityManager.getTransaction().begin();
try {
QueryBuilder queryBuilder = textEntityManager.getSearchFactory().buildQueryBuilder().forEntity(WebBuilding.class).get();
org.apache.lucene.search.Query luceneQ = queryBuilder.keyword().onField("gmlId").matching(s).createQuery();
FullTextQuery query = textEntityManager.createFullTextQuery(luceneQ, WebBuilding.class);
query.setMaxResults(5);
@SuppressWarnings("unchecked")
List<WebBuilding> resultList = query.getResultList();
for (WebBuilding b : resultList) {
System.out.println(b.getGmlId());
}
return null;
} finally {
textEntityManager.getTransaction().commit();
}
}
public static WebBuilding getBuildingForGmlId(String gmlId, int modelId, EntityManager manager) {
manager.getTransaction().begin();
try {
TypedQuery<WebBuilding> query = manager.createQuery("FROM WebBuilding WHERE model.id = ?1 AND gmlId = ?2",
WebBuilding.class);
query.setParameter(1, modelId);
query.setParameter(2, gmlId);
return query.getSingleResult();
} finally {
manager.getTransaction().commit();
}
}
public static long getBuildingCountForModel(int modelId, EntityManager manager) {
manager.getTransaction().begin();
try {
javax.persistence.Query query = manager
.createQuery("SELECT COUNT (b.id) FROM WebBuilding b WHERE b.model.id = ?1");
query.setParameter(1, modelId);
return (Long) query.getSingleResult();
} finally {
manager.getTransaction().commit();
}
}
public static List<BuildingReference> getBuildingsWithErrorIndicator(int from, int modelId,
Integer validationId, EntityManager manager) {
Session session = manager.unwrap(Session.class);
try {
session.getTransaction().begin();
@SuppressWarnings("unchecked")
NativeQuery<Object[]> nQuery = session.createSQLQuery(
"SELECT b.id, b.gml_id, b.model_width, CASE WHEN e.id IS NULL THEN FALSE ELSE TRUE END "
+ "FROM building_reference b "
+ "LEFT JOIN (SELECT br.id FROM building_reference br WHERE EXISTS "
+ "(SELECT 1 FROM weberror ee WHERE ee.building_id = br.id AND ee.validation_id = ?2)) AS e ON (e.id = b.id) "
+ "WHERE b.model_id = ?1");
nQuery.setParameter(1, modelId);
nQuery.setParameter(2, validationId);
nQuery.setFirstResult(from);
nQuery.setMaxResults(20);
List<Object[]> list = nQuery.list();
List<BuildingReference> result = new ArrayList<>();
for (Object[] objects : list) {
result.add(new BuildingReferenceWithErrorIndicator((Integer) objects[0], (String) objects[1], (Double) objects[2], (Boolean) objects[3]));
}
return result;
} finally {
session.getTransaction().commit();
}
}
public static long getErrorBuildingCountForModel(int modelId, Integer validationId, EntityManager manager) {
Session session = manager.unwrap(Session.class);
session.getTransaction().begin();
try {
@SuppressWarnings("unchecked")
NativeQuery<Object> nQuery = session.createSQLQuery(
"SELECT COUNT(b.id) "
+ "FROM building_reference b "
+ "JOIN (SELECT br.id FROM building_reference br WHERE EXISTS "
+ "(SELECT 1 FROM weberror ee WHERE ee.building_id = br.id AND ee.validation_id = ?2)) AS e ON (e.id = b.id) "
+ "WHERE b.model_id = ?1");
nQuery.setParameter(1, modelId);
nQuery.setParameter(2, validationId);
return ((BigInteger) nQuery.getSingleResult()).longValueExact();
} finally {
session.getTransaction().commit();
}
}
public static List<BuildingReference> getErrorBuildingsWithErrorIndicator(int from, int modelId,
Integer validationId, EntityManager manager) {
Session session = manager.unwrap(Session.class);
try {
session.getTransaction().begin();
@SuppressWarnings("unchecked")
NativeQuery<Object[]> nQuery = session.createSQLQuery(
"SELECT b.id, b.gml_id, b.model_width, TRUE "
+ "FROM building_reference b "
+ "JOIN (SELECT br.id FROM building_reference br WHERE EXISTS "
+ "(SELECT 1 FROM weberror ee WHERE ee.building_id = br.id AND ee.validation_id = ?2)) AS e ON (e.id = b.id) "
+ "WHERE b.model_id = ?1");
nQuery.setParameter(1, modelId);
nQuery.setParameter(2, validationId);
nQuery.setFirstResult(from);
nQuery.setMaxResults(20);
List<Object[]> list = nQuery.list();
List<BuildingReference> result = new ArrayList<>();
for (Object[] objects : list) {
result.add(new BuildingReferenceWithErrorIndicator((Integer) objects[0], (String) objects[1], (Double) objects[2], (Boolean) objects[3]));
}
return result;
} finally {
session.getTransaction().commit();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.Validation;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebBuilding;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebError;
public class ErrorQueries {
public static void addErrorToBuilding(WebBuilding building, Validation validation, WebError webError, EntityManager manager) {
manager.getTransaction().begin();
try {
building.getErrors().add(webError);
validation.getErrors().add(webError);
manager.persist(webError);
} finally {
manager.getTransaction().commit();
}
}
public static List<WebError> getErrorsForBuilding(int buildingId, int validationId, EntityManager manager) {
manager.getTransaction().begin();
try {
TypedQuery<WebError> query = manager.createQuery("FROM WebError WHERE building.id = ?1 AND validation.id =?2", WebError.class);
query.setParameter(1, buildingId);
query.setParameter(2, validationId);
return query.getResultList();
} finally {
manager.getTransaction().commit();
}
}
public static void deleteErrorsForBuilding(int buildingId, EntityManager manager) {
manager.getTransaction().begin();
try {
Query query = manager.createQuery("DELETE FROM WebError WHERE building.id = ?1");
query.setParameter(1, buildingId);
query.executeUpdate();
} finally {
manager.getTransaction().commit();
}
}
public static void deleteErrorsForValidation(int validationId, EntityManager manager) {
manager.getTransaction().begin();
try {
Query query = manager.createQuery("DELETE FROM WebError WHERE validation.id = ?1");
query.setParameter(1, validationId);
query.executeUpdate();
} finally {
manager.getTransaction().commit();
}
}
public static void deleteErrorsForModel(int modelId, EntityManager manager) {
manager.getTransaction().begin();
try {
Query query = manager.createQuery("DELETE er FROM WebError er JOIN FETCH er.building b WHERE b.model.id = ?1");
query.setParameter(1, modelId);
query.executeUpdate();
} finally {
manager.getTransaction().commit();
}
}
public static List<WebError> getErrorsForModel(int modelId, EntityManager manager) {
manager.getTransaction().begin();
try {
TypedQuery<WebError> query = manager.createQuery("FROM WebError WHERE building.model.id = ?1", WebError.class);
query.setParameter(1, modelId);
return query.getResultList();
} finally {
manager.getTransaction().commit();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import javax.persistence.EntityManager;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebBuilding;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebGeometry;
public class GeometryQueries {
private GeometryQueries() {
// only static use
}
public static void persistGeometryAndApplyToBuilding(WebGeometry geom, WebBuilding ref, EntityManager manager) {
manager.getTransaction().begin();
try {
manager.persist(geom);
} finally {
manager.getTransaction().commit();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import de.hft.stuttgart.citydoctor2.webservice.model.ParseStatus;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.GmlFile;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebCityDoctorModel;
import de.hft.stuttgart.citydoctor2.webservice.utils.HibernateUtils;
public class ModelQueries {
private ModelQueries() {
// only static usage
}
public static void storeModel(WebCityDoctorModel webModel, EntityManager manager) {
try {
manager.getTransaction().begin();
manager.persist(webModel);
} finally {
manager.getTransaction().commit();
}
}
public static void updateStatus(WebCityDoctorModel webModel, ParseStatus status, EntityManager manager) {
try {
manager.getTransaction().begin();
webModel.setStatus(status);
} finally {
manager.getTransaction().commit();
}
}
public static void updateModelWithBlob(WebCityDoctorModel webModel, GmlFile blob, EntityManager manager) {
try {
manager.getTransaction().begin();
manager.persist(blob);
webModel.setZipFile(blob);
} finally {
manager.getTransaction().commit();
}
}
public static void cleanup() {
EntityManager manager = HibernateUtils.createManager();
try {
manager.getTransaction().begin();
Query query = manager.createQuery("DELETE FROM WebCityDoctorModel WHERE status = " + ParseStatus.PARSING.ordinal());
query.executeUpdate();
manager.getTransaction().commit();
} finally {
manager.close();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import java.time.LocalDateTime;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.Token;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.User;
public class TokenQueries {
private TokenQueries() {
// not used
}
public static Token getTokenForTokenString(String inputToken, String address, EntityManager manager) {
manager.getTransaction().begin();
Token token = null;
try {
TypedQuery<Token> q = manager.createQuery("FROM Token t WHERE t.tokenString = ?1 AND address = ?2", Token.class);
q.setParameter(1, inputToken);
q.setParameter(2, address);
token = q.getSingleResult();
} catch (NoResultException e) {
// ignore
} finally {
manager.getTransaction().commit();
}
return token;
}
public static void persistToken(Token token, EntityManager manager) {
manager.getTransaction().begin();
try {
manager.persist(token);
} finally {
manager.getTransaction().commit();
}
}
public static void updateExpirationDate(LocalDateTime expirationDate, Token token, EntityManager manager) {
manager.getTransaction().begin();
try {
token.setExpires(expirationDate);
} finally {
manager.getTransaction().commit();
}
}
public static Token getTokenForUser(User user, String addr, EntityManager manager) {
manager.getTransaction().begin();
Token token = null;
try {
TypedQuery<Token> q = manager.createQuery("FROM Token t WHERE t.user.id = ?1 AND address = ?2", Token.class);
q.setParameter(1, user.getId());
q.setParameter(2, addr);
token = q.getSingleResult();
} catch (NoResultException e) {
// ignore
} finally {
manager.getTransaction().commit();
}
return token;
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.User;
public class UserQueries {
private UserQueries() {
// only static use
}
public static User getUserForUsername(String username, EntityManager manager) {
manager.getTransaction().begin();
TypedQuery<User> q = manager.createQuery("FROM User WHERE mail = ?1", User.class);
q.setParameter(1, username);
User user = null;
try {
user = q.getSingleResult();
} catch (NoResultException e) {
// ignore
} finally {
manager.getTransaction().commit();
}
return user;
}
public static void createUser(User user, EntityManager manager) {
manager.getTransaction().begin();
try {
manager.persist(user);
} finally {
manager.getTransaction().commit();
}
}
public static void deleteUser(User user, EntityManager manager) {
manager.getTransaction().begin();
try {
manager.remove(user);
} finally {
manager.getTransaction().commit();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.database;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import de.hft.stuttgart.citydoctor2.webservice.model.ValidationStatus;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.FeatureValidationStatus;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.Validation;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebBuilding;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebCityDoctorModel;
public class ValidationQueries {
private ValidationQueries() {
// only static use
}
public static void addFeatureValidationStatus(WebBuilding b, Validation v, FeatureValidationStatus s, EntityManager manager) {
try {
manager.getTransaction().begin();
b.getErrorStatus().add(s);
v.getErrorStatus().add(s);
manager.persist(s);
} finally {
manager.getTransaction().commit();
}
}
public static void persistValidation(EntityManager manager, WebCityDoctorModel model, Validation validation) {
try {
manager.getTransaction().begin();
manager.persist(validation);
model.getValidations().add(validation);
} finally {
manager.getTransaction().commit();
}
}
public static void updateStatus(Validation valid, ValidationStatus status, EntityManager manager) {
try {
manager.getTransaction().begin();
valid.setStatus(status);
} finally {
manager.getTransaction().commit();
}
}
public static void updateValidationWithReports(Validation validation, byte[] pdfArray,
byte[] xmlArray, EntityManager manager) {
try {
manager.getTransaction().begin();
validation.setPdfReport(pdfArray);
validation.setXmlReport(xmlArray);
} finally {
manager.getTransaction().commit();
}
}
public static Validation getValidation(int validationId, EntityManager manager) {
return manager.find(Validation.class, validationId);
}
public static boolean hasFeatureErrors(WebBuilding b, Validation validation, EntityManager manager) {
try {
manager.getTransaction().begin();
Query query = manager.createQuery("SELECT 1 FROM WebError WHERE EXISTS (SELECT 1 FROM WebError WHERE building = ?1 AND validation = ?2)");
query.setParameter(1, b);
query.setParameter(2, validation);
return !query.getResultList().isEmpty();
} finally {
manager.getTransaction().commit();
}
}
}
package de.hft.stuttgart.citydoctor2.webservice.endpoints;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.webservice.AuthenticationException;
import de.hft.stuttgart.citydoctor2.webservice.database.ErrorQueries;
import de.hft.stuttgart.citydoctor2.webservice.model.ErrorReference;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.User;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebBuilding;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebCityDoctorModel;
import de.hft.stuttgart.citydoctor2.webservice.model.entities.WebError;
import de.hft.stuttgart.citydoctor2.webservice.utils.AuthenticationUtils;
import de.hft.stuttgart.citydoctor2.webservice.utils.HibernateUtils;
@Path("")
public class BuildingEndpoint {
private static final Logger logger = LogManager.getLogger(BuildingEndpoint.class);
@GET
@Path("buildings/{buildingId}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getGeometry(@PathParam("buildingId") int buildingId, @Context HttpServletRequest request) {
EntityManager manager = null;
try {
manager = HibernateUtils.createManager();
User user = AuthenticationUtils.authenticateUser(request, manager);
WebBuilding building = manager.find(WebBuilding.class, buildingId);
Response response = checkAccessRightsForBuilding(buildingId, user, building);
if (response != null) {
return response;
}
byte[] array = building.getViewData();
return Response.ok(array).build();
} catch (AuthenticationException e) {
logger.trace(AuthenticationUtils.AUTHENTICATION_DENIED, request.getRemoteAddr(), e);
return Response.status(Status.FORBIDDEN).build();
} catch (Exception e) {
logger.fatal("Error while retrieving building with id {}", buildingId);
logger.catching(e);
return Response.serverError().build();
} finally {
if (manager != null) {
manager.close();
}
}
}
@GET
@Path("buildings/{buildingId}/validation/{validationId}/errors")
@Produces(MediaType.APPLICATION_JSON)
public Response getErrors(@PathParam("buildingId") int buildingId, @PathParam("validationId") int validationId,
@Context HttpServletRequest request) {
EntityManager manager = null;
try {
manager = HibernateUtils.createManager();
User user = AuthenticationUtils.authenticateUser(request, manager);
WebBuilding building = manager.find(WebBuilding.class, buildingId);
Response response = checkAccessRightsForBuilding(buildingId, user, building);
if (response != null) {
return response;
}
List<ErrorReference> refs = new ArrayList<>();
List<WebError> errors = ErrorQueries.getErrorsForBuilding(buildingId, validationId, manager);
for (WebError err : errors) {
refs.add(ErrorReference.of(err));
}
return Response.ok(refs).build();
} catch (AuthenticationException e) {
logger.trace(AuthenticationUtils.AUTHENTICATION_DENIED, request.getRemoteAddr(), e);
return Response.status(Status.FORBIDDEN).build();
} catch (Exception e) {
logger.fatal("Error while retrieving errors for building with id {}", buildingId);
logger.catching(e);
return Response.serverError().build();
} finally {
if (manager != null) {
manager.close();
}
}
}
private Response checkAccessRightsForBuilding(int buildingId, User user, WebBuilding building) {
if (building == null) {
logger.warn("User {} tried to access non existing building with id {}", user.getId(), buildingId);
return Response.status(Status.FORBIDDEN).build();
}
WebCityDoctorModel model = building.getModel();
if (model.getOwner().getId() != user.getId()) {
logger.warn("User {} tried to access not owned model with id {}", user.getId(), model.getId());
return Response.status(Status.FORBIDDEN).build();
}
return null;
}
}
package de.hft.stuttgart.citydoctor2.webservice.endpoints;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import de.hft.stuttgart.citydoctor2.check.DefaultParameter;
import de.hft.stuttgart.citydoctor2.check.Requirement;
import de.hft.stuttgart.citydoctor2.check.RequirementType;
import de.hft.stuttgart.citydoctor2.checks.CheckPrototype;
import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.webservice.model.AvailableChecksReturnType;
import de.hft.stuttgart.citydoctor2.webservice.model.CheckReturnType;
@Path("checks")
public class ChecksEndpoint {
private AvailableChecksReturnType returnValue;
public ChecksEndpoint() {
returnValue = new AvailableChecksReturnType();
List<CheckReturnType> geometricChecks = new ArrayList<>();
List<CheckReturnType> semanticChecks = new ArrayList<>();
returnValue.setGeometricChecks(geometricChecks);
returnValue.setSemanticChecks(semanticChecks);
List<CheckPrototype> prototypes = Checks.getCheckPrototypes();
for (CheckPrototype prototype : prototypes) {
CheckReturnType returnVal = new CheckReturnType();
returnVal.setName(prototype.getCheckId().toString());
List<DefaultParameter> defaultParameters = new ArrayList<>();
for (Requirement req : prototype.checksRequirements()) {
defaultParameters.addAll(req.getDefaultParameter());
}
returnVal.setParameters(defaultParameters);
if (prototype.getType() == RequirementType.GEOMETRY) {
geometricChecks.add(returnVal);
} else if (prototype.getType() == RequirementType.SEMANTIC) {
semanticChecks.add(returnVal);
} else {
throw new IllegalStateException("Cannot handle check type: " + prototype.getType());
}
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getChecks() {
return Response.ok(returnValue).build();
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment