Commit 219d36ea authored by Luna Riegel's avatar Luna Riegel
Browse files

Merge branch 'refs/heads/dev' into dev_advanced_db_management

# Conflicts:
#	CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/EmbeddedDatabaseHandler.java
parents 1c665219 5df59c7a
......@@ -65,7 +65,7 @@ public class CityGMLWriterUtils {
}
public static void writeCityModel(String file, CityDoctorModel model) throws CityDoctorWriteException {
CityGMLContext gmlContext = CityGmlParser.getContext();
CityGMLContext gmlContext = CityGmlParser.setupContext();
CityModel cModel = model.getCityModel();
CityGMLOutputFactory factory = gmlContext.createCityGMLOutputFactory(model.getCityGMLVersion());
try (CityGMLWriter writer = factory.createCityGMLWriter(new File(file))) {
......
package org.xmlobjects.xml;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
public class Attributes implements Serializable {
private static final long serialVersionUID = 8942583366234714632L;
private final Map<String, Map<String, TextContent>> attributes = new HashMap<>();
public boolean isEmpty() {
return attributes.isEmpty();
}
public void add(String namespaceURI, String localName, TextContent value) {
attributes.computeIfAbsent(namespaceURI, v -> new HashMap<>()).put(localName, value);
}
public void add(String namespaceURI, String localName, String value) {
add(namespaceURI, localName, TextContent.of(value));
}
public void add(String localName, TextContent value) {
add(XMLConstants.NULL_NS_URI, localName, value);
}
public void add(String localName, String value) {
add(localName, TextContent.of(value));
}
public void add(QName name, TextContent value) {
add(name.getNamespaceURI(), name.getLocalPart(), value);
}
public void add(QName name, String value) {
add(name, TextContent.of(value));
}
public void addAll(String namespaceURI, Map<String, TextContent> attributes) {
this.attributes.computeIfAbsent(namespaceURI, v -> new HashMap<>()).putAll(attributes);
}
public Map<String, Map<String, TextContent>> get() {
return attributes;
}
public Map<String, TextContent> get(String namespaceURI) {
return attributes.getOrDefault(namespaceURI, Collections.emptyMap());
}
public TextContent getValue(String localName) {
return getValue(XMLConstants.NULL_NS_URI, localName);
}
public TextContent getValue(String namespaceURI, String localName) {
return get(namespaceURI).getOrDefault(localName, TextContent.empty());
}
public TextContent getValue(QName name) {
return getValue(name.getNamespaceURI(), name.getLocalPart());
}
public Attributes copy() {
Attributes copy = new Attributes();
copy.attributes.putAll(attributes);
return copy;
}
}
package org.xmlobjects.xml;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
public class TextContent implements Serializable {
private static final long serialVersionUID = -3862132079185243841L;
private static final DatatypeFactory XML_TYPE_FACTORY;
private static final TextContent EMPTY = new TextContent("");
private static Function<LocalDateTime, ZoneOffset> ZONE_OFFSET_PROVIDER = dateTime -> ZoneOffset.systemDefault().getRules().getOffset(dateTime);
private static boolean WITH_TIME_OFFSET = true;
private static boolean WITH_DATE_OFFSET = false;
private enum Fields { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, NANO, TIMEZONE }
private static final EnumSet<Fields> DATE_TIME_FIELDS = EnumSet.allOf(Fields.class);
private static final EnumSet<Fields> TIME_FIELDS = EnumSet.of(Fields.HOUR, Fields.MINUTE, Fields.SECOND, Fields.NANO, Fields.TIMEZONE);
private static final EnumSet<Fields> DATE_FIELDS = EnumSet.of(Fields.YEAR, Fields.MONTH, Fields.DAY, Fields.TIMEZONE);
private static final EnumSet<Fields> GYEAR_MONTH_FIELDS = EnumSet.of(Fields.YEAR, Fields.MONTH, Fields.TIMEZONE);
private static final EnumSet<Fields> GMONTH_DAY_FIELDS = EnumSet.of(Fields.MONTH, Fields.DAY, Fields.TIMEZONE);
private static final EnumSet<Fields> GDAY_FIELDS = EnumSet.of(Fields.DAY, Fields.TIMEZONE);
private static final EnumSet<Fields> GMONTH_FIELDS = EnumSet.of(Fields.MONTH, Fields.TIMEZONE);
private static final EnumSet<Fields> GYEAR_FIELDS = EnumSet.of(Fields.YEAR, Fields.TIMEZONE);
static {
try {
XML_TYPE_FACTORY = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
throw new RuntimeException("Failed to initialize datatype factory.", e);
}
}
private String content;
private String trimmedContent;
private String[] tokenizedContent;
private Object value;
private transient Function<LocalDateTime, ZoneOffset> zoneOffsetProvider = ZONE_OFFSET_PROVIDER;
private TextContent(String content) {
this.content = Objects.requireNonNull(content, "Content must not be null.");
}
public static TextContent empty() {
return EMPTY;
}
public static TextContent of(String content) {
return ofObject(content);
}
public static TextContent ofList(List<String> content) {
return ofObjectList(content);
}
public static TextContent ofBoolean(Boolean content) {
return ofObject(content);
}
public static TextContent ofBooleanList(List<Boolean> content) {
return ofObjectList(content);
}
public static TextContent ofDouble(Double content) {
return ofObject(content);
}
public static TextContent ofDoubleList(List<Double> content) {
return ofObjectList(content);
}
public static TextContent ofInteger(Integer content) {
return ofObject(content);
}
public static TextContent ofIntegerList(List<Integer> content) {
return ofObjectList(content);
}
public static TextContent ofDuration(Duration content) {
return ofObject(content);
}
public static TextContent ofDurationList(List<Duration> content) {
return ofObjectList(content);
}
public static TextContent ofDateTime(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, DATE_TIME_FIELDS, withOffset);
}
public static TextContent ofDateTime(OffsetDateTime content) {
return ofOffsetDateTime(content, DATE_TIME_FIELDS, WITH_TIME_OFFSET);
}
public static TextContent ofDateTimeList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, DATE_TIME_FIELDS, withOffset);
}
public static TextContent ofDateTimeList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, DATE_TIME_FIELDS, WITH_TIME_OFFSET);
}
public static TextContent ofTime(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, TIME_FIELDS, withOffset);
}
public static TextContent ofTime(OffsetDateTime content) {
return ofOffsetDateTime(content, TIME_FIELDS, WITH_TIME_OFFSET);
}
public static TextContent ofTimeList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, TIME_FIELDS, withOffset);
}
public static TextContent ofTimeList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, TIME_FIELDS, WITH_TIME_OFFSET);
}
public static TextContent ofDate(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, DATE_FIELDS, withOffset);
}
public static TextContent ofDate(OffsetDateTime content) {
return ofOffsetDateTime(content, DATE_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofDateList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, DATE_FIELDS, withOffset);
}
public static TextContent ofDateList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, DATE_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGYearMonth(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, GYEAR_MONTH_FIELDS, withOffset);
}
public static TextContent ofGYearMonth(OffsetDateTime content) {
return ofOffsetDateTime(content, GYEAR_MONTH_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGYearMonthList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, GYEAR_MONTH_FIELDS, withOffset);
}
public static TextContent ofGYearMonthList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, GYEAR_MONTH_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGMonthDay(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, GMONTH_DAY_FIELDS, withOffset);
}
public static TextContent ofGMonthDay(OffsetDateTime content) {
return ofOffsetDateTime(content, GMONTH_DAY_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGMonthDayList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, GMONTH_DAY_FIELDS, withOffset);
}
public static TextContent ofGMonthDayList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, GMONTH_DAY_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGDay(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, GDAY_FIELDS, withOffset);
}
public static TextContent ofGDay(OffsetDateTime content) {
return ofOffsetDateTime(content, GDAY_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGDayList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, GDAY_FIELDS, withOffset);
}
public static TextContent ofGDayList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, GDAY_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGMonth(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, GMONTH_FIELDS, withOffset);
}
public static TextContent ofGMonth(OffsetDateTime content) {
return ofOffsetDateTime(content, GMONTH_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGMonthList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, GMONTH_FIELDS, withOffset);
}
public static TextContent ofGMonthList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, GMONTH_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGYear(OffsetDateTime content, boolean withOffset) {
return ofOffsetDateTime(content, GYEAR_FIELDS, withOffset);
}
public static TextContent ofGYear(OffsetDateTime content) {
return ofOffsetDateTime(content, GYEAR_FIELDS, WITH_DATE_OFFSET);
}
public static TextContent ofGYearList(List<OffsetDateTime> content, boolean withOffset) {
return ofOffsetDateTimeList(content, GYEAR_FIELDS, withOffset);
}
public static TextContent ofGYearList(List<OffsetDateTime> content) {
return ofOffsetDateTimeList(content, GYEAR_FIELDS, WITH_DATE_OFFSET);
}
public boolean isEmpty() {
return this == EMPTY;
}
public TextContent trim() {
content = trimmedContent();
return this;
}
public TextContent normalize() {
int length = content.length();
if (length != 0) {
StringBuilder normalized = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char ch = content.charAt(i);
normalized.append(isWhiteSpace(ch) ? ' ' : ch);
}
content = normalized.toString();
}
return this;
}
public TextContent collapse() {
int length = content.length();
if (length != 0) {
char ch = 0;
int i = 0;
for (; i < length; i++) {
ch = content.charAt(i);
if (!isWhiteSpace(ch))
break;
}
if (i != length) {
StringBuilder collapsed = new StringBuilder(length - i).append(ch);
boolean isWhiteSpace = false;
for (i += 1; i < length; i++) {
ch = content.charAt(i);
if (isWhiteSpace(ch)) {
isWhiteSpace = true;
} else {
if (isWhiteSpace) {
collapsed.append(' ');
isWhiteSpace = false;
}
collapsed.append(ch);
}
}
content = trimmedContent = collapsed.toString();
} else
content = trimmedContent = "";
}
return this;
}
public TextContent filter(Predicate<TextContent> predicate) {
return predicate.test(this) ? this : EMPTY;
}
public String get() {
return isPresent() ? content : null;
}
public boolean isPresent() {
return this != EMPTY;
}
public void ifPresent(Consumer<String> action) {
if (isPresent())
action.accept(content);
}
@SuppressWarnings("unchecked")
public List<String> getAsList() {
if (isListOfType(value, String.class)) {
return (List<String>) value;
} else if (tokenizeContent() != 0) {
List<String> strings = new ArrayList<>(tokenizedContent.length);
Collections.addAll(strings, tokenizedContent);
return setValue(strings);
} else {
return setValue(null);
}
}
public boolean isList() {
return getAsList() != null;
}
public void ifList(Consumer<List<String>> action) {
List<String> value = getAsList();
if (value != null) {
action.accept(value);
}
}
public Boolean getAsBoolean() {
return value instanceof Boolean bool ? bool : setValue(toBoolean(trimmedContent()));
}
public boolean isBoolean() {
return getAsBoolean() != null;
}
public void ifBoolean(Consumer<Boolean> action) {
Boolean value = getAsBoolean();
if (value != null) {
action.accept(value);
}
}
@SuppressWarnings("unchecked")
public List<Boolean> getAsBooleanList() {
if (isListOfType(value, Boolean.class)) {
return (List<Boolean>) value;
} else if (tokenizeContent() != 0) {
List<Boolean> booleans = new ArrayList<>(tokenizedContent.length);
for (String token : tokenizedContent) {
Boolean value = toBoolean(token);
if (value != null) {
booleans.add(value);
} else {
return setValue(null);
}
}
return setValue(booleans);
} else {
return setValue(null);
}
}
public boolean isBooleanList() {
return getAsBooleanList() != null;
}
public void ifBooleanList(Consumer<List<Boolean>> action) {
List<Boolean> value = getAsBooleanList();
if (value != null) {
action.accept(value);
}
}
public Double getAsDouble() {
if (value instanceof Double doubleValue) {
return doubleValue;
} else if (!isEmpty() && !trimmedContent().isEmpty()) {
try {
return setValue(Double.parseDouble(trimmedContent));
} catch (NumberFormatException e) {
return setValue(null);
}
} else {
return setValue(null);
}
}
public boolean isDouble() {
return getAsDouble() != null;
}
public void ifDouble(Consumer<Double> action) {
Double value = getAsDouble();
if (value != null) {
action.accept(value);
}
}
@SuppressWarnings("unchecked")
public List<Double> getAsDoubleList() {
if (isListOfType(value, Double.class)) {
return (List<Double>) value;
} else if (tokenizeContent() != 0) {
List<Double> doubles = new ArrayList<>(tokenizedContent.length);
for (String token : tokenizedContent) {
try {
doubles.add(Double.parseDouble(token));
} catch (NumberFormatException e) {
return setValue(null);
}
}
return setValue(doubles);
} else {
return setValue(null);
}
}
public boolean isDoubleList() {
return getAsDoubleList() != null;
}
public void ifDoubleList(Consumer<List<Double>> action) {
List<Double> value = getAsDoubleList();
if (value != null) {
action.accept(value);
}
}
public Integer getAsInteger() {
if (value instanceof Integer intValue) {
return intValue;
} else if (!isEmpty() && !trimmedContent().isEmpty()) {
try {
return setValue(Integer.parseInt(trimmedContent));
} catch (NumberFormatException e) {
return setValue(null);
}
} else {
return setValue(null);
}
}
public boolean isInteger() {
return getAsInteger() != null;
}
public void ifInteger(Consumer<Integer> action) {
Integer value = getAsInteger();
if (value != null) {
action.accept(value);
}
}
@SuppressWarnings("unchecked")
public List<Integer> getAsIntegerList() {
if (isListOfType(value, Integer.class)) {
return (List<Integer>) value;
} else if (tokenizeContent() != 0) {
List<Integer> integers = new ArrayList<>(tokenizedContent.length);
for (String token : tokenizedContent) {
try {
integers.add(Integer.parseInt(token));
} catch (NumberFormatException e) {
return setValue(null);
}
}
return setValue(integers);
} else {
return setValue(null);
}
}
public boolean isIntegerList() {
return getAsIntegerList() != null;
}
public void ifIntegerList(Consumer<List<Integer>> action) {
List<Integer> value = getAsIntegerList();
if (value != null) {
action.accept(value);
}
}
public Duration getAsDuration() {
if (value instanceof Duration duration) {
return duration;
} else if (!isEmpty() && !trimmedContent().isEmpty()) {
try {
return setValue(XML_TYPE_FACTORY.newDuration(trimmedContent));
} catch (Throwable e) {
return setValue(null);
}
} else {
return setValue(null);
}
}
public boolean isDuration() {
return getAsDuration() != null;
}
public void ifDuration(Consumer<Duration> action) {
Duration value = getAsDuration();
if (value != null) {
action.accept(value);
}
}
@SuppressWarnings("unchecked")
public List<Duration> getAsDurationList() {
if (isListOfType(value, Duration.class)) {
return (List<Duration>) value;
} else if (tokenizeContent() != 0) {
List<Duration> durations = new ArrayList<>(tokenizedContent.length);
for (String token : tokenizedContent) {
try {
durations.add(XML_TYPE_FACTORY.newDuration(token));
} catch (Throwable e) {
return setValue(null);
}
}
return setValue(durations);
} else {
return setValue(null);
}
}
public boolean isDurationList() {
return getAsDurationList() != null;
}
public void ifDurationList(Consumer<List<Duration>> action) {
List<Duration> value = getAsDurationList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsDateTime() {
return getAsOffsetDateTime("dateTime");
}
public boolean isDateTime() {
return getAsDateTime() != null;
}
public void ifDateTime(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsDateTime();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsDateTimeList() {
return getAsOffsetDateTimeList("dateTime");
}
public boolean isDateTimeList() {
return getAsDateTimeList() != null;
}
public void ifDateTimeList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsDateTimeList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsTime() {
return getAsOffsetDateTime("time");
}
public boolean isTime() {
return getAsTime() != null;
}
public void ifTime(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsTime();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsTimeList() {
return getAsOffsetDateTimeList("time");
}
public boolean isTimeList() {
return getAsTimeList() != null;
}
public void ifTimeList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsTimeList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsDate() {
return getAsOffsetDateTime("date");
}
public boolean isDate() {
return getAsDate() != null;
}
public void ifDate(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsDate();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsDateList() {
return getAsOffsetDateTimeList("date");
}
public boolean isDateList() {
return getAsDateList() != null;
}
public void ifDateList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsDateList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsGYearMonth() {
return getAsOffsetDateTime("gYearMonth");
}
public boolean isGYearMonth() {
return getAsGYearMonth() != null;
}
public void ifGYearMonth(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsGYearMonth();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsGYearMonthList() {
return getAsOffsetDateTimeList("gYearMonth");
}
public boolean isGYearMonthList() {
return getAsGYearMonthList() != null;
}
public void ifGYearMonthList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsGYearMonthList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsGMonthDay() {
return getAsOffsetDateTime("gMonthDay");
}
public boolean isGMonthDay() {
return getAsGMonthDay() != null;
}
public void ifGMonthDay(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsGMonthDay();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsGMonthDayList() {
return getAsOffsetDateTimeList("gMonthDay");
}
public boolean isGMonthDayList() {
return getAsGMonthDayList() != null;
}
public void ifGMonthDayList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsGMonthDayList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsGDay() {
return getAsOffsetDateTime("gDay");
}
public boolean isGDay() {
return getAsGDay() != null;
}
public void ifGDay(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsGDay();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsGDayList() {
return getAsOffsetDateTimeList("gDay");
}
public boolean isGDayList() {
return getAsGDayList() != null;
}
public void ifGDayList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsGDayList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsGMonth() {
return getAsOffsetDateTime("gMonth");
}
public boolean isGMonth() {
return getAsGMonth() != null;
}
public void ifGMonth(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsGMonth();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsGMonthList() {
return getAsOffsetDateTimeList("gMonth");
}
public boolean isGMonthList() {
return getAsGMonthList() != null;
}
public void ifGMonthList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsGMonthList();
if (value != null) {
action.accept(value);
}
}
public OffsetDateTime getAsGYear() {
return getAsOffsetDateTime("gYear");
}
public boolean isGYear() {
return getAsGYear() != null;
}
public void ifGYear(Consumer<OffsetDateTime> action) {
OffsetDateTime value = getAsGYear();
if (value != null) {
action.accept(value);
}
}
public List<OffsetDateTime> getAsGYearList() {
return getAsOffsetDateTimeList("gYear");
}
public boolean isGYearList() {
return getAsGYearList() != null;
}
public void ifGYearList(Consumer<List<OffsetDateTime>> action) {
List<OffsetDateTime> value = getAsGYearList();
if (value != null) {
action.accept(value);
}
}
public TextContent withZoneOffsetProvider(Function<LocalDateTime, ZoneOffset> zoneOffsetProvider) {
if (zoneOffsetProvider != null) {
this.zoneOffsetProvider = zoneOffsetProvider;
}
return this;
}
private OffsetDateTime getAsOffsetDateTime(String localName) {
if (value instanceof XMLGregorianCalendar calendar
&& calendar.getXMLSchemaType().getLocalPart().equals(localName)) {
return toOffsetDateTime((XMLGregorianCalendar) value);
} else if (!isEmpty() && !trimmedContent().isEmpty()) {
XMLGregorianCalendar calendar = setValue(toCalendar(trimmedContent(), localName));
return calendar != null ? toOffsetDateTime(calendar) : null;
} else {
return setValue(null);
}
}
@SuppressWarnings("unchecked")
private List<OffsetDateTime> getAsOffsetDateTimeList(String localName) {
List<XMLGregorianCalendar> calendars;
if (value instanceof List<?> list
&& list.stream().allMatch(v -> v instanceof XMLGregorianCalendar calendar
&& calendar.getXMLSchemaType().getLocalPart().equals(localName))) {
calendars = (List<XMLGregorianCalendar>) value;
} else if (tokenizeContent() != 0) {
calendars = new ArrayList<>(tokenizedContent.length);
for (String token : tokenizedContent) {
XMLGregorianCalendar value = toCalendar(token, localName);
if (value != null) {
calendars.add(value);
} else {
return setValue(null);
}
}
setValue(calendars);
} else {
return setValue(null);
}
List<OffsetDateTime> result = new ArrayList<>(calendars.size());
for (XMLGregorianCalendar calendar : calendars) {
result.add(toOffsetDateTime(calendar));
}
return result;
}
private <T> T setValue(T value) {
this.value = value;
return value;
}
private boolean isListOfType(Object value, Class<?> type) {
return value instanceof List<?> list && list.stream().allMatch(type::isInstance);
}
private Boolean toBoolean(String value) {
if (value.isEmpty()) {
return null;
} else if ("true".equals(value)
|| "1".equals(value)) {
return Boolean.TRUE;
} else if ("false".equals(value)
|| "0".equals(value)) {
return Boolean.FALSE;
} else {
return null;
}
}
private XMLGregorianCalendar toCalendar(String value, String localName) {
try {
XMLGregorianCalendar calendar = XML_TYPE_FACTORY.newXMLGregorianCalendar(value);
if (calendar.getXMLSchemaType().getLocalPart().equals(localName)) {
return calendar;
}
} catch (Throwable e) {
//
}
return null;
}
private OffsetDateTime toOffsetDateTime(XMLGregorianCalendar calendar) {
int day = calendar.getDay();
int month = calendar.getMonth();
int year = calendar.getYear();
int hour = calendar.getHour();
int minute = calendar.getMinute();
int second = calendar.getSecond();
int offset = calendar.getTimezone();
BigDecimal fractional = calendar.getFractionalSecond();
int nano = fractional != null ? (int) (fractional.doubleValue() * 1e+9) : DatatypeConstants.FIELD_UNDEFINED;
LocalDateTime dateTime = LocalDateTime.of(
year != DatatypeConstants.FIELD_UNDEFINED ? year : 0,
month != DatatypeConstants.FIELD_UNDEFINED ? month : 1,
day != DatatypeConstants.FIELD_UNDEFINED ? day : 1,
hour != DatatypeConstants.FIELD_UNDEFINED ? hour : 0,
minute != DatatypeConstants.FIELD_UNDEFINED ? minute : 0,
second != DatatypeConstants.FIELD_UNDEFINED ? second : 0,
nano != DatatypeConstants.FIELD_UNDEFINED ? nano : 0);
return OffsetDateTime.of(dateTime, offset != DatatypeConstants.FIELD_UNDEFINED ?
ZoneOffset.ofTotalSeconds(offset * 60) :
zoneOffsetProvider.apply(dateTime));
}
private static TextContent ofObject(Object content) {
return content != null ? new TextContent(content.toString()) : EMPTY;
}
private static TextContent ofObjectList(List<?> content) {
if (content != null && !content.isEmpty()) {
StringBuilder builder = new StringBuilder(content.size());
boolean first = true;
for (Object object : content) {
if (object != null) {
if (!first) {
builder.append(" ");
} else {
first = false;
}
builder.append(object);
}
}
return new TextContent(builder.toString());
} else {
return EMPTY;
}
}
private static TextContent ofOffsetDateTime(OffsetDateTime content, EnumSet<Fields> fields, boolean withOffset) {
XMLGregorianCalendar calendar = toCalendar(content, fields, withOffset);
return calendar != null ? new TextContent(calendar.toXMLFormat()) : EMPTY;
}
private static TextContent ofOffsetDateTimeList(List<OffsetDateTime> content, EnumSet<Fields> fields, boolean withOffset) {
if (content != null && !content.isEmpty()) {
StringBuilder builder = new StringBuilder(content.size());
boolean first = true;
for (OffsetDateTime dateTime : content) {
XMLGregorianCalendar calendar = toCalendar(dateTime, fields, withOffset);
if (calendar != null) {
if (!first) {
builder.append(" ");
} else {
first = false;
}
builder.append(calendar.toXMLFormat());
}
}
return new TextContent(builder.toString());
} else {
return EMPTY;
}
}
private static XMLGregorianCalendar toCalendar(OffsetDateTime dateTime, EnumSet<Fields> fields, boolean withOffset) {
XMLGregorianCalendar calendar = null;
if (dateTime != null) {
calendar = XML_TYPE_FACTORY.newXMLGregorianCalendar(
fields.contains(Fields.YEAR) ? dateTime.getYear() : DatatypeConstants.FIELD_UNDEFINED,
fields.contains(Fields.MONTH) ? dateTime.getMonthValue() : DatatypeConstants.FIELD_UNDEFINED,
fields.contains(Fields.DAY) ? dateTime.getDayOfMonth() : DatatypeConstants.FIELD_UNDEFINED,
fields.contains(Fields.HOUR) ? dateTime.getHour() : DatatypeConstants.FIELD_UNDEFINED,
fields.contains(Fields.MINUTE) ? dateTime.getMinute() : DatatypeConstants.FIELD_UNDEFINED,
fields.contains(Fields.SECOND) ? dateTime.getSecond() : DatatypeConstants.FIELD_UNDEFINED,
DatatypeConstants.FIELD_UNDEFINED,
withOffset && fields.contains(Fields.TIMEZONE) ?
dateTime.getOffset().getTotalSeconds() / 60 :
DatatypeConstants.FIELD_UNDEFINED);
if (fields.contains(Fields.NANO) && dateTime.getNano() != 0) {
calendar.setFractionalSecond(BigDecimal.valueOf(dateTime.getNano(), 9).stripTrailingZeros());
}
}
return calendar;
}
public static void setZoneOffsetProvider(Function<LocalDateTime, ZoneOffset> zoneOffsetProvider) {
if (zoneOffsetProvider != null) {
ZONE_OFFSET_PROVIDER = zoneOffsetProvider;
}
}
public static void serializeTimeWithOffset(boolean useTimeOffset) {
WITH_TIME_OFFSET = useTimeOffset;
}
public static void serializeDateWithOffset(boolean useDateOffset) {
WITH_DATE_OFFSET = useDateOffset;
}
private String trimmedContent() {
if (trimmedContent == null) {
trimmedContent = content.trim();
}
return trimmedContent;
}
private int tokenizeContent() {
if (tokenizedContent == null) {
int length = content.length();
String[] tokens = new String[(length / 2) + 1];
int noOfTokens = 0;
int current = -1;
int next;
do {
next = nextWhiteSpace(content, current + 1, length);
if (next != current + 1) {
tokens[noOfTokens++] = content.substring(current + 1, next);
}
current = next;
} while (next != length);
tokenizedContent = new String[noOfTokens];
System.arraycopy(tokens, 0, tokenizedContent, 0, noOfTokens);
}
return tokenizedContent.length;
}
private int nextWhiteSpace(String value, int pos, int length) {
for (int i = pos; i < length; i++) {
if (isWhiteSpace(value.charAt(i))) {
return i;
}
}
return length;
}
private boolean isWhiteSpace(char ch) {
return ch == ' ' || ch == '\n' || Character.isWhitespace(ch);
}
@Override
public String toString() {
return content;
}
}
......@@ -30,7 +30,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearVisitorResultsVisitor;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearResultsVisitor;
import de.hft.stuttgart.citydoctor2.utils.visitors.GmlGeometryRebuilder;
import de.hft.stuttgart.citydoctor2.utils.visitors.UnsetGeometriesVisitor;
import org.citygml4j.core.model.construction.AbstractConstructionSurface;
......@@ -141,7 +141,7 @@ public class BoundarySurfaceTest {
assertFalse(bs.getAllCheckResults().isEmpty());
bs.addOpening(oMock);
bs.clearAllContainedCheckResults();
verify(oMock).accept(any(ClearVisitorResultsVisitor.class));
verify(oMock).accept(any(ClearResultsVisitor.class));
assertTrue(bs.getAllCheckResults().isEmpty());
}
......
package de.hft.stuttgart.citydoctor2.datastructure;
import static org.junit.jupiter.api.Assertions.*;
import org.citygml4j.core.model.construction.WallSurface;
import org.citygml4j.core.util.geometry.GeometryFactory;
import org.junit.jupiter.api.Test;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
class BridgeConstructiveElementTest {
@Test
void testBoundarySurfaceGeometryRecreation() {
WallSurface wallSurface = new WallSurface();
BoundarySurface surface = new BoundarySurface(wallSurface);
surface.addGeometry(GeometryTestUtils.createDummyGeometry(GeometryType.MULTI_SURFACE, Lod.LOD2));
var gmlBce = new org.citygml4j.core.model.bridge.BridgeConstructiveElement();
BridgeConstructiveElement bce = new BridgeConstructiveElement(gmlBce);
bce.addBoundarySurface(surface);
assertNull(wallSurface.getLod2MultiSurface());
GeometryFactory factory = GeometryFactory.newInstance();
ParserConfiguration config = new ParserConfiguration(8, false);
bce.reCreateGeometries(factory, config);
assertNotNull(wallSurface.getLod2MultiSurface());
}
}
......@@ -33,7 +33,7 @@ import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.CheckableUtilsVisitor;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearVisitorResultsVisitor;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearResultsVisitor;
import org.citygml4j.core.model.construction.AbstractConstructionSurface;
import org.citygml4j.core.model.construction.WallSurface;
import org.citygml4j.core.util.geometry.GeometryFactory;
......@@ -301,7 +301,7 @@ public class GeometryTest {
Polygon p = mock(Polygon.class);
geom.addPolygon(p);
geom.clearAllContainedCheckResults();
verify(p).accept(any(ClearVisitorResultsVisitor.class));
verify(p).accept(any(ClearResultsVisitor.class));
assertFalse(geom.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
}
......
......@@ -6,7 +6,7 @@ import de.hft.stuttgart.citydoctor2.check.CheckId;
import de.hft.stuttgart.citydoctor2.check.CheckResult;
import de.hft.stuttgart.citydoctor2.check.ResultStatus;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearVisitorResultsVisitor;
import de.hft.stuttgart.citydoctor2.utils.visitors.ClearResultsVisitor;
import org.citygml4j.core.model.core.AbstractSpaceBoundary;
import org.citygml4j.core.model.core.AbstractUnoccupiedSpace;
import org.citygml4j.core.model.deprecated.core.DeprecatedPropertiesOfAbstractCityObject;
......@@ -91,7 +91,7 @@ public class TrafficSpaceTest {
tso.clearAllContainedCheckResults();
assertFalse(tso.containsError(CheckId.C_GE_P_HOLE_OUTSIDE));
verify(taMock).accept(any(ClearVisitorResultsVisitor.class));
verify(taMock).accept(any(ClearResultsVisitor.class));
}
@Test
......
......@@ -37,7 +37,7 @@ public class CityGml3ParserTest {
@Test
public void testGetContext() {
CityGMLContext context = CityGmlParser.getContext();
CityGMLContext context = CityGmlParser.setupContext();
List<ADE> ades = ADERegistry.getInstance().getADEs();
ADE ade = ades.get(0);
assertEquals(QualityADEContext.class, ade.getClass());
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.18.0</version>
<version>3.18.1</version>
</parent>
<artifactId>CityDoctorValidation</artifactId>
<name>CityDoctorValidation</name>
......
......@@ -133,7 +133,7 @@ public class CityDoctorValidation {
config = ValidationConfiguration.loadStandardValidationConfig();
config.setUseStreaming(true);
} else {
config = ValidationConfiguration.loadValidationConfig(validationConfigFile.getAbsolutePath());
config = ValidationConfiguration.loadValidationConfigFile(validationConfigFile.getAbsolutePath());
}
String xmlOutputPath = null;
if (xmlOutput != null) {
......@@ -234,7 +234,7 @@ public class CityDoctorValidation {
logger.error(Localization.getText("CityDoctorValidation.notExactlyOneConfigFile"));
System.exit(4);
}
return ValidationConfiguration.loadValidationConfig(configFiles.get(0));
return ValidationConfiguration.loadValidationConfigFile(configFiles.get(0));
} else {
if (optional) {
logger.warn(Localization.getText("CityDoctorValidation.loadingDefaultConfig"));
......
......@@ -47,7 +47,7 @@ public class CityDoctorValidationCLI implements Runnable {
if(config == null){
valConfig=ValidationConfiguration.loadStandardValidationConfig();
} else{
valConfig=ValidationConfiguration.loadValidationConfig(config.getAbsolutePath());
valConfig=ValidationConfiguration.loadValidationConfigFile(config.getAbsolutePath());
}
CityDoctorValidation.startValidationProcess(input, xmlReport, pdfReport, valConfig,output);
} catch (CityDoctorWriteException | CityGmlParseException | IOException | InvalidGmlFileException e) {
......
......@@ -18,10 +18,54 @@
*/
package de.hft.stuttgart.citydoctor2.check;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.XMLConstants;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.XMLValidationError;
import de.hft.stuttgart.citydoctor2.checkresult.utility.CheckReportWriteException;
import de.hft.stuttgart.citydoctor2.checks.CheckContainer;
import de.hft.stuttgart.citydoctor2.checks.CheckPrototype;
......@@ -29,13 +73,11 @@ import de.hft.stuttgart.citydoctor2.checks.Checks;
import de.hft.stuttgart.citydoctor2.checks.SvrlContentHandler;
import de.hft.stuttgart.citydoctor2.checks.util.FeatureCheckedListener;
import de.hft.stuttgart.citydoctor2.database.CityObjectCache;
import de.hft.stuttgart.citydoctor2.database.CityObjectCache;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.datastructure.ImplicitGeometryHolder;
import de.hft.stuttgart.citydoctor2.datastructure.GmlId;
import de.hft.stuttgart.citydoctor2.parser.CityGmlConsumer;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import de.hft.stuttgart.citydoctor2.parser.CityGmlParser;
......@@ -59,40 +101,6 @@ import de.hft.stuttgart.quality.model.properties.RequirementProperty;
import de.hft.stuttgart.quality.model.types.Checking;
import de.hft.stuttgart.quality.model.types.Parameter;
import de.hft.stuttgart.quality.model.types.ValidationPlan;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.xml.XMLConstants;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* The main container class for checking. It contains the logic for validation,
......@@ -253,7 +261,7 @@ public class Checker {
}
handler.getFeatureErrors().forEach((k, v) -> {
String trimmedId = k.trim();
CityObject co = cache.get(new GmlId(k));
CityObject co = cache.get(new GmlId(trimmedId));
if (co == null) {
// gml id reported by schematron was not found, add to general errors
handleSchematronErrorsGlobal(v);
......@@ -692,7 +700,8 @@ public class Checker {
AtomicInteger checkedCount = new AtomicInteger(0);
// clear global errors
model.getGlobalErrors().clear();
model.getGlobalErrors().removeIf(e -> !e.isParsingError());
CityObjectCache cache = model.getCache();
logger.trace("Setting up ThreadPool");
int threadCount = Runtime.getRuntime().availableProcessors() * 5;
......@@ -911,6 +920,20 @@ public class Checker {
// create reporter if available
XmlStreamReporter xmlReporter = getXmlReporter(config, xmlBos, fileName);
PdfStreamReporter pdfReporter = getPdfReporter(config, pdfBos, fileName);
// XML validation
if (config.isXmlValidation() && (xmlReporter != null || pdfReporter != null)) {
List<String> validationIssues = CityGmlParser.validateFile(null, inputFile.toPath());
for (String xmlError : validationIssues) {
XMLValidationError validationError = new XMLValidationError(xmlError);
if (xmlReporter != null) {
xmlReporter.reportGlobalError(validationError);
}
if (pdfReporter != null) {
pdfReporter.reportGlobalError(validationError);
}
}
}
// execute schematron first
SvrlContentHandler handler = executeSchematronValidationIfAvailable(config, inputFile);
......
......@@ -53,7 +53,6 @@ public class ValidationConfiguration implements Serializable {
private static final long serialVersionUID = -8020055032177740646L;
private static final Logger logger = LogManager.getLogger(ValidationConfiguration.class);
private Map<String, String> globalParameters = new HashMap<>();
private boolean xmlValidation = false;
private boolean useStreaming = false;
......@@ -62,9 +61,16 @@ public class ValidationConfiguration implements Serializable {
private ParserConfiguration parserConfig;
public static ValidationConfiguration loadValidationConfig(String validationFile) throws FileNotFoundException {
public static ValidationConfiguration loadValidationConfigFile(String validationFile) throws FileNotFoundException {
return loadValidationConfig(new FileInputStream(validationFile));
}
public static ValidationConfiguration loadValidationConfigFromString(String validationString) throws FileNotFoundException {
Yaml yaml = new Yaml(new Constructor(ValidationConfiguration.class, new LoaderOptions()));
ValidationConfiguration config = yaml.load(validationString);
config.validateConfiguration();
return config;
}
public static ValidationConfiguration loadValidationConfig(InputStream stream) {
Yaml yaml = new Yaml(new Constructor(ValidationConfiguration.class, new LoaderOptions()));
......@@ -91,20 +97,30 @@ public class ValidationConfiguration implements Serializable {
config.setSchematronFilePathInGlobalParameters(CHECK_FOR_SOLID_XML);
return config;
}
private ValidationConfiguration() {
}
public void saveAs(File f) throws IOException {
Yaml yaml = prepareDumpingOfConfig();
try (BufferedWriter bw = new BufferedWriter(new FileWriter(f))) {
yaml.dump(this, bw);
}
}
public String saveAsString() throws IOException {
Yaml yaml = prepareDumpingOfConfig();
return yaml.dump(this);
}
private Yaml prepareDumpingOfConfig() {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(true);
Representer rep = new ValidationConfigurationRepresenter(options);
rep.addClassTag(ValidationConfiguration.class, Tag.MAP);
Yaml yaml = new Yaml(rep);
try (BufferedWriter bw = new BufferedWriter(new FileWriter(f))) {
yaml.dump(this, bw);
}
return yaml;
}
public boolean isXmlValidation() {
......@@ -141,7 +157,7 @@ public class ValidationConfiguration implements Serializable {
public Map<String, String> getGlobalParameters() {
return globalParameters;
}
public void setGlobalParameters(Map<String, String> globalParameters) {
this.globalParameters = globalParameters;
}
......@@ -174,8 +190,7 @@ public class ValidationConfiguration implements Serializable {
});
}
globalParameters.putIfAbsent(GlobalParameters.MIN_VERTEX_DISTANCE, MIN_VERTEX_DISTANCE_DEFAULT);
globalParameters.putIfAbsent(GlobalParameters.NUMBER_OF_ROUNDING_PLACES,
NUMBER_OF_ROUNDING_PLACES_DEFAULT);
globalParameters.putIfAbsent(GlobalParameters.NUMBER_OF_ROUNDING_PLACES, NUMBER_OF_ROUNDING_PLACES_DEFAULT);
}
public int getNumberOfRoundingPlaces() {
......@@ -220,7 +235,7 @@ public class ValidationConfiguration implements Serializable {
public void setSchematronFilePathInGlobalParameters(String string) {
globalParameters.put(GlobalParameters.SCHEMATRON_PATH, string);
}
public void setRequirements(Map<String, RequirementConfiguration> requirements) {
this.requirements = requirements;
}
......
......@@ -18,6 +18,22 @@
*/
package de.hft.stuttgart.citydoctor2.check;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import de.hft.stuttgart.citydoctor2.CityDoctorValidation;
import de.hft.stuttgart.citydoctor2.checkresult.CheckReport;
import de.hft.stuttgart.citydoctor2.checkresult.GlobalErrorStatistics;
......@@ -31,160 +47,165 @@ 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.parser.ParserConfiguration;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Matthias Betz
*/
public class CheckerTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testSchematron() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.getRequirements().get(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.toString()).setEnabled(false);
config.setSchematronFilePathInGlobalParameters("src/test/resources/schematronTest.xml");
CityDoctorModel model = CityGmlParser.parseCityGmlFile(
"src/test/resources/SimpleSolid_SrefBS_SchematronTest.gml", config.getParserConfiguration());
Checker checker = new Checker(config, model);
checker.runChecks();
for (Building b : model.getBuildings().toList()) {
if (b.getGmlId().getGmlString().equals("_Simple_BD.1")) {
assertTrue(b.containsAnyError());
} else {
assertFalse(b.containsAnyError());
}
}
assertFalse(model.getGlobalErrors().isEmpty());
}
@Test
public void testChecker() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
File f = folder.newFile();
File f2 = folder.newFile();
try {
String[] args = new String[6];
args[0] = "-in";
args[1] = "src/test/resources/QA-CS-CONCOMP.gml";
args[2] = "-xmlReport";
args[3] = f.getAbsolutePath();
args[4] = "-pdfReport";
args[5] = f2.getAbsolutePath();
CityDoctorValidation.main(args);
assertTrue(f.exists());
assertTrue(f2.exists());
} finally {
f.delete();
f2.delete();
}
}
@Test
public void testStreaming() throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
File f = folder.newFile();
File f2 = folder.newFile();
File f3 = folder.newFile();
try {
String[] args = new String[10];
args[0] = "-in";
args[1] = "src/test/resources/testarea.gml";
args[2] = "-config";
args[3] = "src/test/resources/testConfigWithStreaming.yml";
args[4] = "-pdfReport";
args[5] = f.getAbsolutePath();
args[6] = "-xmlReport";
args[7] = f2.getAbsolutePath();
args[8] = "-out";
args[9] = f3.getAbsolutePath();
CityDoctorValidation.main(args);
assertTrue(f.exists());
assertTrue(f2.exists());
assertTrue(f3.exists());
} finally {
f.delete();
f2.delete();
f3.delete();
}
}
@Test
public void testReportCreation() throws IOException, CityGmlParseException, InvalidGmlFileException {
Path tmpDir = null;
try {
tmpDir = Files.createTempDirectory("testTmp");
tmpDir.toFile().deleteOnExit();
Path xmlPath = tmpDir.resolve("report.xml");
Path pdfPath = tmpDir.resolve("report.pdf");
File features = new File("src/test/resources/feature_types.gml");
CityDoctorModel model = CityGmlParser.nestedCityGmlFileParse(
features.toString(), new ParserConfiguration(8, false));
assertNotNull(model);
Checker checker = new Checker(model);
checker.runChecks();
checker.writeXmlReport(xmlPath.toString());
checker.writePdfReport(pdfPath.toString());
assertTrue(Files.exists(xmlPath));
assertTrue(Files.exists(pdfPath));
try {
CheckReport report = CheckReport.load(xmlPath.toString());
assertNotNull(report);
GlobalStatistics globalStatistics = report.getGlobalStatistics();
assertNotNull(globalStatistics);
ModelStatistics modelStats = globalStatistics.getModelStats();
assertNotNull(modelStats);
assertEquals(1, modelStats.getNumBuildings());
assertEquals(1, modelStats.getNumVegetation());
assertEquals(1, modelStats.getNumTransportation());
assertEquals(1, modelStats.getNumTunnelObjects());
assertEquals(1, modelStats.getNumBridgeObjects());
assertEquals(1, modelStats.getNumWaterObjects());
assertEquals(1, modelStats.getNumLandObjects());
assertEquals(1, modelStats.getNumCityFurniture());
assertEquals(1, modelStats.getNumGenericCityObjects());
GlobalErrorStatistics globError = globalStatistics.getGlobalErrorStats();
assertNotNull(globError);
assertEquals(0, globError.getNumErrorBuildings());
assertEquals(0, globError.getNumErrorVegetation());
assertEquals(0, globError.getNumErrorTransportation());
assertEquals(0, globError.getNumErrorTunnelObjects());
assertEquals(0, globError.getNumErrorBridgeObjects());
assertEquals(0, globError.getNumErrorWaterObjects());
assertEquals(0, globError.getNumErrorLandObjects());
assertEquals(1, globError.getNumErrorCityFurniture());
assertEquals(1, globError.getNumErrorGenericCityObjects());
} catch (CheckReportParseException e) {
fail("Report should be valid file");
}
} finally {
if (tmpDir != null) {
FileUtils.deleteDirectory(tmpDir.toFile());
}
}
}
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testSchematron() throws CityGmlParseException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.getRequirements().get(Requirement.R_SE_BS_ROOF_UNFRAGMENTED.toString()).setEnabled(false);
config.setSchematronFilePathInGlobalParameters("src/test/resources/schematronTest.xml");
CityDoctorModel model = CityGmlParser.parseCityGmlFile(
"src/test/resources/SimpleSolid_SrefBS_SchematronTest.gml", config.getParserConfiguration());
Checker checker = new Checker(config, model);
checker.runChecks();
for (Building b : model.getBuildings().toList()) {
if (b.getGmlId().getGmlString().equals("_Simple_BD.1")) {
assertTrue(b.containsAnyError());
} else {
assertFalse(b.containsAnyError());
}
}
assertFalse(model.getGlobalErrors().isEmpty());
}
@Test
public void testChecker()
throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
File f = folder.newFile();
File f2 = folder.newFile();
try {
String[] args = new String[6];
args[0] = "-in";
args[1] = "src/test/resources/QA-CS-CONCOMP.gml";
args[2] = "-xmlReport";
args[3] = f.getAbsolutePath();
args[4] = "-pdfReport";
args[5] = f2.getAbsolutePath();
CityDoctorValidation.main(args);
assertTrue(f.exists());
assertTrue(f2.exists());
} finally {
f.delete();
f2.delete();
}
}
@Test
public void testStreaming()
throws CityGmlParseException, IOException, InvalidGmlFileException, CityDoctorWriteException {
File f = folder.newFile();
File f2 = folder.newFile();
File f3 = folder.newFile();
try {
String[] args = new String[10];
args[0] = "-in";
args[1] = "src/test/resources/testarea.gml";
args[2] = "-config";
args[3] = "src/test/resources/testConfigWithStreaming.yml";
args[4] = "-pdfReport";
args[5] = f.getAbsolutePath();
args[6] = "-xmlReport";
args[7] = f2.getAbsolutePath();
args[8] = "-out";
args[9] = f3.getAbsolutePath();
CityDoctorValidation.main(args);
assertTrue(f.exists());
assertTrue(f2.exists());
assertTrue(f3.exists());
} finally {
f.delete();
f2.delete();
f3.delete();
}
}
@Test
public void testStreamingWithXMLValidation() throws CityGmlParseException, IOException, InvalidGmlFileException,
CityDoctorWriteException, CheckReportParseException {
File f2 = folder.newFile();
try {
String[] args = new String[6];
args[0] = "-in";
args[1] = "src/test/resources/SimpleSolid_SrefBS_XMLInvalid.gml";
args[2] = "-config";
args[3] = "src/test/resources/testConfigWithStreamingWithValidation.yml";
args[4] = "-xmlReport";
args[5] = f2.getAbsolutePath();
CityDoctorValidation.main(args);
assertTrue(f2.exists());
CheckReport checkReport = CheckReport.load(f2.toPath());
assertEquals(1, checkReport.getValidationResults().getGlobalErrors().size());
} finally {
f2.delete();
}
}
@Test
public void testReportCreation() throws IOException, CityGmlParseException, InvalidGmlFileException {
Path tmpDir = null;
try {
tmpDir = Files.createTempDirectory("testTmp");
tmpDir.toFile().deleteOnExit();
Path xmlPath = tmpDir.resolve("report.xml");
Path pdfPath = tmpDir.resolve("report.pdf");
File features = new File("src/test/resources/feature_types.gml");
CityDoctorModel model = CityGmlParser.nestedCityGmlFileParse(features.toString(),
new ParserConfiguration(8, false));
assertNotNull(model);
Checker checker = new Checker(model);
checker.runChecks();
checker.writeXmlReport(xmlPath.toString());
checker.writePdfReport(pdfPath.toString());
assertTrue(Files.exists(xmlPath));
assertTrue(Files.exists(pdfPath));
try {
CheckReport report = CheckReport.load(xmlPath.toString());
assertNotNull(report);
GlobalStatistics globalStatistics = report.getGlobalStatistics();
assertNotNull(globalStatistics);
ModelStatistics modelStats = globalStatistics.getModelStats();
assertNotNull(modelStats);
assertEquals(1, modelStats.getNumBuildings());
assertEquals(1, modelStats.getNumVegetation());
assertEquals(1, modelStats.getNumTransportation());
assertEquals(1, modelStats.getNumTunnelObjects());
assertEquals(1, modelStats.getNumBridgeObjects());
assertEquals(1, modelStats.getNumWaterObjects());
assertEquals(1, modelStats.getNumLandObjects());
assertEquals(1, modelStats.getNumCityFurniture());
assertEquals(1, modelStats.getNumGenericCityObjects());
GlobalErrorStatistics globError = globalStatistics.getGlobalErrorStats();
assertNotNull(globError);
assertEquals(0, globError.getNumErrorBuildings());
assertEquals(0, globError.getNumErrorVegetation());
assertEquals(0, globError.getNumErrorTransportation());
assertEquals(0, globError.getNumErrorTunnelObjects());
assertEquals(0, globError.getNumErrorBridgeObjects());
assertEquals(0, globError.getNumErrorWaterObjects());
assertEquals(0, globError.getNumErrorLandObjects());
assertEquals(1, globError.getNumErrorCityFurniture());
assertEquals(1, globError.getNumErrorGenericCityObjects());
} catch (CheckReportParseException e) {
fail("Report should be valid file");
}
} finally {
if (tmpDir != null) {
FileUtils.deleteDirectory(tmpDir.toFile());
}
}
}
}
......@@ -39,7 +39,7 @@ public class FilterTest {
@Test
public void testFilterExclude() throws CityGmlParseException, IOException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration
.loadValidationConfig("src/test/resources/testConfigWithExclude.yml");
.loadValidationConfigFile("src/test/resources/testConfigWithExclude.yml");
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/testarea.gml",
new ParserConfiguration(8, false));
Checker c = new Checker(config, model);
......@@ -59,7 +59,7 @@ public class FilterTest {
@Test
public void testFilterInclude() throws CityGmlParseException, IOException, InvalidGmlFileException {
ValidationConfiguration config = ValidationConfiguration
.loadValidationConfig("src/test/resources/testConfigWithInclude.yml");
.loadValidationConfigFile("src/test/resources/testConfigWithInclude.yml");
CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/testarea.gml",
new ParserConfiguration(8, false));
Checker c = new Checker(config, model);
......
......@@ -37,7 +37,7 @@ public class ValidationConfigurationTest {
@Test
public void testLoadingConfig() throws FileNotFoundException {
String file = "src/test/resources/testConfig.yml";
ValidationConfiguration config = ValidationConfiguration.loadValidationConfig(file);
ValidationConfiguration config = ValidationConfiguration.loadValidationConfigFile(file);
assertEquals(8, config.getNumberOfRoundingPlaces());
assertTrue(config.getRequirements().containsKey(RequirementId.R_GE_R_TOO_FEW_POINTS.toString()));
assertFalse(config.getRequirements().get(RequirementId.R_GE_P_NON_PLANAR.toString()).isEnabled());
......@@ -47,7 +47,7 @@ public class ValidationConfigurationTest {
@Test
public void testLoadingConfigWithFilter() throws FileNotFoundException {
String file = "src/test/resources/testConfigWithFilter.yml";
ValidationConfiguration config = ValidationConfiguration.loadValidationConfig(file);
ValidationConfiguration config = ValidationConfiguration.loadValidationConfigFile(file);
assertEquals(8, config.getNumberOfRoundingPlaces());
assertTrue(config.getRequirements().containsKey(RequirementId.R_GE_R_TOO_FEW_POINTS.toString()));
assertFalse(config.getRequirements().get(RequirementId.R_GE_P_NON_PLANAR.toString()).isEnabled());
......@@ -76,7 +76,7 @@ public class ValidationConfigurationTest {
String file = "src/test/resources/testConfigVulnerability.yml";
ValidationConfiguration config = null;
try {
config = ValidationConfiguration.loadValidationConfig(file);
config = ValidationConfiguration.loadValidationConfigFile(file);
assertNotNull(config);
fail("Config with Vulnerability should not be successfully loaded");
} catch (FileNotFoundException e){
......
<?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.
Fehler in der Reihenfolge der Attribute.
CityGML 2.0
Gebäudevolumen: 56,25 m3
12.12.2025
Author: V. Coors, HFT Stuttgart
Lizenz:
-->
<core:cityObjectMember>
<bldg:Building gml:id="_Simple_BD.1">
<gen:stringAttribute name="averageStoreyHeight">
<gen:value>2.5</gen:value>
</gen:stringAttribute>
<gml:name>falsche Reihenfolge</gml:name>
<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
globalParameters:
numberOfRoundingPlaces: 8
schematronFilePath: src/test/resources/schematronTest.xml
useStreaming: true
xmlValidation: true
requirements:
R_GE_R_TOO_FEW_POINTS:
enabled: true
R_GE_R_NOT_CLOSED:
enabled: true
R_GE_R_CONSECUTIVE_POINTS_SAME:
enabled: true
R_GE_R_SELF_INTERSECTION:
enabled: true
R_GE_S_MULTIPLE_CONNECTED_COMPONENTS:
enabled: true
R_GE_P_INTERIOR_DISCONNECTED:
enabled: true
R_GE_P_INTERSECTING_RINGS:
enabled: true
R_GE_P_NON_PLANAR:
enabled: false
parameters:
# one of ("distance", "angle", "both")
type: distance
distanceTolerance: 0.01
angleTolerance: 0.1
R_GE_P_HOLE_OUTSIDE:
enabled: true
R_GE_P_ORIENTATION_RINGS_SAME:
enabled: true
R_GE_P_INNER_RINGS_NESTED:
enabled: true
R_GE_S_TOO_FEW_POLYGONS:
enabled: true
R_GE_S_NOT_CLOSED:
enabled: true
R_GE_S_NON_MANIFOLD_EDGE:
enabled: true
R_GE_S_POLYGON_WRONG_ORIENTATION:
enabled: true
R_GE_S_ALL_POLYGONS_WRONG_ORIENTATION:
enabled: true
R_GE_S_NON_MANIFOLD_VERTEX:
enabled: true
R_GE_S_SELF_INTERSECTION:
enabled: true
\ No newline at end of file
......@@ -6,7 +6,7 @@
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.18.0</version>
<version>3.18.1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>CityDoctorAutoPro</artifactId>
......
......@@ -362,7 +362,7 @@ public class AutoProWindow extends JDialog implements ItemListener {
*/
private void startCppAutoProMethods() throws FileNotFoundException {
List<Building> buildings = this.model.getBuildings();
List<Building> buildings = this.model.getBuildings().toList();
List<Geometry> geometryList = getAllGeometriesOfSelectedBuildings(buildings);
setBuildingsToOrigin(geometryList);
......@@ -525,12 +525,12 @@ public class AutoProWindow extends JDialog implements ItemListener {
Building building = part.getParent();
building.getBuildingParts().remove(part);
if (building.getBuildingParts().isEmpty() && building.getGeometries().isEmpty()) {
model.getBuildings().remove(building);
model.getBuildings().toList().remove(building);
}
} else if (parent instanceof Building && parent.getGeometries().isEmpty()) {
Building building = (Building) parent;
if (building.getBuildingParts().isEmpty()) {
model.getBuildings().remove(building);
model.getBuildings().toList().remove(building);
}
}
}
......
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