Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
1fbe16e1
Commit
1fbe16e1
authored
Dec 12, 2025
by
Matthias Betz
Browse files
add xml validation to streaming processing
parent
82888d4b
Pipeline
#12286
passed with stage
in 2 minutes and 15 seconds
Changes
10
Pipelines
1
Show whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorCheckResult/src/main/java/de/hft/stuttgart/citydoctor2/checkresult/CheckReport.java
View file @
1fbe16e1
...
@@ -22,6 +22,7 @@ import java.io.BufferedReader;
...
@@ -22,6 +22,7 @@ import java.io.BufferedReader;
import
java.io.FileReader
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
java.nio.file.Path
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -65,7 +66,11 @@ public class CheckReport {
...
@@ -65,7 +66,11 @@ public class CheckReport {
private
Map
<
String
,
FeatureReport
>
featureReports
;
private
Map
<
String
,
FeatureReport
>
featureReports
;
public
static
CheckReport
load
(
String
file
)
throws
CheckReportParseException
{
public
static
CheckReport
load
(
String
file
)
throws
CheckReportParseException
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
file
)))
{
return
load
(
Path
.
of
(
file
));
}
public
static
CheckReport
load
(
Path
path
)
throws
CheckReportParseException
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
path
.
toFile
())))
{
CheckReport
report
=
(
CheckReport
)
getContext
().
createUnmarshaller
().
unmarshal
(
new
InputSource
(
reader
));
CheckReport
report
=
(
CheckReport
)
getContext
().
createUnmarshaller
().
unmarshal
(
new
InputSource
(
reader
));
enrichReportStructure
(
report
);
enrichReportStructure
(
report
);
return
report
;
return
report
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlConsumer.java
View file @
1fbe16e1
...
@@ -32,6 +32,5 @@ public interface CityGmlConsumer {
...
@@ -32,6 +32,5 @@ public interface CityGmlConsumer {
}
}
// public void endOfFile();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
View file @
1fbe16e1
...
@@ -131,9 +131,9 @@ public class CityGmlParser {
...
@@ -131,9 +131,9 @@ public class CityGmlParser {
private
static
CityGMLContext
context
;
private
static
CityGMLContext
context
;
private
static
List
<
QName
>
chunkProperties
=
new
ArrayList
<>();
private
static
List
<
QName
>
chunkProperties
=
new
ArrayList
<>();
static
{
static
{
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
FACTORY
=
SAXParserFactory
.
newInstance
();
FACTORY
=
SAXParserFactory
.
newInstance
();
try
{
try
{
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
false
);
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
false
);
...
@@ -149,7 +149,7 @@ public class CityGmlParser {
...
@@ -149,7 +149,7 @@ public class CityGmlParser {
private
CityGmlParser
()
{
private
CityGmlParser
()
{
}
}
public
static
synchronized
CityGMLContext
g
etContext
()
{
public
static
synchronized
CityGMLContext
s
et
up
Context
()
{
if
(
context
==
null
)
{
if
(
context
==
null
)
{
try
{
try
{
context
=
CityGMLContext
.
newInstance
(
CityGmlParser
.
class
.
getClassLoader
());
context
=
CityGMLContext
.
newInstance
(
CityGmlParser
.
class
.
getClassLoader
());
...
@@ -168,13 +168,17 @@ public class CityGmlParser {
...
@@ -168,13 +168,17 @@ public class CityGmlParser {
}
}
/**
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* <p/>
* The nested parse uses an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}, which
* The nested parse uses an
* is not connected to the database.
* {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache
* UnconnectedCache}, which is not connected to the database.
* <p/>
* <p/>
* Nested parsing should only be used for accessing Features in auxiliary, small CityGML files, e.g. parsing of
* Nested parsing should only be used for accessing Features in auxiliary, small
* {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject LibraryObject} files.
* CityGML files, e.g. parsing of
* {@link de.hft.stuttgart.citydoctor2.datastructure.LibraryObject
* LibraryObject} files.
*
*
* @param filePath String path to the file
* @param filePath String path to the file
* @param config Configuration of the parser
* @param config Configuration of the parser
...
@@ -188,10 +192,12 @@ public class CityGmlParser {
...
@@ -188,10 +192,12 @@ public class CityGmlParser {
}
}
/**
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* Features are held in a non-persistent, embedded Database with an in-memory
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
*
* @param filePath String path to the file
* @param filePath String path to the file
* @param config Configuration of the parser
* @param config Configuration of the parser
...
@@ -204,12 +210,13 @@ public class CityGmlParser {
...
@@ -204,12 +210,13 @@ public class CityGmlParser {
return
parseCityGmlFile
(
filePath
,
config
,
null
,
null
);
return
parseCityGmlFile
(
filePath
,
config
,
null
,
null
);
}
}
/**
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* Features are held in a non-persistent, embedded Database with an in-memory
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
*
* @param filePath String path to the file
* @param filePath String path to the file
* @param config Configuration of the parser
* @param config Configuration of the parser
...
@@ -224,10 +231,12 @@ public class CityGmlParser {
...
@@ -224,10 +231,12 @@ public class CityGmlParser {
}
}
/**
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* Features are held in a non-persistent, embedded Database with an in-memory
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
*
* @param filePath String path to the file
* @param filePath String path to the file
* @param config Configuration of the parser
* @param config Configuration of the parser
...
@@ -243,18 +252,22 @@ public class CityGmlParser {
...
@@ -243,18 +252,22 @@ public class CityGmlParser {
}
}
/**
/**
* Parses a given CityGML file and collects the contained CityObject Features in a {@link CityDoctorModel}.
* Parses a given CityGML file and collects the contained CityObject Features in
* a {@link CityDoctorModel}.
* <p/>
* <p/>
* Features are held in a non-persistent, embedded Database with an in-memory upstream cache. Thus, strong references
* Features are held in a non-persistent, embedded Database with an in-memory
* to {@link CityObject} are to be avoided, to allow for the memory management of the cache.
* upstream cache. Thus, strong references to {@link CityObject} are to be
* avoided, to allow for the memory management of the cache.
*
*
* @param filePath String path to the file
* @param filePath String path to the file
* @param config Configuration of the parser
* @param config Configuration of the parser
* @param l Listener hook for tracking of parsing progress
* @param l Listener hook for tracking of parsing progress
* @param handler Validation handler for GML-file validation
* @param handler Validation handler for GML-file validation
* @param verbose If verbosity is enabled the parser will write info logs to the logger
* @param verbose If verbosity is enabled the parser will write info logs to
* @param unconnected If true the parser will use an {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache UnconnectedCache}
* the logger
* to collect the parsed CityObjects
* @param unconnected If true the parser will use an
* {@link de.hft.stuttgart.citydoctor2.database.UnconnectedCache
* UnconnectedCache} to collect the parsed CityObjects
* @return A {@link CityDoctorModel} object with the parsed Features
* @return A {@link CityDoctorModel} object with the parsed Features
* @throws CityGmlParseException if parsing of the CityGML-file failed
* @throws CityGmlParseException if parsing of the CityGML-file failed
* @throws InvalidGmlFileException if the GMLValidationHandler found an error
* @throws InvalidGmlFileException if the GMLValidationHandler found an error
...
@@ -262,13 +275,12 @@ public class CityGmlParser {
...
@@ -262,13 +275,12 @@ public class CityGmlParser {
private
static
CityDoctorModel
parseCityGmlFile
(
String
filePath
,
ParserConfiguration
config
,
ProgressListener
l
,
private
static
CityDoctorModel
parseCityGmlFile
(
String
filePath
,
ParserConfiguration
config
,
ProgressListener
l
,
GMLValidationHandler
handler
,
boolean
verbose
,
boolean
unconnected
)
GMLValidationHandler
handler
,
boolean
verbose
,
boolean
unconnected
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
throws
CityGmlParseException
,
InvalidGmlFileException
{
CityGMLContext
context
=
g
etContext
();
CityGMLContext
context
=
s
et
up
Context
();
Path
file
=
Paths
.
get
(
filePath
);
Path
file
=
Paths
.
get
(
filePath
);
List
<
String
>
validationIssues
=
Collections
.
emptyList
();
List
<
String
>
validationIssues
=
Collections
.
emptyList
();
if
(
config
.
getValidate
())
{
if
(
config
.
getValidate
())
{
validationIssues
=
validateFile
(
context
,
handler
,
file
);
validationIssues
=
validateFile
(
handler
,
file
);
}
}
try
{
try
{
parseEpsgCodeFromFile
(
file
,
config
,
verbose
);
parseEpsgCodeFromFile
(
file
,
config
,
verbose
);
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
...
@@ -288,8 +300,6 @@ public class CityGmlParser {
...
@@ -288,8 +300,6 @@ public class CityGmlParser {
}
}
}
}
public
static
void
streamCityGml
(
String
file
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
public
static
void
streamCityGml
(
String
file
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
String
outputFile
)
throws
CityGmlParseException
{
Path
f
=
Paths
.
get
(
file
);
Path
f
=
Paths
.
get
(
file
);
...
@@ -342,18 +352,18 @@ public class CityGmlParser {
...
@@ -342,18 +352,18 @@ public class CityGmlParser {
private
static
void
readAndDiscardFeatures
(
Path
file
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
private
static
void
readAndDiscardFeatures
(
Path
file
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
,
false
);
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
,
false
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
,
config
,
file
);
}
}
private
static
void
readAndDiscardModel
(
Citygml3FeatureMapper
mapper
,
ObservedInputStream
ois
,
private
static
void
readAndDiscardModel
(
Citygml3FeatureMapper
mapper
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
,
ParserConfiguration
config
,
Path
file
)
getContext
();
throws
CityGMLReadException
{
setupContext
();
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
CityGMLChunkWriter
writer
=
null
;
CityGMLChunkWriter
writer
=
null
;
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
CityDoctorModel
model
=
mapper
.
getModel
();
CityDoctorModel
model
=
mapper
.
getModel
();
boolean
isInitialized
=
false
;
boolean
isInitialized
=
false
;
while
(
reader
.
hasNext
())
{
while
(
reader
.
hasNext
())
{
...
@@ -418,7 +428,7 @@ public class CityGmlParser {
...
@@ -418,7 +428,7 @@ public class CityGmlParser {
if
(
outputFile
==
null
)
{
if
(
outputFile
==
null
)
{
return
null
;
return
null
;
}
}
CityGMLContext
gmlContext
=
CityGmlParser
.
g
etContext
();
CityGMLContext
gmlContext
=
CityGmlParser
.
s
et
up
Context
();
CityGMLVersion
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
CityGMLVersion
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
version
);
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
version
);
CityGMLChunkWriter
writer
=
factory
.
createCityGMLChunkWriter
(
new
File
(
outputFile
),
CityGMLChunkWriter
writer
=
factory
.
createCityGMLChunkWriter
(
new
File
(
outputFile
),
...
@@ -432,8 +442,8 @@ public class CityGmlParser {
...
@@ -432,8 +442,8 @@ public class CityGmlParser {
}
}
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
Path
file
,
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
Path
file
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
,
boolean
unconnected
)
boolean
verbose
,
boolean
unconnected
)
throws
CityGMLReadException
{
throws
CityGMLReadException
{
return
readAndKeepModel
(
new
Citygml3FeatureMapper
(
config
,
file
,
unconnected
),
inputFactory
,
ois
,
verbose
);
return
readAndKeepModel
(
new
Citygml3FeatureMapper
(
config
,
file
,
unconnected
),
inputFactory
,
ois
,
verbose
);
}
}
...
@@ -448,7 +458,7 @@ public class CityGmlParser {
...
@@ -448,7 +458,7 @@ public class CityGmlParser {
CityModel
cgmlModel
=
null
;
CityModel
cgmlModel
=
null
;
CityDoctorModel
cdModel
=
mapper
.
getModel
();
CityDoctorModel
cdModel
=
mapper
.
getModel
();
AutoCloseable
parsingContext
=
cdModel
.
getCache
().
startParsingMode
();
AutoCloseable
parsingContext
=
cdModel
.
getCache
().
startParsingMode
();
try
(
parsingContext
){
try
(
parsingContext
)
{
List
<
AbstractCityObject
>
queuedObjects
=
new
ArrayList
<>();
List
<
AbstractCityObject
>
queuedObjects
=
new
ArrayList
<>();
while
(
reader
.
hasNext
())
{
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
AbstractFeature
chunk
=
reader
.
next
();
...
@@ -473,7 +483,7 @@ public class CityGmlParser {
...
@@ -473,7 +483,7 @@ public class CityGmlParser {
if
(
cgmlModel
==
null
)
{
if
(
cgmlModel
==
null
)
{
// Add object to queue till the CityModel has been parsed
// Add object to queue till the CityModel has been parsed
queuedObjects
.
add
(
aco
);
queuedObjects
.
add
(
aco
);
}
else
if
(!
cdModel
.
containsGmlId
(
id
)){
}
else
if
(!
cdModel
.
containsGmlId
(
id
))
{
cgmlModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
cgmlModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
}
}
}
}
...
@@ -486,7 +496,8 @@ public class CityGmlParser {
...
@@ -486,7 +496,8 @@ public class CityGmlParser {
mapper
.
setCityModel
(
new
CityModel
());
mapper
.
setCityModel
(
new
CityModel
());
for
(
AbstractCityObject
aco
:
queuedObjects
)
{
for
(
AbstractCityObject
aco
:
queuedObjects
)
{
if
(!
cdModel
.
containsGmlId
(
aco
.
getId
()))
{
if
(!
cdModel
.
containsGmlId
(
aco
.
getId
()))
{
mapper
.
getModel
().
getCityModel
().
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
mapper
.
getModel
().
getCityModel
().
getCityObjectMembers
()
.
add
(
new
AbstractCityObjectProperty
(
aco
));
}
}
}
}
}
}
...
@@ -506,7 +517,8 @@ public class CityGmlParser {
...
@@ -506,7 +517,8 @@ public class CityGmlParser {
}
}
}
}
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
,
boolean
verbose
)
throws
CityGmlParseException
{
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
,
boolean
verbose
)
throws
CityGmlParseException
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
.
toFile
())))
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
.
toFile
())))
{
parseEpsgCodeFromStream
(
bis
,
config
,
verbose
);
parseEpsgCodeFromStream
(
bis
,
config
,
verbose
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
...
@@ -673,11 +685,12 @@ public class CityGmlParser {
...
@@ -673,11 +685,12 @@ public class CityGmlParser {
return
CRS_FACTORY
.
createFromParameters
(
crsName
,
params
.
toArray
(
new
String
[
0
]));
return
CRS_FACTORY
.
createFromParameters
(
crsName
,
params
.
toArray
(
new
String
[
0
]));
}
}
private
static
List
<
String
>
validateFile
(
CityGMLContext
context
,
GMLValidationHandler
handler
,
Path
file
)
public
static
List
<
String
>
validateFile
(
GMLValidationHandler
handler
,
Path
file
)
throws
CityGmlParseException
{
throws
CityGmlParseException
{
if
(
handler
==
null
)
{
if
(
handler
==
null
)
{
handler
=
new
GMLValidationHandler
();
handler
=
new
GMLValidationHandler
();
}
}
setupContext
();
try
{
try
{
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
readAdditionalSchemaDefinitions
(
context
,
file
,
schemaHandler
);
readAdditionalSchemaDefinitions
(
context
,
file
,
schemaHandler
);
...
@@ -696,8 +709,7 @@ public class CityGmlParser {
...
@@ -696,8 +709,7 @@ public class CityGmlParser {
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
Path
file
,
SchemaHandler
schemaHandler
)
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
Path
file
,
SchemaHandler
schemaHandler
)
throws
CityGmlParseException
{
throws
CityGmlParseException
{
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
())
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
()).
withSchemaHandler
(
schemaHandler
)
.
withSchemaHandler
(
schemaHandler
)
.
createReader
(
file
))
{
.
createReader
(
file
))
{
reader
.
nextTag
();
reader
.
nextTag
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
...
@@ -715,5 +727,4 @@ public class CityGmlParser {
...
@@ -715,5 +727,4 @@ public class CityGmlParser {
}
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/writer/CityGMLWriterUtils.java
View file @
1fbe16e1
...
@@ -65,7 +65,7 @@ public class CityGMLWriterUtils {
...
@@ -65,7 +65,7 @@ public class CityGMLWriterUtils {
}
}
public
static
void
writeCityModel
(
String
file
,
CityDoctorModel
model
)
throws
CityDoctorWriteException
{
public
static
void
writeCityModel
(
String
file
,
CityDoctorModel
model
)
throws
CityDoctorWriteException
{
CityGMLContext
gmlContext
=
CityGmlParser
.
g
etContext
();
CityGMLContext
gmlContext
=
CityGmlParser
.
s
et
up
Context
();
CityModel
cModel
=
model
.
getCityModel
();
CityModel
cModel
=
model
.
getCityModel
();
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
model
.
getCityGMLVersion
());
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
model
.
getCityGMLVersion
());
try
(
CityGMLWriter
writer
=
factory
.
createCityGMLWriter
(
new
File
(
file
)))
{
try
(
CityGMLWriter
writer
=
factory
.
createCityGMLWriter
(
new
File
(
file
)))
{
...
...
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/parser/CityGml3ParserTest.java
View file @
1fbe16e1
...
@@ -37,7 +37,7 @@ public class CityGml3ParserTest {
...
@@ -37,7 +37,7 @@ public class CityGml3ParserTest {
@Test
@Test
public
void
testGetContext
()
{
public
void
testGetContext
()
{
CityGMLContext
context
=
CityGmlParser
.
g
etContext
();
CityGMLContext
context
=
CityGmlParser
.
s
et
up
Context
();
List
<
ADE
>
ades
=
ADERegistry
.
getInstance
().
getADEs
();
List
<
ADE
>
ades
=
ADERegistry
.
getInstance
().
getADEs
();
ADE
ade
=
ades
.
get
(
0
);
ADE
ade
=
ades
.
get
(
0
);
assertEquals
(
QualityADEContext
.
class
,
ade
.
getClass
());
assertEquals
(
QualityADEContext
.
class
,
ade
.
getClass
());
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
View file @
1fbe16e1
...
@@ -65,6 +65,7 @@ import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
...
@@ -65,6 +65,7 @@ import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError
;
import
de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError
;
import
de.hft.stuttgart.citydoctor2.check.error.SchematronError
;
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.checkresult.utility.CheckReportWriteException
;
import
de.hft.stuttgart.citydoctor2.checks.CheckContainer
;
import
de.hft.stuttgart.citydoctor2.checks.CheckContainer
;
import
de.hft.stuttgart.citydoctor2.checks.CheckPrototype
;
import
de.hft.stuttgart.citydoctor2.checks.CheckPrototype
;
...
@@ -919,6 +920,20 @@ public class Checker {
...
@@ -919,6 +920,20 @@ public class Checker {
XmlStreamReporter
xmlReporter
=
getXmlReporter
(
config
,
xmlBos
,
fileName
);
XmlStreamReporter
xmlReporter
=
getXmlReporter
(
config
,
xmlBos
,
fileName
);
PdfStreamReporter
pdfReporter
=
getPdfReporter
(
config
,
pdfBos
,
fileName
);
PdfStreamReporter
pdfReporter
=
getPdfReporter
(
config
,
pdfBos
,
fileName
);
// XML validation
if
(
config
.
isUseStreaming
()
&&
(
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
// execute schematron first
SvrlContentHandler
handler
=
executeSchematronValidationIfAvailable
(
config
,
inputFile
);
SvrlContentHandler
handler
=
executeSchematronValidationIfAvailable
(
config
,
inputFile
);
CityGmlConsumer
con
=
new
StreamCityGmlConsumer
(
c
,
xmlReporter
,
pdfReporter
,
handler
,
config
,
l
);
CityGmlConsumer
con
=
new
StreamCityGmlConsumer
(
c
,
xmlReporter
,
pdfReporter
,
handler
,
config
,
l
);
...
...
CityDoctorParent/CityDoctorValidation/src/test/java/de/hft/stuttgart/citydoctor2/check/CheckerTest.java
View file @
1fbe16e1
...
@@ -18,6 +18,22 @@
...
@@ -18,6 +18,22 @@
*/
*/
package
de.hft.stuttgart.citydoctor2.check
;
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.CityDoctorValidation
;
import
de.hft.stuttgart.citydoctor2.checkresult.CheckReport
;
import
de.hft.stuttgart.citydoctor2.checkresult.CheckReport
;
import
de.hft.stuttgart.citydoctor2.checkresult.GlobalErrorStatistics
;
import
de.hft.stuttgart.citydoctor2.checkresult.GlobalErrorStatistics
;
...
@@ -31,22 +47,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
...
@@ -31,22 +47,6 @@ import de.hft.stuttgart.citydoctor2.parser.CityGmlParseException;
import
de.hft.stuttgart.citydoctor2.parser.CityGmlParser
;
import
de.hft.stuttgart.citydoctor2.parser.CityGmlParser
;
import
de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException
;
import
de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
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
* @author Matthias Betz
...
@@ -76,7 +76,8 @@ public class CheckerTest {
...
@@ -76,7 +76,8 @@ public class CheckerTest {
}
}
@Test
@Test
public
void
testChecker
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
public
void
testChecker
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
File
f
=
folder
.
newFile
();
File
f
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
...
@@ -98,7 +99,8 @@ public class CheckerTest {
...
@@ -98,7 +99,8 @@ public class CheckerTest {
}
}
@Test
@Test
public
void
testStreaming
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
public
void
testStreaming
()
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
,
CityDoctorWriteException
{
File
f
=
folder
.
newFile
();
File
f
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
File
f2
=
folder
.
newFile
();
File
f3
=
folder
.
newFile
();
File
f3
=
folder
.
newFile
();
...
@@ -125,6 +127,27 @@ public class CheckerTest {
...
@@ -125,6 +127,27 @@ public class CheckerTest {
}
}
}
}
@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
@Test
public
void
testReportCreation
()
throws
IOException
,
CityGmlParseException
,
InvalidGmlFileException
{
public
void
testReportCreation
()
throws
IOException
,
CityGmlParseException
,
InvalidGmlFileException
{
Path
tmpDir
=
null
;
Path
tmpDir
=
null
;
...
@@ -134,8 +157,8 @@ public class CheckerTest {
...
@@ -134,8 +157,8 @@ public class CheckerTest {
Path
xmlPath
=
tmpDir
.
resolve
(
"report.xml"
);
Path
xmlPath
=
tmpDir
.
resolve
(
"report.xml"
);
Path
pdfPath
=
tmpDir
.
resolve
(
"report.pdf"
);
Path
pdfPath
=
tmpDir
.
resolve
(
"report.pdf"
);
File
features
=
new
File
(
"src/test/resources/feature_types.gml"
);
File
features
=
new
File
(
"src/test/resources/feature_types.gml"
);
CityDoctorModel
model
=
CityGmlParser
.
nestedCityGmlFileParse
(
CityDoctorModel
model
=
CityGmlParser
.
nestedCityGmlFileParse
(
features
.
toString
(),
features
.
toString
(),
new
ParserConfiguration
(
8
,
false
));
new
ParserConfiguration
(
8
,
false
));
assertNotNull
(
model
);
assertNotNull
(
model
);
Checker
checker
=
new
Checker
(
model
);
Checker
checker
=
new
Checker
(
model
);
checker
.
runChecks
();
checker
.
runChecks
();
...
@@ -174,12 +197,10 @@ public class CheckerTest {
...
@@ -174,12 +197,10 @@ public class CheckerTest {
assertEquals
(
1
,
globError
.
getNumErrorCityFurniture
());
assertEquals
(
1
,
globError
.
getNumErrorCityFurniture
());
assertEquals
(
1
,
globError
.
getNumErrorGenericCityObjects
());
assertEquals
(
1
,
globError
.
getNumErrorGenericCityObjects
());
}
catch
(
CheckReportParseException
e
)
{
}
catch
(
CheckReportParseException
e
)
{
fail
(
"Report should be valid file"
);
fail
(
"Report should be valid file"
);
}
}
}
finally
{
}
finally
{
if
(
tmpDir
!=
null
)
{
if
(
tmpDir
!=
null
)
{
FileUtils
.
deleteDirectory
(
tmpDir
.
toFile
());
FileUtils
.
deleteDirectory
(
tmpDir
.
toFile
());
...
...
CityDoctorParent/CityDoctorValidation/src/test/resources/SimpleSolid_SrefBS_XMLInvalid.gml
0 → 100644
View file @
1fbe16e1
<?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
CityDoctorParent/CityDoctorValidation/src/test/resources/testConfigWithStreamingWithValidation.yml
0 → 100644
View file @
1fbe16e1
globalParameters
:
numberOfRoundingPlaces
:
8
schematronFilePath
:
src/test/resources/schematronTest.xml
useStreaming
:
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
CityDoctorParent/Extensions/CityDoctorHealer/src/main/java/de/hft/stuttgart/citydoctor2/healer/Healer.java
View file @
1fbe16e1
...
@@ -289,7 +289,7 @@ public class Healer {
...
@@ -289,7 +289,7 @@ public class Healer {
private
byte
[]
writeCityGml
(
AbstractCityObject
aco
)
throws
CityGMLWriteException
{
private
byte
[]
writeCityGml
(
AbstractCityObject
aco
)
throws
CityGMLWriteException
{
CityModel
model
=
new
CityModel
();
CityModel
model
=
new
CityModel
();
model
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
model
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
CityGMLContext
context
=
CityGmlParser
.
g
etContext
();
CityGMLContext
context
=
CityGmlParser
.
s
et
up
Context
();
CityGMLOutputFactory
outputFactory
=
context
.
createCityGMLOutputFactory
(
CityGMLVersion
.
v2_0
);
CityGMLOutputFactory
outputFactory
=
context
.
createCityGMLOutputFactory
(
CityGMLVersion
.
v2_0
);
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
try
(
CityGMLWriter
writer
=
outputFactory
.
createCityGMLWriter
(
out
))
{
try
(
CityGMLWriter
writer
=
outputFactory
.
createCityGMLWriter
(
out
))
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment