diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b63da4551b2e169d28b20728d5d53c6ca1779da4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000000000000000000000000000000000..4914fb0bfbc4d5371ac3ee76a5b3b5229f43344b
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+energy-ade2-citydb
\ No newline at end of file
diff --git a/.idea/artifacts/energy_ade2_citydb_jar.xml b/.idea/artifacts/energy_ade2_citydb_jar.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d20439dc692bac9477de29f9590785c97c3533b
--- /dev/null
+++ b/.idea/artifacts/energy_ade2_citydb_jar.xml
@@ -0,0 +1,109 @@
+
+
+ $PROJECT_DIR$/out/artifacts/energy_ade2_citydb_jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a27b7c24acc9b8c1c4654b960b2baf6ef2211824
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000000000000000000000000000000000..63758e754572d536422997ed68348087a83ce70d
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6bfb2cf39cc4d401d7437e4730adbdd432bf6e53
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2b63946d5b31084bbb7dda418ceb3d75eb686373
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ae84807f3c115317adad4febf64a6462649681a5
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index f03413f3cfc09e8de2e609903a8e30cae383bf3f..e1a8936b7baf5bf72c7f92a1aed3bc24f1a944b9 100644
--- a/README.md
+++ b/README.md
@@ -1,92 +1,22 @@
-# Energy ADE 2 3DCityDB
+# Energy ADE (ver 2 beta 7) module for importer/exporter plugin v5.5.1 for 3DCityDB v4.4.2 - Work in Progress
+[Java 17](https://bell-sw.com/pages/downloads/#jdk-17-lts) is the minimum requirement.
+This is a 3DCityDB importer/exporter plugin module for the **Energy Application Domain Extension** (Energy ADE) v2 beta7 for CityGML.
-## Getting started
+There are
+currently _no plans to migrate_ the Energy ADE 2 module to citygml4j v3, CityGML 3 or 3DCityDB v5.
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+Priority List:
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://transfer.hft-stuttgart.de/gitlab/energy-ade/energy-ade-2-3dcitydb.git
-git branch -M master
-git push -uf origin master
-```
-
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://transfer.hft-stuttgart.de/gitlab/energy-ade/energy-ade-2-3dcitydb/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
-
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
-
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
-
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
-
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
-
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
-
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
-
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
-
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
-
-## License
-For open source projects, say how it is licensed.
-
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
+- Timeseries
+- DataType
+- Core
+- Resource
+- UrbanFunctionAreas
+- WeatherStation
+- Layered Construction
+- Schedule
+- Devices
+- BuildingPhysics
+- Occupancy
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..5c7447db882b3fefbed60548db966007d6fabdc4
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'java'
+ id 'java-library'
+ id 'distribution'
+ id 'maven-publish'
+ id 'signing'
+ id 'io.github.gradle-nexus.publish-plugin' version '2.0.0'
+}
+
+group = 'de.stuttgart.hft'
+version = 'beta7'
+description 'Energy ADE2 extension for the 3DCityDB'
+
+repositories {
+ maven {
+ url 'https://3dcitydb.org/maven'
+ }
+ maven {
+ url 'https://repo.osgeo.org/repository/release'
+ }
+ mavenCentral()
+ mavenLocal()
+}
+
+configurations {
+ citygml4j
+}
+
+dependencies {
+ api 'org.citydb:impexp-client-gui:5.5.1'
+ api 'org.citygml4j.ade:energy-ade2-citygml4j:2.0.1'
+
+ citygml4j('org.citygml4j.ade:energy-ade2-citygml4j:2.0.1') {
+ transitive = false
+ }
+
+ testImplementation platform('org.junit:junit-bom:5.10.0')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
+
+}
+
+test {
+ useJUnitPlatform()
+}
+
+distributions.main {
+ distributionBaseName = 'energy-ade2'
+
+ contents {
+ from 'README.md'
+ into('lib') {
+ from jar
+ from configurations.citygml4j
+ }
+ into('schema-mapping') {
+ from "$rootDir/resources/database/schema-mapping"
+ }
+ into('3dcitydb') {
+ from "$rootDir/resources/database/3dcitydb"
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..249e5832f090a2944b7473328c07c9755baa3196
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..d8421bcea78a9ecac7a7e4bfd3e4e33d91e9e1e1
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Feb 12 14:58:14 CET 2025
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000000000000000000000000000000000000..1b6c787337ffb79f0e3cf8b1e9f00f680a959de1
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..107acd32c4e687021ef32db511e8a206129b88ec
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/resources/database/3dcitydb/postgreSQL/CREATE_ADE_DB.sql b/resources/database/3dcitydb/postgreSQL/CREATE_ADE_DB.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ee163e51f48716b6e0eaf1f1c3fc1b8eff7d17cc
--- /dev/null
+++ b/resources/database/3dcitydb/postgreSQL/CREATE_ADE_DB.sql
@@ -0,0 +1,1048 @@
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+--
+-- CityGML Energy ADE 2.0 (beta 7)
+--
+-- Last update: 2025-06-25
+--
+-- This DDL script installs the 3DCityDB schema for the Energy ADE 2.0. It must be run
+-- from within the ADE Manager plugin of the 3DCityDB Importer/Exporter.
+--
+-- This script was first automatically generated using the 3DCityDB ADE Manager
+-- and successively edited and restructured by:
+--
+-- Dr. Giorgio Agugiaro
+-- 3D Geoinformation group
+-- Delft University of Technology
+-- The Netherlands
+--
+-- https://3d.bk.tudelft.nl/gagugiaro/
+--
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- ***************************** CREATE_ADE_DB.SQL execution START ************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Create Sequences ***********************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+CREATE SEQUENCE ng2_ctyobj_relation_seq INCREMENT BY 1 MINVALUE 0 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1 NO CYCLE OWNED BY NONE;
+CREATE SEQUENCE ng2_optical_property_seq INCREMENT BY 1 MINVALUE 0 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1 NO CYCLE OWNED BY NONE;
+CREATE SEQUENCE ng2_qualified_attribute_seq INCREMENT BY 1 MINVALUE 0 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1 NO CYCLE OWNED BY NONE;
+CREATE SEQUENCE ng2_suitability_seq INCREMENT BY 1 MINVALUE 0 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1 NO CYCLE OWNED BY NONE;
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Create tables **************************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+-- --------------------------------------------------------------------
+-- ng2_address_to_building_unit
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_address_to_building_unit (
+ address_id BIGINT NOT NULL,
+ building_unit_id BIGINT NOT NULL,
+ PRIMARY KEY (address_id, building_unit_id)
+);
+
+-- --------------------------------------------------------------------
+-- ng2_building - extends building table
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_building (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ is_protected NUMERIC,
+ constr_weight VARCHAR,
+ constr_weight_codespace VARCHAR,
+ attic_thm_status VARCHAR,
+ basement_thm_status VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_building_partition
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_building_partition (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+-- Thermal Zone attributes
+ heat_capacity NUMERIC,
+ heat_capacity_uom VARCHAR,
+ infiltration_rate NUMERIC,
+ infiltration_rate_uom VARCHAR,
+ is_cooled NUMERIC,
+ is_heated NUMERIC,
+ coincides_with_lod2_hull NUMERIC,
+ coincides_with_lod3_hull NUMERIC,
+-- Usage Zone and BuildingUnit attributes
+ type VARCHAR,
+ type_codespace VARCHAR,
+-- Usage Zone attributes
+ is_primary NUMERIC,
+ num_of_building_units INTEGER,
+ int_heat_gains NUMERIC,
+ int_heat_gains_uom VARCHAR,
+ int_heat_gains_conv NUMERIC,
+ int_heat_gains_conv_uom VARCHAR,
+ int_heat_gains_lat NUMERIC,
+ int_heat_gains_lat_uom VARCHAR,
+ int_heat_gains_rad NUMERIC,
+ int_heat_gains_rad_uom VARCHAR,
+-- BuildingUnit attributes
+ num_of_rooms INTEGER,
+ owner_name VARCHAR,
+ ownership_type VARCHAR,
+ ownership_type_codespace VARCHAR,
+-- Used to store the FK to the schedule(s)
+ cooling_schedule_id BIGINT,
+ heating_schedule_id BIGINT,
+ ventilation_schedule_id BIGINT,
+-- Used to store the association from UsageZone to BuildingUnit
+ usage_zone_id BIGINT,
+-- Used to store the association from ThermalZone to UsageZone
+ thermal_zone_id BIGINT,
+-- Parent id (Building(Part) of a ThermalZone, UsageZone or BuildintUnit
+ building_id BIGINT,
+-- FK to the geometries in the surface_geometry table
+ lod1_solid_id BIGINT,
+ lod2_solid_id BIGINT,
+ lod3_solid_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_cityobject - extends cityobject table
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_cityobject (
+ id BIGINT PRIMARY KEY,
+ layered_construction_id BIGINT,
+ ref_point geometry(POINTZ)
+);
+
+-- --------------------------------------------------------------------
+-- ng2_ctyobj_relation
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_ctyobj_relation (
+ id BIGINT PRIMARY KEY DEFAULT nextval('ng2_ctyobj_relation_seq'::regclass),
+-- this refers to ng2_cityobject (id), i.e. the source
+ ng2_cityobject_id BIGINT,
+-- this refers to cityobject (id), i.e. the target
+ cityobject_id BIGINT,
+ relation_type VARCHAR,
+ relation_type_codespace VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_device
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_device (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+-- AbstractDevice attributes (also for LightingDevice, GenericDevice, GenericElectricalDevice)
+ model VARCHAR,
+ num_of_devices INTEGER,
+ year_of_manufacture INTEGER,
+ installed_power NUMERIC,
+ installed_power_uom VARCHAR,
+ nominal_efficiency NUMERIC,
+ nominal_efficiency_uom VARCHAR,
+ efficiency_indicator VARCHAR,
+ heat_diss NUMERIC,
+ heat_diss_uom VARCHAR,
+ heat_diss_conv NUMERIC,
+ heat_diss_conv_uom VARCHAR,
+ heat_diss_lat NUMERIC,
+ heat_diss_lat_uom VARCHAR,
+ heat_diss_rad NUMERIC,
+ heat_diss_rad_uom VARCHAR,
+-- HeatPump attributes
+ heat_source VARCHAR,
+ cop_source_temp NUMERIC,
+ cop_source_temp_uom VARCHAR,
+ cop_operation_temp NUMERIC,
+ cop_operation_temp_uom VARCHAR,
+-- Boiler attributes
+ has_condensation NUMERIC,
+-- MovableShadingDevice attributes
+ type VARCHAR,
+ type_codespace VARCHAR,
+ installation_side VARCHAR,
+ max_cover_ratio NUMERIC,
+ max_cover_ratio_uom VARCHAR,
+-- FK to table optical_property
+ transmittance_id BIGINT,
+ cityobject_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_device_operation
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_device_operation (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ yearly_global_efficiency NUMERIC,
+-- FK
+ schedule_id BIGINT,
+ device_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_energy_perf_cert
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_energy_perf_cert (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ label VARCHAR,
+ value NUMERIC,
+ value_uom VARCHAR,
+ issue_date DATE,
+ expiration_date DATE,
+ cert_method VARCHAR,
+ cert_uri VARCHAR,
+-- FK
+ building_id BIGINT,
+ building_partition_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_layer
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_layer (
+ id BIGINT PRIMARY KEY,
+ thickness NUMERIC,
+ thickness_uom VARCHAR,
+ material_id BIGINT,
+-- FK
+ layered_construction_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_layered_construction
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_layered_construction (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ u_value NUMERIC,
+ u_value_uom VARCHAR,
+ g_value NUMERIC,
+ g_value_uom VARCHAR,
+ glazing_ratio NUMERIC,
+ glazing_ratio_uom VARCHAR,
+ library_code VARCHAR,
+ library_code_codespace VARCHAR,
+-- FKs
+ layered_construction_id BIGINT,
+ library_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_library
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_library (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ author VARCHAR,
+ source VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_material
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_material (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+-- Abstract library attributes
+ library_code VARCHAR,
+ library_code_codespace VARCHAR,
+-- SolidMaterial attributes
+ thm_conductivity NUMERIC,
+ thm_conductivity_uom VARCHAR,
+ spec_heat_capacity NUMERIC,
+ spec_heat_capacity_uom VARCHAR,
+ density NUMERIC,
+ density_uom VARCHAR,
+ permeance NUMERIC,
+ permeance_uom VARCHAR,
+ porosity NUMERIC,
+ porosity_uom VARCHAR,
+ embodied_carbon NUMERIC,
+ embodied_carbon_uom VARCHAR,
+ embodied_energy NUMERIC,
+ embodied_energy_uom VARCHAR,
+-- Gas attributes
+ is_ventilated NUMERIC,
+ r_value NUMERIC,
+ r_value_uom VARCHAR,
+-- FK
+ library_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_occupants
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_occupants (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ num_of_occupants INTEGER,
+ heat_diss NUMERIC,
+ heat_diss_uom VARCHAR,
+ heat_diss_conv NUMERIC,
+ heat_diss_conv_uom VARCHAR,
+ heat_diss_lat NUMERIC,
+ heat_diss_lat_uom VARCHAR,
+ heat_diss_rad NUMERIC,
+ heat_diss_rad_uom VARCHAR,
+ avg_diet_type VARCHAR,
+ avg_diet_type_codespace VARCHAR,
+ avg_income_level VARCHAR,
+ avg_income_level_codespace VARCHAR,
+ avg_instr_level VARCHAR,
+ avg_instr_level_codespace VARCHAR,
+-- FK
+ schedule_id BIGINT,
+ building_partition_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_opening - extends (building) opening table
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_opening (
+ id BIGINT PRIMARY KEY,
+ area NUMERIC,
+ area_uom VARCHAR,
+ azimuth NUMERIC,
+ azimuth_uom VARCHAR,
+ inclination NUMERIC,
+ inclination_uom VARCHAR,
+ ground_view_factor NUMERIC,
+ ground_view_factor_uom VARCHAR,
+ sky_view_factor NUMERIC,
+ sky_view_factor_uom VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_optical_property
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_optical_property (
+ id BIGINT PRIMARY KEY DEFAULT nextval('ng2_optical_property_seq'::regclass),
+ objectclass_id INTEGER,
+ fraction NUMERIC,
+ fraction_uom VARCHAR,
+ surface VARCHAR,
+ wavelength_range VARCHAR,
+-- FK
+ layered_construction_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_qualified_attribute
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_qualified_attribute (
+ id BIGINT PRIMARY KEY DEFAULT nextval('ng2_qualified_attribute_seq'::regclass),
+ objectclass_id INTEGER,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ value NUMERIC,
+ value_uom VARCHAR,
+ description VARCHAR,
+ source VARCHAR,
+-- FK
+ building_id BIGINT,
+ building_partition_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_refurbishment_measure
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_refurbishment_measure (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ start_date DATE,
+ end_date DATE,
+ library_code VARCHAR,
+ library_code_codespace VARCHAR,
+-- FK
+ building_id BIGINT,
+ building_partition_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_resource
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_resource (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ enduse VARCHAR,
+ enduse_codespace VARCHAR,
+ status VARCHAR,
+ operation_type VARCHAR,
+ operation_type_codespace VARCHAR,
+ year INTEGER,
+ amount_type VARCHAR,
+ amount_type_codespace VARCHAR,
+ amount NUMERIC,
+ amount_uom VARCHAR,
+ time_series_id BIGINT,
+ is_amount_normalized NUMERIC,
+ normalization_param VARCHAR,
+ normalization_value NUMERIC,
+ normalization_value_uom VARCHAR,
+ co2_equivalent NUMERIC,
+ co2_equivalent_uom VARCHAR,
+ costs_money NUMERIC,
+ costs_money_uom VARCHAR,
+ yields_money NUMERIC,
+ yields_money_uom VARCHAR,
+-- Attributes for Energy
+ energy_carrier VARCHAR,
+ energy_carrier_codespace VARCHAR,
+ maximum_load NUMERIC,
+ maximum_load_uom VARCHAR,
+ source VARCHAR,
+ source_codespace VARCHAR,
+-- Attributes for Waste
+ is_dangerous NUMERIC,
+ is_recyclable NUMERIC,
+-- FK
+ cityobject_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_schedule
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_schedule (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ library_code VARCHAR,
+ library_code_codespace VARCHAR,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ start_time TIME WITHOUT TIME ZONE,
+ start_day INTEGER,
+ start_month INTEGER,
+ start_year INTEGER,
+ time_interval NUMERIC,
+ time_interval_unit VARCHAR,
+-- time_interval_factor INTEGER, -- used for temporalExtent
+-- time_interval_radix INTEGER, -- used for temporalExtent
+-- DualValue Schedule
+ idle_value NUMERIC,
+ idle_value_uom VARCHAR,
+ usage_value NUMERIC,
+ usage_value_uom VARCHAR,
+ start_usage_time TIME WITHOUT TIME ZONE,
+ end_usage_time TIME WITHOUT TIME ZONE,
+-- Atomic Schedule
+ constant_value NUMERIC,
+ constant_value_uom VARCHAR,
+-- FK
+ time_series_id BIGINT,
+ library_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_schedule_component
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_schedule_component (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ repetitions INTEGER NOT NULL DEFAULT 1,
+ additional_gap NUMERIC,
+ additional_gap_unit VARCHAR,
+-- additional_gap_factor INTEGER,
+-- additional_gap_radix INTEGER,
+-- FK
+ parent_schedule_id BIGINT,
+ schedule_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_solar_collector
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_solar_collector (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ cell_type VARCHAR,
+ cell_type_codespace VARCHAR,
+ module_area NUMERIC,
+ module_area_uom VARCHAR,
+ azimuth NUMERIC,
+ azimuth_uom VARCHAR,
+ inclination NUMERIC,
+ inclination_uom VARCHAR,
+ aperture_area NUMERIC,
+ aperture_area_uom VARCHAR,
+ opt_efficiency NUMERIC,
+ opt_efficiency_uom VARCHAR,
+ lin_heat_loss_coeff NUMERIC,
+ quad_heat_loss_coeff NUMERIC,
+-- FK
+ lod2_multi_surface_id BIGINT,
+ lod3_multi_surface_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_storage_device
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_storage_device (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+ medium VARCHAR,
+ medium_codespace VARCHAR,
+ preparation_temp NUMERIC,
+ preparation_temp_uom VARCHAR,
+ thm_losses_factor NUMERIC,
+ thm_losses_factor_uom VARCHAR,
+ volume NUMERIC,
+ volume_uom VARCHAR,
+ batt_techn VARCHAR,
+ batt_techn_codespace VARCHAR,
+ power_capacity NUMERIC,
+ power_capacity_uom VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_suitability
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_suitability (
+ id BIGINT PRIMARY KEY DEFAULT nextval('ng2_suitability_seq'::regclass),
+ reason VARCHAR,
+ reason_codespace VARCHAR,
+ value NUMERIC,
+ value_uom VARCHAR,
+ description VARCHAR,
+ schedule_id BIGINT,
+-- FK
+ cityobject_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_them_surf_to_thermal_zone
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_them_surf_to_thermal_zone (
+ thematic_surface_id BIGINT NOT NULL,
+ thermal_zone_id BIGINT NOT NULL,
+ PRIMARY KEY (thematic_surface_id, thermal_zone_id)
+);
+
+-- --------------------------------------------------------------------
+-- ng2_thematic_surface - extends (building) thematic_surface table
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_thematic_surface (
+ id BIGINT PRIMARY KEY,
+ total_surf_area NUMERIC,
+ total_surf_area_uom VARCHAR,
+ opaque_surf_area NUMERIC,
+ opaque_surf_area_uom VARCHAR,
+ open_to_surf_ratio NUMERIC,
+ open_to_surf_ratio_uom VARCHAR,
+ thickness NUMERIC,
+ thickness_uom VARCHAR,
+ azimuth NUMERIC,
+ azimuth_uom VARCHAR,
+ inclination NUMERIC,
+ inclination_uom VARCHAR,
+ ground_view_factor NUMERIC,
+ ground_view_factor_uom VARCHAR,
+ sky_view_factor NUMERIC,
+ sky_view_factor_uom VARCHAR,
+ is_adiabatic NUMERIC,
+ heat_capacity NUMERIC,
+ heat_capacity_uom VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_time_series
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_time_series (
+ id BIGINT PRIMARY KEY,
+ objectclass_id INTEGER,
+-- AbstractTieSeries attributes
+ acquisition_method VARCHAR,
+ acquisition_method_codespace VARCHAR,
+ interpolation_type VARCHAR,
+ source VARCHAR,
+-- Other attributes
+ period_begin TIMESTAMP WITH TIME ZONE,
+ period_end TIMESTAMP WITH TIME ZONE,
+ start_time TIME WITHOUT TIME ZONE,
+ start_day INTEGER,
+ start_month INTEGER,
+ temporal_extent NUMERIC,
+ temporal_extent_unit VARCHAR,
+-- temporal_extent_factor INTEGER,
+-- temporal_extent_radix INTEGER,
+ time_interval NUMERIC,
+ time_interval_unit VARCHAR,
+-- time_interval_factor INTEGER,
+-- time_interval_radix INTEGER,
+ values_list TEXT,
+ values_list_uom VARCHAR,
+ uom VARCHAR,
+ file_uri VARCHAR,
+ num_of_header_lines INTEGER,
+ field_separator VARCHAR,
+ record_separator VARCHAR,
+ value_column_number INTEGER,
+ decimal_symbol VARCHAR,
+ auth_type VARCHAR,
+ auth_type_codespace VARCHAR,
+ base_url VARCHAR,
+ connection_type VARCHAR,
+ connection_type_codespace VARCHAR,
+ datastream_id VARCHAR,
+ link_to_observation VARCHAR,
+ link_to_sensor_description VARCHAR,
+ mqtt_server VARCHAR,
+ mqtt_topic VARCHAR,
+ observation_id VARCHAR,
+ observation_property VARCHAR,
+ sensor_id VARCHAR,
+ sensor_name VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_urban_function_area
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_urban_function_area (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ code VARCHAR,
+ code_codespace VARCHAR
+);
+
+-- --------------------------------------------------------------------
+-- ng2_utl_ntw_connection
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_utl_ntw_connection (
+ id BIGINT PRIMARY KEY,
+ network_type VARCHAR,
+ network_type_codespace VARCHAR,
+ connection_status VARCHAR,
+ function_in_network VARCHAR,
+ function_in_network_codespace VARCHAR,
+ usage_in_network VARCHAR,
+ usage_in_network_codespace VARCHAR,
+ network_id VARCHAR,
+ network_node_id VARCHAR,
+-- FK
+ cityobject_id BIGINT
+);
+
+-- --------------------------------------------------------------------
+-- ng2_weather_data
+-- --------------------------------------------------------------------
+CREATE TABLE ng2_weather_data (
+ id BIGINT PRIMARY KEY,
+ type VARCHAR,
+ type_codespace VARCHAR,
+ value_type VARCHAR,
+ value_type_codespace VARCHAR,
+ yearly_value NUMERIC,
+ yearly_value_uom VARCHAR,
+ library_code VARCHAR,
+ library_code_codespace VARCHAR,
+-- FK
+ time_series_id BIGINT,
+ cityobject_id BIGINT,
+--
+ position geometry(POINTZ)
+);
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Create foreign keys ********************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+-- --------------------------------------------------------------------
+-- ng2_address_to_building_unit
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_address_to_building_unit ADD CONSTRAINT ng2_addr_to_bdgu_fk1 FOREIGN KEY (address_id) REFERENCES address (id) ON DELETE CASCADE;
+ALTER TABLE ng2_address_to_building_unit ADD CONSTRAINT ng2_addr_to_bdgu_fk2 FOREIGN KEY (building_unit_id) REFERENCES ng2_building_partition (id) ON DELETE CASCADE;
+
+-- --------------------------------------------------------------------
+-- ng2_building
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_building ADD CONSTRAINT ng2_bdg_fk FOREIGN KEY (id) REFERENCES building (id);
+
+-- --------------------------------------------------------------------
+-- ng2_building_partition
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_lod1_fk FOREIGN KEY (lod1_solid_id) REFERENCES surface_geometry (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_lod2_fk FOREIGN KEY (lod2_solid_id) REFERENCES surface_geometry (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_lod3_fk FOREIGN KEY (lod3_solid_id) REFERENCES surface_geometry (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_uz_fk FOREIGN KEY (usage_zone_id) REFERENCES ng2_building_partition (id) ON DELETE SET NULL;
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_tz_fk FOREIGN KEY (thermal_zone_id) REFERENCES ng2_building_partition (id) ON DELETE SET NULL;
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_bdg_fk FOREIGN KEY (building_id) REFERENCES ng2_building (id);
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_sched_fk1 FOREIGN KEY (cooling_schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_sched_fk2 FOREIGN KEY (heating_schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+ALTER TABLE ng2_building_partition ADD CONSTRAINT ng2_bdgp_sched_fk3 FOREIGN KEY (ventilation_schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_cityobject
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_cityobject ADD CONSTRAINT ng2_cto_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_cityobject ADD CONSTRAINT ng2_cto_lcns_fk FOREIGN KEY (layered_construction_id) REFERENCES ng2_layered_construction (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_ctyobj_relation
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_ctyobj_relation ADD CONSTRAINT ng2_cto_rel_fk2 FOREIGN KEY (cityobject_id) REFERENCES cityobject (id) ON DELETE SET NULL;
+ALTER TABLE ng2_ctyobj_relation ADD CONSTRAINT ng2_cto_rel_fk1 FOREIGN KEY (ng2_cityobject_id) REFERENCES ng2_cityobject (id);
+
+-- --------------------------------------------------------------------
+-- ng2_device
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_device ADD CONSTRAINT ng2_dev_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_device ADD CONSTRAINT ng2_dev_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_device ADD CONSTRAINT ng2_dev_opt_fk FOREIGN KEY (transmittance_id) REFERENCES ng2_optical_property (id) ON DELETE SET NULL;
+ALTER TABLE ng2_device ADD CONSTRAINT ng2_dev_ng2_cto_fk FOREIGN KEY (cityobject_id) REFERENCES ng2_cityobject (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_device_operation
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_device_operation ADD CONSTRAINT ng2_dev_opr_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_device_operation ADD CONSTRAINT ng2_dev_opr_sched_fk FOREIGN KEY (schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+ALTER TABLE ng2_device_operation ADD CONSTRAINT ng2_dev_opr_dev_fk FOREIGN KEY (device_id) REFERENCES ng2_device (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_energy_perf_cert
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_energy_perf_cert ADD CONSTRAINT ng2_epc_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_energy_perf_cert ADD CONSTRAINT ng2_epc_bdg_fk FOREIGN KEY (building_id) REFERENCES ng2_building (id) ON DELETE SET NULL;
+ALTER TABLE ng2_energy_perf_cert ADD CONSTRAINT ng2_epc_bdg_part_fk FOREIGN KEY (building_partition_id) REFERENCES ng2_building_partition (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_layer
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_layer ADD CONSTRAINT ng2_lyr_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_layer ADD CONSTRAINT ng2_lyr_mat_fk FOREIGN KEY (material_id) REFERENCES ng2_material (id) ON DELETE SET NULL;
+ALTER TABLE ng2_layer ADD CONSTRAINT ng2_lyr_lcns_fk FOREIGN KEY (layered_construction_id) REFERENCES ng2_layered_construction (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_layered_construction
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_layered_construction ADD CONSTRAINT ng2_lcns_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_layered_construction ADD CONSTRAINT ng2_lcns_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_layered_construction ADD CONSTRAINT ng2_lcns_lcns_fk FOREIGN KEY (layered_construction_id) REFERENCES ng2_layered_construction (id) ON DELETE SET NULL;
+ALTER TABLE ng2_layered_construction ADD CONSTRAINT ng2_lcns_lib_fk FOREIGN KEY (library_id) REFERENCES ng2_library (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_library
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_library ADD CONSTRAINT ng2_lib_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_library ADD CONSTRAINT ng2_lib_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+
+-- --------------------------------------------------------------------
+-- ng2_material
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_material ADD CONSTRAINT ng2_mat_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_material ADD CONSTRAINT ng2_mat_lib_fk FOREIGN KEY (library_id) REFERENCES ng2_library (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_occupants
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_occupants ADD CONSTRAINT ng2_occ_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_occupants ADD CONSTRAINT ng2_occ_sched_fk FOREIGN KEY (schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+ALTER TABLE ng2_occupants ADD CONSTRAINT ng2_occ_ng2_bdgp_fk FOREIGN KEY (building_partition_id) REFERENCES ng2_building_partition (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_opening
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_opening ADD CONSTRAINT ng2_opn_fk FOREIGN KEY (id) REFERENCES opening (id);
+
+-- --------------------------------------------------------------------
+-- ng2_optical_property
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_optical_property ADD CONSTRAINT ng2_optpty_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_optical_property ADD CONSTRAINT ng2_optpty_lcns_fk FOREIGN KEY (layered_construction_id) REFERENCES ng2_layered_construction (id);
+
+-- --------------------------------------------------------------------
+-- ng2_qualified_attribute
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_qualified_attribute ADD CONSTRAINT ng2_qatt_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_qualified_attribute ADD CONSTRAINT ng2_qatt_bdg_fk FOREIGN KEY (building_id) REFERENCES ng2_building (id);
+ALTER TABLE ng2_qualified_attribute ADD CONSTRAINT ng2_qatt_bdg_part_fk FOREIGN KEY (building_partition_id) REFERENCES ng2_building_partition (id);
+
+-- --------------------------------------------------------------------
+-- ng2_refurbishment_measure
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_refurbishment_measure ADD CONSTRAINT ng2_refurb_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_refurbishment_measure ADD CONSTRAINT ng2_refurb_bdg_fk FOREIGN KEY (building_id) REFERENCES ng2_building (id) ON DELETE SET NULL;
+ALTER TABLE ng2_refurbishment_measure ADD CONSTRAINT ng2_refurb_bdg_part_fk FOREIGN KEY (building_partition_id) REFERENCES ng2_building_partition (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_resource
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_resource ADD CONSTRAINT ng2_res_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_resource ADD CONSTRAINT ng2_res_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_resource ADD CONSTRAINT ng2_res_ts_fk FOREIGN KEY (time_series_id) REFERENCES ng2_time_series (id) ON DELETE SET NULL;
+ALTER TABLE ng2_resource ADD CONSTRAINT ng2_res_cto_fk FOREIGN KEY (cityobject_id) REFERENCES ng2_cityobject (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_schedule
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_schedule ADD CONSTRAINT ng2_sched_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_schedule ADD CONSTRAINT ng2_sched_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_schedule ADD CONSTRAINT ng2_sched_ts_fk FOREIGN KEY (time_series_id) REFERENCES ng2_time_series (id) ON DELETE SET NULL;
+ALTER TABLE ng2_schedule ADD CONSTRAINT ng2_sched_lib_fk FOREIGN KEY (library_id) REFERENCES ng2_library (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_schedule_component
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_schedule_component ADD CONSTRAINT ng2_sched_comp_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_schedule_component ADD CONSTRAINT ng2_sched_comp_sched_fk1 FOREIGN KEY (parent_schedule_id) REFERENCES ng2_schedule (id);
+ALTER TABLE ng2_schedule_component ADD CONSTRAINT ng2_sched_comp_sched_fk2 FOREIGN KEY (schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_solar_collector
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_solar_collector ADD CONSTRAINT ng2_sol_coll_fk FOREIGN KEY (id) REFERENCES ng2_device (id);
+ALTER TABLE ng2_solar_collector ADD CONSTRAINT ng2_sol_coll_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+ALTER TABLE ng2_solar_collector ADD CONSTRAINT ng2_sol_coll_lod2_fk FOREIGN KEY (lod2_multi_surface_id) REFERENCES surface_geometry (id);
+ALTER TABLE ng2_solar_collector ADD CONSTRAINT ng2_sol_coll_lod3_fk FOREIGN KEY (lod3_multi_surface_id) REFERENCES surface_geometry (id);
+
+-- --------------------------------------------------------------------
+-- ng2_storage_device
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_storage_device ADD CONSTRAINT ng2_sto_dev_fk FOREIGN KEY (id) REFERENCES ng2_device (id);
+ALTER TABLE ng2_storage_device ADD CONSTRAINT ng2_sto_dev_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+
+-- --------------------------------------------------------------------
+-- ng2_suitability
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_suitability ADD CONSTRAINT ng2_suit_cto_fk FOREIGN KEY (cityobject_id) REFERENCES ng2_cityobject (id);
+ALTER TABLE ng2_suitability ADD CONSTRAINT ng2_suit_sched_fk FOREIGN KEY (schedule_id) REFERENCES ng2_schedule (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_them_surf_to_thermal_zone
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_them_surf_to_thermal_zone ADD CONSTRAINT ng2_thm_surf_to_tz_fk2 FOREIGN KEY (thermal_zone_id) REFERENCES ng2_building_partition (id);
+ALTER TABLE ng2_them_surf_to_thermal_zone ADD CONSTRAINT ng2_thm_surf_to_tz_fk1 FOREIGN KEY (thematic_surface_id) REFERENCES thematic_surface (id) ON DELETE CASCADE;
+
+-- --------------------------------------------------------------------
+-- ng2_thematic_surface
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_thematic_surface ADD CONSTRAINT ng2_them_surf_fk FOREIGN KEY (id) REFERENCES thematic_surface (id);
+
+-- --------------------------------------------------------------------
+-- ng2_time_series
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_time_series ADD CONSTRAINT ng2_ts_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_time_series ADD CONSTRAINT ng2_ts_oc_fk FOREIGN KEY (objectclass_id) REFERENCES objectclass (id);
+
+-- --------------------------------------------------------------------
+-- ng2_urban_function_area
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_urban_function_area ADD CONSTRAINT ng2_ufa_fk FOREIGN KEY (id) REFERENCES cityobjectgroup (id);
+
+-- --------------------------------------------------------------------
+-- ng2_utl_ntw_connection
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_utl_ntw_connection ADD CONSTRAINT ng2_utl_ntw_con_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_utl_ntw_connection ADD CONSTRAINT ng2_utl_ntw_con_cto_fk FOREIGN KEY (cityobject_id) REFERENCES ng2_cityobject (id) ON DELETE SET NULL;
+
+-- --------------------------------------------------------------------
+-- ng2_weather_data
+-- --------------------------------------------------------------------
+ALTER TABLE ng2_weather_data ADD CONSTRAINT ng2_wth_data_fk FOREIGN KEY (id) REFERENCES cityobject (id);
+ALTER TABLE ng2_weather_data ADD CONSTRAINT ng2_wth_data_ts_fk FOREIGN KEY (time_series_id) REFERENCES ng2_time_series (id) ON DELETE SET NULL;
+ALTER TABLE ng2_weather_data ADD CONSTRAINT ng2_wth_data_ng2_cto_fk FOREIGN KEY (cityobject_id) REFERENCES ng2_cityobject (id) ON DELETE SET NULL;
+
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Create Indexes *************************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+-- --------------------------------------------------------------------
+-- ng2_address_to_building_unit
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_address_to_bdgu_fk1x ON ng2_address_to_building_unit USING btree (address_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_address_to_bdgu_fk2x ON ng2_address_to_building_unit USING btree (building_unit_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_building
+-- --------------------------------------------------------------------
+-- no indices needed
+
+-- --------------------------------------------------------------------
+-- ng2_building_partition
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_bdgp_oc_fkx ON ng2_building_partition USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_sched_fk1x ON ng2_building_partition USING btree (cooling_schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_sched_fk2x ON ng2_building_partition USING btree (heating_schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_sched_fk3x ON ng2_building_partition USING btree (ventilation_schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_uz_fkx ON ng2_building_partition USING btree (usage_zone_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_tz_fkx ON ng2_building_partition USING btree (thermal_zone_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_bdg_fkx ON ng2_building_partition USING btree (building_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_solid1_fkx ON ng2_building_partition USING btree (lod1_solid_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_solid2_fkx ON ng2_building_partition USING btree (lod2_solid_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_bdgp_solid3_fkx ON ng2_building_partition USING btree (lod3_solid_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_cityobject
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_cto_ref_point_spx ON ng2_cityobject USING gist (ref_point);
+CREATE INDEX ng2_cto_lcns_fkx ON ng2_cityobject USING btree (layered_construction_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_ctyobj_relation
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_cto_rel_fk1x ON ng2_ctyobj_relation USING btree (ng2_cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_cto_rel_fk2x ON ng2_ctyobj_relation USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_device
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_dev_oc_fkx ON ng2_device USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_dev_opt_fkx ON ng2_device USING btree (transmittance_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_dev_cto_fkx ON ng2_device USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_device_operation
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_dev_opr_sched_fkx ON ng2_device_operation USING btree (schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_dev_opr_dev_fkx ON ng2_device_operation USING btree (device_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_energy_perf_cert
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_epc_bdg_fkx ON ng2_energy_perf_cert USING btree (building_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_epc_bdg_part_fkx ON ng2_energy_perf_cert USING btree (building_partition_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_layer
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_lyr_mat_fkx ON ng2_layer USING btree (material_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_lyr_lcns_fkx ON ng2_layer USING btree (layered_construction_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_layered_constr
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_lcns_oc_fkx ON ng2_layered_construction USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_lcns_lcns_fkx ON ng2_layered_construction USING btree (layered_construction_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_lcns_lib_fkx ON ng2_layered_construction USING btree (library_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_library
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_lib_oc_fkx ON ng2_library USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_material
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_mat_oc_fkx ON ng2_material USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_mat_lib_fkx ON ng2_material USING btree (library_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_occupants
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_occ_sched_fkx ON ng2_occupants USING btree (schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_occ_ng2_bdgp_fkx ON ng2_occupants USING btree (building_partition_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_opening
+-- --------------------------------------------------------------------
+-- no indices needed
+
+-- --------------------------------------------------------------------
+-- ng2_optical_property
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_optpty_oc_fkx ON ng2_optical_property USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_optpty_lcns_fkx ON ng2_optical_property USING btree (layered_construction_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_qualified_attribute
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_qual_attr_oc_fkx ON ng2_qualified_attribute USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_qual_attr_bdg_fkx ON ng2_qualified_attribute USING btree (building_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_qual_attr_bdg_part_fkx ON ng2_qualified_attribute USING btree (building_partition_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_qual_attr_type_idx ON ng2_qualified_attribute USING btree (type ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_refurbishment_measure
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_ref_meas_bdg_fkx ON ng2_refurbishment_measure USING btree (building_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_ref_meas_bdg_part_fkx ON ng2_refurbishment_measure USING btree (building_partition_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_resource
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_res_oc_fkx ON ng2_resource USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_res_ts_fkx ON ng2_resource USING btree (time_series_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_res_cto_fkx ON ng2_resource USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_schedule
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_sched_oc_fkx ON ng2_schedule USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_sched_ts_fkx ON ng2_schedule USING btree (time_series_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_sched_lib_fkx ON ng2_schedule USING btree (library_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_schedule_component
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_sched_comp_sched_fk1x ON ng2_schedule_component USING btree (parent_schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_sched_comp_sched_fk2x ON ng2_schedule_component USING btree (schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_solar_collector
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_sol_col_oc_fkx ON ng2_solar_collector USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_sol_col_lod2_fkx ON ng2_solar_collector USING btree (lod2_multi_surface_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_sol_col_lod3_fkx ON ng2_solar_collector USING btree (lod2_multi_surface_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_storage_device
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_sto_dev_oc_fkx ON ng2_storage_device USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_suitability
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_suit_cto_fkx ON ng2_suitability USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_suit_sched_fkx ON ng2_suitability USING btree (schedule_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_suit_reas_fkx ON ng2_suitability USING btree (reason ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_them_surf_to_thermal_zone
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_thm_surf_to_tz_fk1x ON ng2_them_surf_to_thermal_zone USING btree (thematic_surface_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_thm_surf_to_tz_fk2x ON ng2_them_surf_to_thermal_zone USING btree (thermal_zone_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_thematic_surface
+-- --------------------------------------------------------------------
+-- no indices needed
+
+-- --------------------------------------------------------------------
+-- ng2_time_series
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_ts_oc_fkx ON ng2_time_series USING btree (objectclass_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_urban_function_area
+-- --------------------------------------------------------------------
+-- no indices needed
+
+-- --------------------------------------------------------------------
+-- ng2_utl_ntw_connection
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_utl_ntw_conn_cto_fkx ON ng2_utl_ntw_connection USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+
+-- --------------------------------------------------------------------
+-- ng2_weather_data
+-- --------------------------------------------------------------------
+CREATE INDEX ng2_wht_data_ts_fkx ON ng2_weather_data USING btree (time_series_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
+CREATE INDEX ng2_wht_data_cto_fkx ON ng2_weather_data USING btree (cityobject_id ASC NULLS LAST) WITH (FILLFACTOR = 90);
diff --git a/resources/database/3dcitydb/postgreSQL/DROP_ADE_DB.sql b/resources/database/3dcitydb/postgreSQL/DROP_ADE_DB.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c4990464412834a4aa8527039aa23917b1df9042
--- /dev/null
+++ b/resources/database/3dcitydb/postgreSQL/DROP_ADE_DB.sql
@@ -0,0 +1,149 @@
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+--
+-- CityGML Energy ADE 2.0 (beta 7)
+--
+-- Last update: 2025-05-09
+--
+-- This DDL script uninstalls the 3DCityDB schema for the Energy ADE 2.0. It must be run
+-- from within the ADE Manager plugin of the 3DCityDB Importer/Exporter.
+--
+-- This script was first automatically generated using the 3DCityDB ADE Manager
+-- and successively edited and restructured by:
+--
+-- Dr. Giorgio Agugiaro
+-- 3D Geoinformation group
+-- Delft University of Technology
+-- The Netherlands
+--
+-- https://3d.bk.tudelft.nl/gagugiaro/
+--
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- ******************************* DROP_ADE_DB.SQL execution START ************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Drop foreign keys **********************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ALTER TABLE ng2_address_to_building_unit DROP CONSTRAINT ng2_addr_to_bdgu_fk1;
+ALTER TABLE ng2_address_to_building_unit DROP CONSTRAINT ng2_addr_to_bdgu_fk2;
+ALTER TABLE ng2_building DROP CONSTRAINT ng2_bdg_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_bdg_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_lod1_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_lod2_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_lod3_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_oc_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_sched_fk1;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_sched_fk2;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_sched_fk3;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_tz_fk;
+ALTER TABLE ng2_building_partition DROP CONSTRAINT ng2_bdgp_uz_fk;
+ALTER TABLE ng2_cityobject DROP CONSTRAINT ng2_cto_fk;
+ALTER TABLE ng2_cityobject DROP CONSTRAINT ng2_cto_lcns_fk;
+ALTER TABLE ng2_ctyobj_relation DROP CONSTRAINT ng2_cto_rel_fk1;
+ALTER TABLE ng2_ctyobj_relation DROP CONSTRAINT ng2_cto_rel_fk2;
+ALTER TABLE ng2_device DROP CONSTRAINT ng2_dev_fk;
+ALTER TABLE ng2_device DROP CONSTRAINT ng2_dev_ng2_cto_fk;
+ALTER TABLE ng2_device DROP CONSTRAINT ng2_dev_oc_fk;
+ALTER TABLE ng2_device DROP CONSTRAINT ng2_dev_opt_fk;
+ALTER TABLE ng2_device_operation DROP CONSTRAINT ng2_dev_opr_fk;
+ALTER TABLE ng2_device_operation DROP CONSTRAINT ng2_dev_opr_dev_fk;
+ALTER TABLE ng2_device_operation DROP CONSTRAINT ng2_dev_opr_sched_fk;
+ALTER TABLE ng2_energy_perf_cert DROP CONSTRAINT ng2_epc_fk;
+ALTER TABLE ng2_energy_perf_cert DROP CONSTRAINT ng2_epc_bdg_fk;
+ALTER TABLE ng2_energy_perf_cert DROP CONSTRAINT ng2_epc_bdg_part_fk;
+ALTER TABLE ng2_layer DROP CONSTRAINT ng2_lyr_fk;
+ALTER TABLE ng2_layer DROP CONSTRAINT ng2_lyr_lcns_fk;
+ALTER TABLE ng2_layer DROP CONSTRAINT ng2_lyr_mat_fk;
+ALTER TABLE ng2_layered_construction DROP CONSTRAINT ng2_lcns_fk;
+ALTER TABLE ng2_layered_construction DROP CONSTRAINT ng2_lcns_lcns_fk;
+ALTER TABLE ng2_layered_construction DROP CONSTRAINT ng2_lcns_oc_fk;
+ALTER TABLE ng2_layered_construction DROP CONSTRAINT ng2_lcns_lib_fk;
+ALTER TABLE ng2_library DROP CONSTRAINT ng2_lib_fk;
+ALTER TABLE ng2_library DROP CONSTRAINT ng2_lib_oc_fk;
+ALTER TABLE ng2_material DROP CONSTRAINT ng2_mat_fk;
+ALTER TABLE ng2_material DROP CONSTRAINT ng2_mat_lib_fk;
+ALTER TABLE ng2_occupants DROP CONSTRAINT ng2_occ_fk;
+ALTER TABLE ng2_occupants DROP CONSTRAINT ng2_occ_ng2_bdgp_fk;
+ALTER TABLE ng2_occupants DROP CONSTRAINT ng2_occ_sched_fk;
+ALTER TABLE ng2_opening DROP CONSTRAINT ng2_opn_fk;
+ALTER TABLE ng2_optical_property DROP CONSTRAINT ng2_optpty_lcns_fk;
+ALTER TABLE ng2_optical_property DROP CONSTRAINT ng2_optpty_oc_fk;
+ALTER TABLE ng2_qualified_attribute DROP CONSTRAINT ng2_qatt_oc_fk;
+ALTER TABLE ng2_qualified_attribute DROP CONSTRAINT ng2_qatt_bdg_fk;
+ALTER TABLE ng2_qualified_attribute DROP CONSTRAINT ng2_qatt_bdg_part_fk;
+ALTER TABLE ng2_refurbishment_measure DROP CONSTRAINT ng2_refurb_fk;
+ALTER TABLE ng2_refurbishment_measure DROP CONSTRAINT ng2_refurb_bdg_fk;
+ALTER TABLE ng2_refurbishment_measure DROP CONSTRAINT ng2_refurb_bdg_part_fk;
+ALTER TABLE ng2_resource DROP CONSTRAINT ng2_res_fk;
+ALTER TABLE ng2_resource DROP CONSTRAINT ng2_res_oc_fk;
+ALTER TABLE ng2_resource DROP CONSTRAINT ng2_res_ts_fk;
+ALTER TABLE ng2_resource DROP CONSTRAINT ng2_res_cto_fk;
+ALTER TABLE ng2_schedule DROP CONSTRAINT ng2_sched_fk;
+ALTER TABLE ng2_schedule DROP CONSTRAINT ng2_sched_oc_fk;
+ALTER TABLE ng2_schedule DROP CONSTRAINT ng2_sched_ts_fk;
+ALTER TABLE ng2_schedule DROP CONSTRAINT ng2_sched_lib_fk;
+ALTER TABLE ng2_schedule_component DROP CONSTRAINT ng2_sched_comp_fk;
+ALTER TABLE ng2_schedule_component DROP CONSTRAINT ng2_sched_comp_sched_fk1;
+ALTER TABLE ng2_schedule_component DROP CONSTRAINT ng2_sched_comp_sched_fk2;
+ALTER TABLE ng2_solar_collector DROP CONSTRAINT ng2_sol_coll_fk;
+ALTER TABLE ng2_solar_collector DROP CONSTRAINT ng2_sol_coll_oc_fk;
+ALTER TABLE ng2_solar_collector DROP CONSTRAINT ng2_sol_coll_lod2_fk;
+ALTER TABLE ng2_solar_collector DROP CONSTRAINT ng2_sol_coll_lod3_fk;
+ALTER TABLE ng2_storage_device DROP CONSTRAINT ng2_sto_dev_fk;
+ALTER TABLE ng2_storage_device DROP CONSTRAINT ng2_sto_dev_oc_fk;
+ALTER TABLE ng2_suitability DROP CONSTRAINT ng2_suit_cto_fk;
+ALTER TABLE ng2_suitability DROP CONSTRAINT ng2_suit_sched_fk;
+ALTER TABLE ng2_them_surf_to_thermal_zone DROP CONSTRAINT ng2_thm_surf_to_tz_fk1;
+ALTER TABLE ng2_them_surf_to_thermal_zone DROP CONSTRAINT ng2_thm_surf_to_tz_fk2;
+ALTER TABLE ng2_thematic_surface DROP CONSTRAINT ng2_them_surf_fk;
+ALTER TABLE ng2_time_series DROP CONSTRAINT ng2_ts_fk;
+ALTER TABLE ng2_time_series DROP CONSTRAINT ng2_ts_oc_fk;
+ALTER TABLE ng2_urban_function_area DROP CONSTRAINT ng2_ufa_fk;
+ALTER TABLE ng2_utl_ntw_connection DROP CONSTRAINT ng2_utl_ntw_con_cto_fk;
+ALTER TABLE ng2_utl_ntw_connection DROP CONSTRAINT ng2_utl_ntw_con_fk;
+ALTER TABLE ng2_weather_data DROP CONSTRAINT ng2_wth_data_fk;
+ALTER TABLE ng2_weather_data DROP CONSTRAINT ng2_wth_data_ng2_cto_fk;
+ALTER TABLE ng2_weather_data DROP CONSTRAINT ng2_wth_data_ts_fk;
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Drop tables ***************************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+DROP TABLE ng2_address_to_building_unit CASCADE;
+DROP TABLE ng2_building CASCADE;
+DROP TABLE ng2_building_partition CASCADE;
+DROP TABLE ng2_cityobject CASCADE;
+DROP TABLE ng2_ctyobj_relation CASCADE;
+DROP TABLE ng2_device CASCADE;
+DROP TABLE ng2_device_operation CASCADE;
+DROP TABLE ng2_energy_perf_cert CASCADE;
+DROP TABLE ng2_layer CASCADE;
+DROP TABLE ng2_layered_construction CASCADE;
+DROP TABLE ng2_library CASCADE;
+DROP TABLE ng2_material CASCADE;
+DROP TABLE ng2_occupants CASCADE;
+DROP TABLE ng2_opening CASCADE;
+DROP TABLE ng2_optical_property CASCADE;
+DROP TABLE ng2_qualified_attribute CASCADE;
+DROP TABLE ng2_refurbishment_measure CASCADE;
+DROP TABLE ng2_resource CASCADE;
+DROP TABLE ng2_schedule CASCADE;
+DROP TABLE ng2_schedule_component CASCADE;
+DROP TABLE ng2_solar_collector CASCADE;
+DROP TABLE ng2_storage_device CASCADE;
+DROP TABLE ng2_suitability CASCADE;
+DROP TABLE ng2_them_surf_to_thermal_zone CASCADE;
+DROP TABLE ng2_thematic_surface CASCADE;
+DROP TABLE ng2_time_series CASCADE;
+DROP TABLE ng2_urban_function_area CASCADE;
+DROP TABLE ng2_utl_ntw_connection CASCADE;
+DROP TABLE ng2_weather_data CASCADE;
+
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+-- *********************************** Drop Sequences *************************************
+-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+DROP SEQUENCE ng2_ctyobj_relation_seq;
+DROP SEQUENCE ng2_optical_property_seq;
+DROP SEQUENCE ng2_qualified_attribute_seq;
+DROP SEQUENCE ng2_suitability_seq;
\ No newline at end of file
diff --git a/resources/database/schema-mapping/schema-mapping.xml b/resources/database/schema-mapping/schema-mapping.xml
new file mode 100644
index 0000000000000000000000000000000000000000..deaf3a84a9e2eff990ab341660f099a40e937874
--- /dev/null
+++ b/resources/database/schema-mapping/schema-mapping.xml
@@ -0,0 +1,1408 @@
+
+
+
+
+ Energy ADE
+ 2.0 beta 7 (2025-06-25)
+ Database schema for the 3DCityDB 4.x
+ ng2
+
+
+
+ http://www.citygml.org/ade/energy/2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..c79eb416dc01045d52947ca2e2e7e4a433adc6ac
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'energy-ade2-citydb'
+includeBuild '../energy-ade2-citygml4j'
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/EnergyADEExtension.java b/src/main/java/de/stuttgart/hft/EnergyADEExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d7fcab7c7ebfc04a505b0a8d68392f70b998c0f
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/EnergyADEExtension.java
@@ -0,0 +1,59 @@
+package de.stuttgart.hft;
+
+import de.stuttgart.hft.ade.energy2.exporter.ExportManager;
+import de.stuttgart.hft.ade.energy2.importer.ImportManager;
+import de.stuttgart.hft.ade.energy2.schema.ObjectMapper;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.ADEExtension;
+import org.citydb.core.ade.ADEExtensionException;
+import org.citydb.core.ade.ADEObjectMapper;
+import org.citydb.core.ade.exporter.ADEExportManager;
+import org.citydb.core.ade.importer.ADEImportManager;
+import org.citydb.core.database.schema.mapping.SchemaMapping;
+import org.citydb.gui.ImpExpLauncher;
+import org.citygml4j.ade.energy.EnergyADEContext;
+import org.citygml4j.model.citygml.ade.binding.ADEContext;
+
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+
+public class EnergyADEExtension extends ADEExtension {
+ private final ObjectMapper objectMapper = new ObjectMapper();
+ private final SchemaMapper schemaMapper = new SchemaMapper();
+ private final EnergyADEContext context = new EnergyADEContext();
+
+ public static void main(String[] args) {
+ EnergyADEExtension adeExtension = new EnergyADEExtension();
+ adeExtension.setBasePath(Paths.get("resources/database").toAbsolutePath());
+ new ImpExpLauncher().withArgs(args)
+ .withADEExtension(adeExtension)
+ .start();
+ }
+
+ @Override
+ public void init(SchemaMapping schemaMapping) throws ADEExtensionException {
+ objectMapper.populateObjectClassIds(schemaMapping);
+ schemaMapper.populateSchemaNames(schemaMapping.getMetadata().getDBPrefix().toLowerCase());
+ }
+
+ @Override
+ public List getADEContexts() {
+ return Collections.singletonList(context);
+ }
+
+ @Override
+ public ADEObjectMapper getADEObjectMapper() {
+ return objectMapper;
+ }
+
+ @Override
+ public ADEImportManager createADEImportManager() {
+ return new ImportManager(this, schemaMapper);
+ }
+
+ @Override
+ public ADEExportManager createADEExportManager() {
+ return new ExportManager(objectMapper, schemaMapper);
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/AbstractQualifiedAttributeExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/AbstractQualifiedAttributeExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..db9a778a121435b3a16d5c8f9a060e4681847f14
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/AbstractQualifiedAttributeExporter.java
@@ -0,0 +1,135 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.database.schema.mapping.ComplexType;
+import org.citydb.core.database.schema.mapping.SchemaMapping;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citydb.core.registry.ObjectRegistry;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.model.gml.basicTypes.Code;
+import org.citygml4j.model.gml.basicTypes.Measure;
+import org.citygml4j.model.gml.base.StringOrRef;
+
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AbstractQualifiedAttributeExporter implements ADEExporter {
+
+ private final PreparedStatement ps;
+ private final CityGMLExportHelper helper;
+ private final ExportManager manager;
+ private final Connection connection;
+ private WeatherDataExporter weatherDataExporter;
+ private ResourceExporter resourceExporter;
+ private String module;
+ private Map> attributeClassMap;
+
+ public AbstractQualifiedAttributeExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.manager = manager;
+ attributeClassMap = new HashMap<>();
+ SchemaMapping schemaMapping = ObjectRegistry.getInstance().getSchemaMapping();
+ ComplexType qualifiedHeightType = schemaMapping.getComplexType("QualifiedHeight", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassIdOfQualifiedHeight = qualifiedHeightType.getObjectClassId();
+ attributeClassMap.put(objectClassIdOfQualifiedHeight, QualifiedHeight.class);
+
+ ComplexType qualifiedAreaType = schemaMapping.getComplexType("QualifiedArea", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassIdOfQualifiedArea = qualifiedAreaType.getObjectClassId();
+ attributeClassMap.put(objectClassIdOfQualifiedArea, QualifiedArea.class);
+
+ ComplexType qualifiedVolumeType = schemaMapping.getComplexType("QualifiedVolume", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassIdOfQualifiedVolume = qualifiedVolumeType.getObjectClassId();
+ attributeClassMap.put(objectClassIdOfQualifiedVolume, QualifiedVolume.class);
+
+ String tableName = helper.getTableNameWithSchema(
+ manager.getSchemaMapper().getTableName(ADETable.QUALIFIED_ATTRIBUTE)
+ );
+
+ String select = "SELECT id, objectclass_id, type, type_codespace, \"value\", value_uom, description, source, building_id, building_partition_id " +
+ "FROM " + tableName + " WHERE building_id = ?";
+
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+ ps = connection.prepareStatement(select);
+ }
+
+ public Collection doExport(long objectId) throws SQLException {
+ ps.setLong(1, objectId);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ Collection result = new ArrayList<>();
+
+ while (rs.next()) {
+ long objectIdFromDB = rs.getLong(1);
+ int objectClassId = rs.getInt(2);
+
+ AbstractQualifiedAttribute attribute = createQualifiedAttribute(objectClassId);
+
+ String descriptionValue = rs.getString(7);
+ if (descriptionValue != null && !descriptionValue.trim().isEmpty()) {
+ StringOrRef description = new StringOrRef();
+ description.setValue(descriptionValue);
+ attribute.setDescription(description);
+ // System.out.println("Set description for QualifiedAttribute id=" + objectIdFromDB + ": " + descriptionValue);
+ }
+
+ if (rs.getString(8) != null)
+ attribute.setSource(rs.getString(8));
+
+ Measure value = new Measure();
+ value.setValue(rs.getDouble(5));
+ value.setUom(rs.getString(6));
+ attribute.setValue(value);
+
+ if (attribute instanceof QualifiedHeight qualifiedHeight) {
+ Code type = new Code();
+ type.setValue(rs.getString(3));
+ type.setCodeSpace(rs.getString(4));
+ qualifiedHeight.setType(type);
+ } else if (attribute instanceof QualifiedArea qualifiedArea) {
+ Code type = new Code();
+ type.setValue(rs.getString(3));
+ type.setCodeSpace(rs.getString(4));
+ qualifiedArea.setType(type);
+ } else if (attribute instanceof QualifiedVolume qualifiedVolume) {
+ Code type = new Code();
+ type.setValue(rs.getString(3));
+ type.setCodeSpace(rs.getString(4));
+ qualifiedVolume.setType(type);
+ }
+
+ result.add(attribute);
+ }
+
+ return result;
+ }
+ }
+
+ private AbstractQualifiedAttribute createQualifiedAttribute(int objectClassId) {
+
+ try {
+ Class extends AbstractQualifiedAttribute> aClass = attributeClassMap.get(objectClassId);
+ return aClass.getDeclaredConstructor().newInstance();
+
+ }catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException exception){
+ throw new IllegalStateException(exception);
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/BuildingPropertiesExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/BuildingPropertiesExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c33d6425f3cd955f1a2726938f678b23138615e
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/BuildingPropertiesExporter.java
@@ -0,0 +1,137 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import net.opengis.gml.CodeType;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.model.citygml.building.AbstractBuilding;
+import org.sig3d.citygml.energyADE2beta7.ThermalStatusValueType;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+public class BuildingPropertiesExporter implements ADEExporter {
+ private final PreparedStatement ps;
+ private final CityGMLExportHelper helper;
+ private final ExportManager manager;
+ private final Connection connection;
+ private final AbstractQualifiedAttributeExporter abstractQualifiedAttributeExporter;
+ private final RefurbishmentMeasureExporter refurbishmentMeasureExporter;
+ private final String module;
+
+ public BuildingPropertiesExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.manager = manager;
+
+ String select = "select id, type, type_codespace, is_protected, constr_weight, constr_weight_codespace, attic_thm_status, basement_thm_status from " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.BUILDING)) +
+ " where id = ?";
+
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+ ps = connection.prepareStatement(select);
+ abstractQualifiedAttributeExporter = manager.getExporter(AbstractQualifiedAttributeExporter.class);
+ refurbishmentMeasureExporter = manager.getExporter(RefurbishmentMeasureExporter.class);
+ }
+
+ public void doExport(AbstractBuilding building, long objectId, AbstractType> objectType, ProjectionFilter projectionFilter) throws SQLException, CityGMLExportException {
+ ps.setLong(1, objectId);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ if (rs.next()) {
+ // Building type
+ if (projectionFilter.containsProperty("buildingType", module)) {
+ String type = rs.getString("type");
+ String typeCodespace = rs.getString("type_codespace");
+ if (type != null || typeCodespace != null) {
+ CodeType bdgType = new CodeType();
+ if (type != null)
+ bdgType.setValue(type);
+ if (typeCodespace != null)
+ bdgType.setCodeSpace(typeCodespace);
+ BuildingTypeProperty buildingTypeProperty = new BuildingTypeProperty();
+ buildingTypeProperty.setValue(bdgType);
+ building.addGenericApplicationPropertyOfAbstractBuilding(buildingTypeProperty);
+ }
+ }
+
+ // Is protected
+ if (projectionFilter.containsProperty("isProtected", module)) {
+ int isProtected = rs.getInt("is_protected");
+ boolean wasNull = rs.wasNull();
+ Boolean isProtectedValue = wasNull ? false : (isProtected == 1);
+ BuildingIsProtectedProperty buildingIsProtectedProperty = new BuildingIsProtectedProperty();
+ buildingIsProtectedProperty.setValue(isProtectedValue);
+ building.addGenericApplicationPropertyOfAbstractBuilding(buildingIsProtectedProperty);
+ }
+
+ // Construction weight
+ if (projectionFilter.containsProperty("constructionWeight", module)) {
+ String constrWeightValue = rs.getString("constr_weight");
+ String constrWeightCodeSpace = rs.getString("constr_weight_codespace");
+ if (constrWeightValue != null || constrWeightCodeSpace != null) {
+ CodeType constrWeight = new CodeType();
+ constrWeight.setValue(constrWeightValue);
+ constrWeight.setCodeSpace(constrWeightCodeSpace);
+ BuildingConstructionWeightProperty buildingConstructionWeightProperty = new BuildingConstructionWeightProperty();
+ buildingConstructionWeightProperty.setValue(constrWeight);
+ building.addGenericApplicationPropertyOfAbstractBuilding(buildingConstructionWeightProperty);
+ }
+ }
+
+ // Attic thermal status
+ if (projectionFilter.containsProperty("atticThermalStatus", module)) {
+ String atticThmStatusValue = rs.getString("attic_thm_status");
+ if (atticThmStatusValue != null) {
+ ThermalStatusValueType thermalStatusValue = ThermalStatusValueType.fromValue(atticThmStatusValue);
+ BuildingAtticThermalStatusProperty buildingAtticThmStatusProperty = new BuildingAtticThermalStatusProperty();
+ buildingAtticThmStatusProperty.setValue(thermalStatusValue);
+ building.addGenericApplicationPropertyOfAbstractBuilding(buildingAtticThmStatusProperty);
+ }
+ }
+
+ // Basement thermal status
+ if (projectionFilter.containsProperty("basementThermalStatus", module)) {
+ String basementThmStatusValue = rs.getString("basement_thm_status");
+ if (basementThmStatusValue != null) {
+ ThermalStatusValueType thermalStatusValueType = ThermalStatusValueType.fromValue(basementThmStatusValue);
+ BuildingBasementThermalStatusProperty buildingBasementThermalStatusProperty = new BuildingBasementThermalStatusProperty();
+ buildingBasementThermalStatusProperty.setValue(thermalStatusValueType);
+ building.addGenericApplicationPropertyOfAbstractBuilding(buildingBasementThermalStatusProperty);
+ }
+ }
+
+ // Refurbishment measures
+ if (projectionFilter.containsProperty("refurbishmentMeasure", module)) {
+ Collection refurbProps = refurbishmentMeasureExporter.doExport(objectId, objectType, projectionFilter);
+ for (RefurbishmentMeasureProperty refurbProp : refurbProps) {
+ building.addGenericApplicationPropertyOfAbstractBuilding(refurbProp);
+ }
+ }
+
+ // Qualified attributes
+ if (projectionFilter.containsProperty("qualifiedAttribute", module)) {
+ for (AbstractQualifiedAttribute qualifiedAttribute : abstractQualifiedAttributeExporter.doExport(objectId)) {
+ AbstractQualifiedAttributeProperty property = new AbstractQualifiedAttributeProperty(qualifiedAttribute);
+ building.addGenericApplicationPropertyOfAbstractBuilding(property);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ abstractQualifiedAttributeExporter.close();
+ refurbishmentMeasureExporter.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/CityObjectPropertiesExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/CityObjectPropertiesExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..5809304811b478c49b1998d0a0448af5d7d5274b
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/CityObjectPropertiesExporter.java
@@ -0,0 +1,91 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.model.citygml.core.AbstractCityObject;
+import org.citygml4j.model.gml.geometry.primitives.PointProperty;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class CityObjectPropertiesExporter implements ADEExporter {
+
+ private final PreparedStatement ps;
+ private final CityGMLExportHelper helper;
+ private final ExportManager manager;
+ private final Connection connection;
+ private WeatherDataExporter weatherDataExporter;
+ private ResourceExporter resourceExporter;
+ private String module;
+
+ public CityObjectPropertiesExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.manager = manager;
+
+ String select = "select id, ref_point from " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.CITYOBJECT)) +
+ " where id = ?";
+
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+ ps = connection.prepareStatement(select);
+
+ weatherDataExporter = manager.getExporter(WeatherDataExporter.class);
+ resourceExporter = manager.getExporter(ResourceExporter.class);
+ }
+
+ public Collection doExport(AbstractCityObject cityObject, long objectId, AbstractType> objectType, ProjectionFilter projectionFilter) throws SQLException {
+ ps.setLong(1, objectId);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ Collection result = new ArrayList<>();
+ while (rs.next()) {
+ Object pointObj = rs.getObject(2);
+ if (projectionFilter.containsProperty("weatherData", module)) {
+ for (WeatherData weatherData : weatherDataExporter.doExport(objectId)) {
+ WeatherDataProperty property = new WeatherDataProperty(weatherData);
+ cityObject.addGenericApplicationPropertyOfCityObject(property);
+ }
+ }
+
+ if (projectionFilter.containsProperty("resource", module)) {
+ for (AbstractResource resource : resourceExporter.doExport(objectId)) {
+ AbstractResourceProperty property = new AbstractResourceProperty(resource);
+ cityObject.addGenericApplicationPropertyOfCityObject(property);
+ }
+ }
+
+ if (pointObj != null) {
+ GeometryObject pointObject = helper.getDatabaseAdapter().getGeometryConverter().getPoint(pointObj);
+ if (pointObject != null) {
+ PointProperty point = helper.getGMLConverter().getPointProperty(pointObject , false);
+ ReferencePointProperty referencePointProperty = new ReferencePointProperty(point);
+ cityObject.getGenericApplicationPropertyOfCityObject().add(referencePointProperty);
+ }
+ }
+
+ result.add(cityObject);
+ }
+ return result;
+ } catch (CityGMLExportException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ExportManager.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ExportManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..057d069ccd1132ec88ba32e239f2aee3f8a3e457
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ExportManager.java
@@ -0,0 +1,146 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.exporter;
+
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.ObjectMapper;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.exporter.ADEExportManager;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.database.schema.mapping.FeatureType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.core.AbstractResource;
+import org.citygml4j.ade.energy.model.core.QualifiedHeight;
+import org.citygml4j.ade.energy.model.core.WeatherData;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.citygml.ade.binding.ADEModelObject;
+import org.citygml4j.model.citygml.building.AbstractBuilding;
+import org.citygml4j.model.citygml.core.AbstractCityObject;
+import org.citygml4j.model.gml.feature.AbstractFeature;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ExportManager implements ADEExportManager {
+ private final Map, ADEExporter> exporters;
+ private final ObjectMapper objectMapper;
+ private final SchemaMapper schemaMapper;
+
+ private Connection connection;
+ private CityGMLExportHelper helper;
+
+ public ExportManager(ObjectMapper objectMapper, SchemaMapper schemaMapper) {
+ this.objectMapper = objectMapper;
+ this.schemaMapper = schemaMapper;
+ exporters = new HashMap<>();
+ }
+
+ @Override
+ public void init(Connection connection, CityGMLExportHelper helper) throws CityGMLExportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ }
+
+ @Override
+ public void exportObject(ADEModelObject object, long objectId, AbstractObjectType> objectType, ProjectionFilter projectionFilter) throws CityGMLExportException, SQLException {
+ if (object instanceof WeatherStation)
+ getExporter(WeatherStationExporter.class).doExport((WeatherStation) object, objectId, objectType, projectionFilter);
+ else if (object instanceof WeatherData)
+ getExporter(WeatherDataExporter.class).doExport(objectId);
+ else if (object instanceof UrbanFunctionArea)
+ getExporter(UrbanFunctionAreaExporter.class).doExport((UrbanFunctionArea) object, objectId, objectType, projectionFilter);
+ else if (object instanceof AbstractTimeSeries)
+ getExporter(TimeSeriesExporter.class).doExport(objectId);
+ else if (object instanceof AbstractResource)
+ getExporter(ResourceExporter.class).doExport(objectId);
+ }
+
+ @Override
+ public void exportGenericApplicationProperties(String adeHookTable, AbstractFeature parent, long parentId, FeatureType parentType, ProjectionFilter projectionFilter) throws CityGMLExportException, SQLException {
+ if (adeHookTable.equals(schemaMapper.getTableName(ADETable.TIME_SERIES)) && parent instanceof AbstractTimeSeries)
+ getExporter(TimeSeriesExporter.class).doExport(parentId);
+ else if (adeHookTable.equals(schemaMapper.getTableName(ADETable.CITYOBJECT)) && parent instanceof AbstractCityObject)
+ getExporter(CityObjectPropertiesExporter.class).doExport((AbstractCityObject) parent, parentId, parentType, projectionFilter);
+ else if (adeHookTable.equals(schemaMapper.getTableName(ADETable.RESOURCE)) && parent instanceof AbstractResource)
+ getExporter(ResourceExporter.class).doExport(parentId);
+ else if (adeHookTable.equals(schemaMapper.getTableName(ADETable.BUILDING)) && parent instanceof AbstractBuilding)
+ getExporter(BuildingPropertiesExporter.class).doExport((AbstractBuilding) parent, parentId, parentType, projectionFilter);
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ for (ADEExporter exporter : exporters.values())
+ exporter.close();
+ }
+
+ protected ObjectMapper getObjectMapper() {
+ return objectMapper;
+ }
+
+ protected SchemaMapper getSchemaMapper() {
+ return schemaMapper;
+ }
+
+ protected T getExporter(Class type) throws CityGMLExportException, SQLException {
+ ADEExporter exporter = exporters.get(type);
+
+ if (exporter == null) {
+ if (type == TimeSeriesExporter.class)
+ exporter = new TimeSeriesExporter(connection, helper, this);
+ else if (type == UrbanFunctionAreaExporter.class)
+ exporter = new UrbanFunctionAreaExporter(connection, helper, this);
+ else if (type == WeatherStationExporter.class)
+ exporter = new WeatherStationExporter(connection, helper, this);
+ else if (type == ResourceExporter.class)
+ exporter = new ResourceExporter(connection, helper, this);
+ else if (type == WeatherDataExporter.class)
+ exporter = new WeatherDataExporter(connection, helper, this);
+ else if (type == CityObjectPropertiesExporter.class)
+ exporter = new CityObjectPropertiesExporter(connection, helper, this);
+ else if (type == BuildingPropertiesExporter.class)
+ exporter = new BuildingPropertiesExporter(connection, helper, this);
+ else if (type == AbstractQualifiedAttributeExporter.class)
+ exporter = new AbstractQualifiedAttributeExporter(connection, helper, this);
+ else if (type == RefurbishmentMeasureExporter.class)
+ exporter = new RefurbishmentMeasureExporter(connection, helper, this);
+ if (exporter == null)
+ throw new SQLException("Failed to build ADE exporter of type " + type.getName() + ".");
+
+ exporters.put(type, exporter);
+ }
+
+ return type.cast(exporter);
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/RefurbishmentMeasureExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/RefurbishmentMeasureExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1306ce9c07dd17090d9a5e98be50f6e1093c5ef
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/RefurbishmentMeasureExporter.java
@@ -0,0 +1,152 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.core.RefurbishmentMeasure;
+import org.citygml4j.ade.energy.model.core.RefurbishmentMeasureProperty;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.model.gml.basicTypes.Code;
+import org.citygml4j.model.gml.base.StringOrRef;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.GregorianCalendar;
+
+public class RefurbishmentMeasureExporter implements ADEExporter {
+ private final PreparedStatement ps;
+ private final PreparedStatement cityObjectPs;
+ private final CityGMLExportHelper helper;
+ private final ExportManager manager;
+ private final Connection connection;
+ private final String module;
+
+ public RefurbishmentMeasureExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.manager = manager;
+
+ String select = "SELECT id, type, type_codespace, start_date, end_date, library_code, library_code_codespace, building_id, building_partition_id FROM " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.REFURBISHMENT_MEASURE)) +
+ " WHERE building_id = ?";
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+ ps = connection.prepareStatement(select);
+
+ // Prepare statement for cityobject table
+ String cityObjectSelect = "SELECT gmlid, description FROM " +
+ helper.getTableNameWithSchema("cityobject") +
+ " WHERE id = ?";
+ cityObjectPs = connection.prepareStatement(cityObjectSelect);
+ }
+
+ public Collection doExport(long objectId, AbstractType> objectType, ProjectionFilter projectionFilter) throws SQLException {
+ ps.setLong(1, objectId); // Set the building_id parameter
+ Collection result = new ArrayList<>();
+
+ try (ResultSet rs = ps.executeQuery()) {
+ while (rs.next()) {
+ long refurbId = rs.getLong("id");
+ RefurbishmentMeasure refurbishmentMeasure = new RefurbishmentMeasure();
+
+ // Fetch gmlid and description from cityobject
+ cityObjectPs.setLong(1, refurbId);
+ try (ResultSet cityObjectRs = cityObjectPs.executeQuery()) {
+ if (cityObjectRs.next()) {
+ String gmlId = cityObjectRs.getString("gmlid");
+ if (!cityObjectRs.wasNull()) {
+ refurbishmentMeasure.setId(gmlId);
+ }
+ String description = cityObjectRs.getString("description");
+ if (!cityObjectRs.wasNull()) {
+ StringOrRef descriptionType = new StringOrRef();
+ descriptionType.setValue(description);
+ refurbishmentMeasure.setDescription(descriptionType);
+ }
+ }
+ }
+
+ // Set type
+ if (projectionFilter.containsProperty("type", module)) {
+ String type = rs.getString("type");
+ String typeCodespace = rs.getString("type_codespace");
+ if (type != null || typeCodespace != null) {
+ Code refMeasureType = new Code();
+ if (type != null) {
+ refMeasureType.setValue(type);
+ }
+ if (typeCodespace != null) {
+ refMeasureType.setCodeSpace(typeCodespace);
+ }
+ refurbishmentMeasure.setType(refMeasureType);
+ }
+ }
+
+ // Set start date
+ if (projectionFilter.containsProperty("startDate", module)) {
+ Date start_date = rs.getDate("start_date");
+ if (start_date != null) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(start_date);
+ XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
+ //xmlCal.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
+ refurbishmentMeasure.setStartDate(xmlCal);
+ }
+ }
+
+ // Set end date
+ if (projectionFilter.containsProperty("endDate", module)) {
+ Date end_date = rs.getDate("end_date");
+ if (end_date != null) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(end_date);
+ XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
+ // xmlCal.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
+ refurbishmentMeasure.setEndDate(xmlCal);
+ }
+ }
+
+ // Set library code
+ if (projectionFilter.containsProperty("libraryCode", module)) {
+ String library_code = rs.getString("library_code");
+ String library_code_codespace = rs.getString("library_code_codespace");
+ if (library_code != null || library_code_codespace != null) {
+ Code library = new Code();
+ if (library_code != null) {
+ library.setValue(library_code);
+ }
+ if (library_code_codespace != null) {
+ library.setCodeSpace(library_code_codespace);
+ }
+ refurbishmentMeasure.setLibraryCode(library);
+ }
+ }
+
+ // Wrap in RefurbishmentMeasureProperty
+ RefurbishmentMeasureProperty refurbProp = new RefurbishmentMeasureProperty();
+ refurbProp.setRefurbishmentMeasure(refurbishmentMeasure);
+ result.add(refurbProp);
+ }
+ return result;
+ } catch (DatatypeConfigurationException e) {
+ throw new SQLException("Failed to convert date: " + e.getMessage(), e);
+ } catch (SQLException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ cityObjectPs.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ResourceExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ResourceExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a8d8387df936201d802a3cde3b1ff227407013d
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/ResourceExporter.java
@@ -0,0 +1,322 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.ObjectType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.core.AbstractResource;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.gml.basicTypes.Code;
+import org.citygml4j.model.gml.basicTypes.Measure;
+import org.sig3d.citygml.energyADE2beta7.ResourceStatusValueType;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class ResourceExporter implements ADEExporter {
+ private final CityGMLExportHelper helper;
+ private TimeSeriesExporter timeSeriesExporter;
+ private PreparedStatement ps;
+
+ public ResourceExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager)
+ throws CityGMLExportException, SQLException {
+ this.helper = helper;
+ String tableName = helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.RESOURCE));
+ String sql = "SELECT " + getColumnNames() + " FROM " + tableName + " WHERE cityobject_id = ?";
+ ps = connection.prepareStatement(sql);
+ timeSeriesExporter = manager.getExporter(TimeSeriesExporter.class);
+ }
+
+ public Collection doExport(long cityObjectId) throws CityGMLExportException, SQLException {
+ ps.setLong(1, cityObjectId);
+ try (ResultSet rs = ps.executeQuery()) {
+ Collection result = new ArrayList<>();
+ while (rs.next()) {
+ long objectId = rs.getLong(1);
+ int objectClassId = rs.getInt(2);
+ if (rs.wasNull()) {
+ continue;
+ }
+
+ AbstractResource resource = helper.createObject(objectId, objectClassId, AbstractResource.class);
+ if (resource == null) {
+ helper.logOrThrowErrorMessage("Failed to instantiate " + helper.getObjectSignature(objectClassId, cityObjectId) + " as resource object.");
+ continue;
+ }
+
+ ObjectType objectType = helper.getObjectType(objectClassId);
+ ProjectionFilter projectionFilter = helper.getProjectionFilter(objectType);
+
+ // Set AbstractResource properties
+ String statusValue = rs.getString(7);
+ if (statusValue != null) {
+ resource.setStatus(ResourceStatusValueType.fromValue(statusValue));
+ }
+
+ String operationValue = rs.getString(8);
+ String operationCodeSpace = rs.getString(9);
+ if (operationValue != null || operationCodeSpace != null) {
+ Code operationType = new Code();
+ operationType.setValue(operationValue);
+ operationType.setCodeSpace(operationCodeSpace);
+ resource.setOperationType(operationType);
+ }
+
+ String amountValue = rs.getString(11);
+ String amountCodeSpace = rs.getString(12);
+ if (amountValue != null || amountCodeSpace != null) {
+ Code amountType = new Code();
+ amountType.setValue(amountValue);
+ amountType.setCodeSpace(amountCodeSpace);
+ resource.setAmountType(amountType);
+ }
+
+ double amountVal = rs.getDouble(13);
+ if (!rs.wasNull()) {
+ Measure amount = new Measure();
+ amount.setValue(amountVal);
+ String uom = rs.getString(14);
+ if (uom != null) {
+ amount.setUom(uom);
+ }
+ amount.setParent(resource);
+ resource.setAmount(amount);
+ }
+
+ int normalized = rs.getInt(16);
+ if (!rs.wasNull()) {
+ resource.setAmountNormalized(normalized == 1);
+ }
+
+ String normalizationParam = rs.getString(17);
+ if (normalizationParam != null) {
+ resource.setNormalizationParameter(normalizationParam);
+ }
+
+ double normVal = rs.getDouble(18);
+ if (!rs.wasNull()) {
+ Measure normalizationValue = new Measure();
+ normalizationValue.setParent(resource);
+ normalizationValue.setValue(normVal);
+ String uom = rs.getString(19);
+ if (uom != null) {
+ normalizationValue.setUom(uom);
+ }
+ resource.setNormalizationValue(normalizationValue);
+ }
+
+ double co2Val = rs.getDouble(20);
+ if (!rs.wasNull()) {
+ Measure co2Equivalent = new Measure();
+ co2Equivalent.setValue(co2Val);
+ String uom = rs.getString(21);
+ if (uom != null) {
+ co2Equivalent.setUom(uom);
+ }
+ resource.setCo2Equivalent(co2Equivalent);
+ }
+
+ int year = rs.getInt(10);
+ if (!rs.wasNull()) {
+ resource.setYear(year);
+ }
+
+ double costVal = rs.getDouble(22);
+ if (!rs.wasNull()) {
+ Measure costsMoney = new Measure();
+ costsMoney.setValue(costVal);
+ String uom = rs.getString(23);
+ if (uom != null) {
+ costsMoney.setUom(uom);
+ }
+ resource.setCostsMoney(costsMoney);
+ }
+
+ double yieldVal = rs.getDouble(24);
+ if (!rs.wasNull()) {
+ Measure yieldsMoney = new Measure();
+ yieldsMoney.setValue(yieldVal);
+ String uom = rs.getString(25);
+ if (uom != null) {
+ yieldsMoney.setUom(uom);
+ }
+ resource.setYieldsMoney(yieldsMoney);
+ }
+
+ long timeSeriesId = rs.getLong(15);
+ if (timeSeriesId != 0 && timeSeriesExporter != null) {
+ Collection timeSeries = timeSeriesExporter.doExport(timeSeriesId);
+ if (timeSeries != null && !timeSeries.isEmpty()) {
+ AbstractTimeSeries firstSeries = timeSeries.iterator().next();
+ if (firstSeries != null) {
+ resource.setTimeDependentAmount(new AbstractTimeSeriesProperty(firstSeries));
+ }
+ }
+ }
+
+ if (resource instanceof Energy) {
+ Energy energy = (Energy) resource;
+ String energyType = rs.getString(3);
+ String energyTypeCodeSpace = rs.getString(4);
+ if (energyType != null || energyTypeCodeSpace != null) {
+ Code energyTypeValue = new Code();
+ energyTypeValue.setValue(energyType);
+ energyTypeValue.setCodeSpace(energyTypeCodeSpace);
+ energy.setEnergyTypeValue(energyTypeValue);
+ }
+ String energyEndUse = rs.getString(5);
+ String energyEndUseCodeSpace = rs.getString(6);
+ if (energyEndUse != null || energyEndUseCodeSpace != null) {
+ Code energyEndUseValue = new Code();
+ energyEndUseValue.setValue(energyEndUse);
+ energyEndUseValue.setCodeSpace(energyEndUseCodeSpace);
+ energy.setEnergyEndUseValue(energyEndUseValue);
+ }
+ String energyCarrier = rs.getString(26);
+ String energyCarrierCodeSpace = rs.getString(27);
+ if (energyCarrier != null || energyCarrierCodeSpace != null) {
+ Code energyCarrierValue = new Code();
+ energyCarrierValue.setValue(energyCarrier);
+ energyCarrierValue.setCodeSpace(energyCarrierCodeSpace);
+ energy.setEnergyCarrierValue(energyCarrierValue);
+ }
+ double maxLoadVal = rs.getDouble(28);
+ if (!rs.wasNull()) {
+ Measure maximumLoad = new Measure();
+ maximumLoad.setValue(maxLoadVal);
+ String uom = rs.getString(29);
+ if (uom != null) {
+ maximumLoad.setUom(uom);
+ }
+ energy.setMaximumLoad(maximumLoad);
+ }
+ String energySource = rs.getString(30);
+ String energySourceCodeSpace = rs.getString(31);
+ if (energySource != null || energySourceCodeSpace != null) {
+ Code energySourceValue = new Code();
+ energySourceValue.setValue(energySource);
+ energySourceValue.setCodeSpace(energySourceCodeSpace);
+ energy.setEnergySourceValue(energySourceValue);
+ }
+ } else if (resource instanceof Water) {
+ Water water = (Water) resource;
+ String waterType = rs.getString(3);
+ String waterTypeCodeSpace = rs.getString(4);
+ if (waterType != null || waterTypeCodeSpace != null) {
+ Code waterTypeValue = new Code();
+ waterTypeValue.setValue(waterType);
+ waterTypeValue.setCodeSpace(waterTypeCodeSpace);
+ water.setWaterTypeValue(waterTypeValue);
+ }
+ String waterEndUse = rs.getString(5);
+ String waterEndUseCodeSpace = rs.getString(6);
+ if (waterEndUse != null || waterEndUseCodeSpace != null) {
+ Code waterEndUseValue = new Code();
+ waterEndUseValue.setValue(waterEndUse);
+ waterEndUseValue.setCodeSpace(waterEndUseCodeSpace);
+ water.setWaterEndUseValue(waterEndUseValue);
+ }
+ } else if (resource instanceof Waste) {
+ Waste waste = (Waste) resource;
+ String wasteType = rs.getString(3);
+ String wasteTypeCodeSpace = rs.getString(4);
+ if (wasteType != null || wasteTypeCodeSpace != null) {
+ Code wasteTypeValue = new Code();
+ wasteTypeValue.setValue(wasteType);
+ wasteTypeValue.setCodeSpace(wasteTypeCodeSpace);
+ waste.setWasteTypeValue(wasteTypeValue);
+ }
+ String wasteEndUse = rs.getString(5);
+ String wasteEndUseCodeSpace = rs.getString(6);
+ if (wasteEndUse != null || wasteEndUseCodeSpace != null) {
+ Code wasteEndUseValue = new Code();
+ wasteEndUseValue.setValue(wasteEndUse);
+ wasteEndUseValue.setCodeSpace(wasteEndUseCodeSpace);
+ waste.setWasteEndUseValue(wasteEndUseValue);
+ }
+ int isDangerous = rs.getInt(32);
+ if (!rs.wasNull()) {
+ waste.setAmountNormalized(isDangerous == 1);
+ }
+ int recyclable = rs.getInt(33);
+ if (!rs.wasNull()) {
+ waste.setRecyclable(recyclable == 1);
+ }
+ } else if (resource instanceof ConstructionMaterial) {
+ ConstructionMaterial cm = (ConstructionMaterial) resource;
+ String type = rs.getString(3);
+ String typeCodeSpace = rs.getString(4);
+ if (type != null || typeCodeSpace != null) {
+ Code typeValue = new Code();
+ typeValue.setValue(type);
+ typeValue.setCodeSpace(typeCodeSpace);
+ cm.setConstructionMaterialTypeValue(typeValue);
+ }
+ String endUse = rs.getString(5);
+ String endUseCodeSpace = rs.getString(6);
+ if (endUse != null || endUseCodeSpace != null) {
+ Code endUseValue = new Code();
+ endUseValue.setValue(endUse);
+ endUseValue.setCodeSpace(endUseCodeSpace);
+ cm.setConstructionMaterialEndUseValue(endUseValue);
+ }
+ } else if (resource instanceof Food) {
+ Food food = (Food) resource;
+ String foodType = rs.getString(3);
+ String foodTypeCodeSpace = rs.getString(4);
+ if (foodType != null || foodTypeCodeSpace != null) {
+ Code foodTypeValue = new Code();
+ foodTypeValue.setValue(foodType);
+ foodTypeValue.setCodeSpace(foodTypeCodeSpace);
+ food.setFoodTypeValue(foodTypeValue);
+ }
+ String foodEndUse = rs.getString(5);
+ String foodEndUseCodeSpace = rs.getString(6);
+ if (foodEndUse != null || foodEndUseCodeSpace != null) {
+ Code foodEndUseValue = new Code();
+ foodEndUseValue.setValue(foodEndUse);
+ foodEndUseValue.setCodeSpace(foodEndUseCodeSpace);
+ food.setFoodEndUseValue(foodEndUseValue);
+ }
+ } else if (resource instanceof OtherResource) {
+ OtherResource other = (OtherResource) resource;
+ String otherType = rs.getString(3);
+ String otherTypeCodeSpace = rs.getString(4);
+ if (otherType != null || otherTypeCodeSpace != null) {
+ Code otherTypeValue = new Code();
+ otherTypeValue.setValue(otherType);
+ otherTypeValue.setCodeSpace(otherTypeCodeSpace);
+ other.setOtherResourceTypeValue(otherTypeValue);
+ }
+ String otherEndUse = rs.getString(5);
+ String otherEndUseCS = rs.getString(6);
+ if (otherEndUse != null || otherEndUseCS != null) {
+ Code otherEndUseValue = new Code();
+ otherEndUseValue.setValue(otherEndUse);
+ otherEndUseValue.setCodeSpace(otherEndUseCS);
+ other.setOtherResourceEndUseValue(otherEndUseValue);
+ }
+ }
+ result.add(resource);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+
+ private String getColumnNames() {
+ return "id, objectclass_id, type, type_codespace, enduse, enduse_codespace, status, operation_type," +
+ " operation_type_codespace, year, amount_type, amount_type_codespace, amount, " +
+ "amount_uom, time_series_id, is_amount_normalized, normalization_param, normalization_value, " +
+ "normalization_value_uom, co2_equivalent, co2_equivalent_uom, costs_money, costs_money_uom, " +
+ "yields_money, yields_money_uom, energy_carrier, energy_carrier_codespace, maximum_load, " +
+ "maximum_load_uom, source, source_codespace, is_dangerous, is_recyclable, cityobject_id";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/TimeSeriesExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/TimeSeriesExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d79a6c83b36ef3545cc427d36256a7d30c10302
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/TimeSeriesExporter.java
@@ -0,0 +1,411 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.gml.basicTypes.Code;
+import org.citygml4j.model.gml.basicTypes.MeasureList;
+
+import java.net.URI;
+import java.sql.*;
+import java.time.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class TimeSeriesExporter implements ADEExporter {
+
+ private final CityGMLExportHelper helper;
+ private AbstractTimeSeries abstractTimeSeries;
+ private PreparedStatement ps;
+
+ public TimeSeriesExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager)
+ throws CityGMLExportException, SQLException {
+ this.helper = helper;
+ String tableName = helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.TIME_SERIES));
+ String sql = "SELECT " + getColumnNames() + " FROM " + tableName + " WHERE id = ?";
+ ps = connection.prepareStatement(sql);
+ }
+
+ public Collection doExport(long objectId) throws CityGMLExportException, SQLException {
+ ps.setLong(1, objectId);
+ try (ResultSet rs = ps.executeQuery()) {
+ Collection result = new ArrayList<>();
+ while (rs.next()) {
+ long timeSeriesId = rs.getLong(1);
+ int abstractTimeSeriesObjectClassId = rs.getInt(2);
+ if (rs.wasNull()) {
+ continue;
+ }
+
+ abstractTimeSeries = helper.createObject(timeSeriesId, abstractTimeSeriesObjectClassId, AbstractTimeSeries.class);
+ if (abstractTimeSeries == null) {
+ helper.logOrThrowErrorMessage("Failed to instantiate " + helper.getObjectSignature(abstractTimeSeriesObjectClassId, timeSeriesId) + " as time series object.");
+ continue;
+ }
+
+ // Set AbstractTimeSeries properties
+ String acquisition_method = rs.getString(3);
+ String acquisition_method_codespace = rs.getString(4);
+ if (acquisition_method != null || acquisition_method_codespace != null) {
+ Code aqmtd = new Code();
+ aqmtd.setParent(abstractTimeSeries);
+ aqmtd.setValue(acquisition_method);
+ aqmtd.setCodeSpace(acquisition_method_codespace);
+ abstractTimeSeries.setAcquisitionMethod(aqmtd);
+ }
+
+ String interpolation_type = rs.getString(5);
+ if (interpolation_type != null) {
+ abstractTimeSeries.setInterpolationTypeValue(InterpolationTypeValue.fromValue(interpolation_type));
+ }
+
+ String source = rs.getString(6);
+ if (source != null) {
+ abstractTimeSeries.setSource(source);
+ }
+
+ if (abstractTimeSeries instanceof RegularTimeSeries) {
+ RegularTimeSeries regularTimeSeries = (RegularTimeSeries) abstractTimeSeries;
+ Timestamp period_begin = rs.getTimestamp(7);
+ Timestamp period_end = rs.getTimestamp(8);
+
+ if (period_begin != null && period_end != null) {
+ ZoneId zoneId = ZoneId.systemDefault();
+ ZonedDateTime beginZdt = period_begin.toInstant().atZone(zoneId);
+ ZonedDateTime endZdt = period_end.toInstant().atZone(zoneId);
+
+ TimePeriod timePeriod = new TimePeriod();
+ timePeriod.setBeginPosition(beginZdt);
+ timePeriod.setEndPosition(endZdt);
+
+ TimePeriodProperty timePeriodProperty = new TimePeriodProperty();
+ timePeriodProperty.setTimePeriod(timePeriod);
+ regularTimeSeries.setTemporalExtent(timePeriodProperty);
+ }
+
+ Double time_interval = rs.getObject(14) != null ? rs.getDouble(14) : null;
+ String time_interval_unit = rs.getString(15);
+ if (time_interval != null) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(time_interval);
+ timeIntervalLength.setUnit(time_interval_unit);
+ regularTimeSeries.setTimeInterval(timeIntervalLength);
+ }
+
+ String valuesString = rs.getString(16);
+ String uom = rs.getString(17);
+ if (valuesString != null && !valuesString.isBlank()) {
+ List valuesList = Arrays.stream(valuesString.trim().split("\\s+"))
+ .map(Double::parseDouble)
+ .collect(Collectors.toList());
+
+ MeasureList measureList = new MeasureList();
+ measureList.setValue(valuesList);
+ measureList.setUom(uom != null ? uom : "");
+ regularTimeSeries.setValues(measureList);
+ }
+
+ } else if (abstractTimeSeries instanceof RegularTimeSeriesFile) {
+ RegularTimeSeriesFile regularTimeSeriesFile = (RegularTimeSeriesFile) abstractTimeSeries;
+
+ ZonedDateTime beginZdt = rs.getObject(7, ZonedDateTime.class);
+ ZonedDateTime endZdt = rs.getObject(8, ZonedDateTime.class);
+
+ if (beginZdt != null && endZdt != null) {
+ TimePeriod timePeriod = new TimePeriod();
+ timePeriod.setBeginPosition(beginZdt);
+ timePeriod.setEndPosition(endZdt);
+
+ TimePeriodProperty timePeriodProperty = new TimePeriodProperty();
+ timePeriodProperty.setTimePeriod(timePeriod);
+ regularTimeSeriesFile.setTemporalExtent(timePeriodProperty);
+ }
+
+ String uom = rs.getString(18);
+ if (uom != null) {
+ regularTimeSeriesFile.setUom(uom);
+ }
+
+ String file_uri = rs.getString(19);
+ if (file_uri != null && !file_uri.isEmpty()) {
+ try {
+ regularTimeSeriesFile.setFileURI(URI.create(file_uri));
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid URI for TimeSeries id=" + timeSeriesId + ": " + file_uri);
+ }
+ }
+
+ Double time_interval = rs.getObject(14) != null ? rs.getDouble(14) : null;
+ String time_interval_unit = rs.getString(15);
+ if (time_interval != null) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(time_interval);
+ timeIntervalLength.setUnit(time_interval_unit);
+ regularTimeSeriesFile.setTimeInterval(timeIntervalLength);
+ }
+
+ int num_of_header_lines = rs.getInt(20);
+ if (!rs.wasNull()) {
+ regularTimeSeriesFile.setNumberOfHeaderLines(num_of_header_lines);
+ }
+
+ String field_separator = rs.getString(21);
+ if (field_separator != null) {
+ regularTimeSeriesFile.setFieldSeparator(field_separator);
+ }
+
+ String record_separator = rs.getString(22);
+ if (record_separator != null) {
+ regularTimeSeriesFile.setRecordSeparator(record_separator);
+ }
+
+ String decimal_symbol = rs.getString(24);
+ if (decimal_symbol != null) {
+ regularTimeSeriesFile.setDecimalSymbol(decimal_symbol);
+ }
+
+ Integer value_column_number = rs.getObject(23) != null ? rs.getInt(23) : null;
+ if (value_column_number != null) {
+ regularTimeSeriesFile.setValueColumnNumber(value_column_number);
+ }
+ } else if (abstractTimeSeries instanceof TypicalValuesTimeSeries) {
+ TypicalValuesTimeSeries typicalValuesTimeSeries = (TypicalValuesTimeSeries) abstractTimeSeries;
+
+ Time start_time = rs.getTime(9);
+ if (start_time != null) {
+ LocalTime startTimestamp = start_time.toLocalTime();
+ typicalValuesTimeSeries.setStartTime(startTimestamp);
+ }
+
+ Integer start_day = rs.getObject(10) != null ? rs.getInt(10) : null;
+ if (start_day != null) {
+ typicalValuesTimeSeries.setStartDay(start_day);
+ }
+
+ Integer start_month = rs.getObject(11) != null ? rs.getInt(11) : null;
+ if (start_month != null) {
+ typicalValuesTimeSeries.setStartMonth(start_month);
+ }
+
+ Double time_interval = rs.getObject(14) != null ? rs.getDouble(14) : null;
+ String time_interval_unit = rs.getString(15);
+ if (time_interval != null) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(time_interval);
+ timeIntervalLength.setUnit(time_interval_unit);
+ typicalValuesTimeSeries.setTimeInterval(timeIntervalLength);
+ }
+
+ Double temporal_extent = rs.getDouble(12);
+ String temporal_extent_unit = rs.getString(13);
+ if (!rs.wasNull()) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(temporal_extent);
+ timeIntervalLength.setUnit(temporal_extent_unit);
+ typicalValuesTimeSeries.setTemporalExtent(timeIntervalLength);
+ }
+
+ String valuesString = rs.getString(16);
+ String uom = rs.getString(17);
+ if (valuesString != null && !valuesString.isBlank()) {
+ List valuesList = Arrays.stream(valuesString.trim().split("\\s+"))
+ .map(Double::parseDouble)
+ .collect(Collectors.toList());
+
+ MeasureList measureList = new MeasureList();
+ measureList.setValue(valuesList);
+ measureList.setUom(uom != null ? uom : "");
+ typicalValuesTimeSeries.setValues(measureList);
+ }
+ } else if (abstractTimeSeries instanceof TypicalValuesTimeSeriesFile) {
+ TypicalValuesTimeSeriesFile timeSeriesFile = (TypicalValuesTimeSeriesFile) abstractTimeSeries;
+
+ Time start_time = rs.getTime(9);
+ if (start_time != null) {
+ LocalTime localTime = start_time.toLocalTime();
+ ZonedDateTime zonedDateTime = localTime.atDate(LocalDate.now())
+ .atZone(ZoneId.systemDefault());
+ timeSeriesFile.setStartTime(zonedDateTime);
+ }
+
+ Integer start_day = rs.getObject(10) != null ? rs.getInt(10) : null;
+ if (start_day != null) {
+ timeSeriesFile.setStartDay(start_day);
+ }
+
+ Integer start_month = rs.getObject(11) != null ? rs.getInt(11) : null;
+ if (start_month != null) {
+ timeSeriesFile.setStartMonth(start_month);
+ }
+
+ Double time_interval = rs.getObject(14) != null ? rs.getDouble(14) : null;
+ String time_interval_unit = rs.getString(15);
+ if (time_interval != null) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(time_interval);
+ timeIntervalLength.setUnit(time_interval_unit);
+ timeSeriesFile.setTimeInterval(timeIntervalLength);
+ }
+
+ Double temporal_extent = rs.getDouble(12);
+ String temporal_extent_unit = rs.getString(13);
+ if (!rs.wasNull()) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(temporal_extent);
+ timeIntervalLength.setUnit(temporal_extent_unit);
+ timeSeriesFile.setTemporalExtent(timeIntervalLength);
+ }
+
+ String uom = rs.getString(18);
+ if (uom != null) {
+ timeSeriesFile.setUom(uom);
+ }
+
+ String file_uri = rs.getString(19);
+ if (file_uri != null && !file_uri.isEmpty()) {
+ try {
+ timeSeriesFile.setFileURI(URI.create(file_uri));
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid URI for TimeSeries id=" + timeSeriesId + ": " + file_uri);
+ }
+ }
+
+ int num_of_header_lines = rs.getInt(20);
+ if (!rs.wasNull()) {
+ timeSeriesFile.setNumberOfHeaderLines(num_of_header_lines);
+ }
+
+ String field_separator = rs.getString(21);
+ if (field_separator != null) {
+ timeSeriesFile.setFieldSeparator(field_separator);
+ }
+
+ String record_separator = rs.getString(22);
+ if (record_separator != null) {
+ timeSeriesFile.setRecordSeparator(record_separator);
+ }
+
+ String decimal_symbol = rs.getString(24);
+ if (decimal_symbol != null) {
+ timeSeriesFile.setDecimalSymbol(decimal_symbol);
+ }
+
+ Integer value_column_number = rs.getObject(23) != null ? rs.getInt(23) : null;
+ if (value_column_number != null) {
+ timeSeriesFile.setValueColumnNumber(value_column_number);
+ }
+
+ } else if (abstractTimeSeries instanceof SensorConnection) {
+ SensorConnection sensorConnection = (SensorConnection) abstractTimeSeries;
+ Double temporal_extent = rs.getDouble(12);
+ String temporal_extent_unit = rs.getString(13);
+ if (!rs.wasNull()) {
+ TimeIntervalLength timeIntervalLength = new TimeIntervalLength();
+ timeIntervalLength.setValue(temporal_extent);
+ timeIntervalLength.setUnit(temporal_extent_unit);
+ sensorConnection.setTemporalExtent(timeIntervalLength);
+ }
+
+ String connection_type = rs.getString(28);
+ String connection_type_codespace = rs.getString(29);
+ if (connection_type != null) {
+ Code code = new Code();
+ code.setValue(connection_type);
+ code.setCodeSpace(connection_type_codespace);
+ sensorConnection.setConnectionType(code);
+ }
+
+ String observation_property = rs.getString(36);
+ if (observation_property != null) {
+ sensorConnection.setObservationProperty(observation_property);
+ }
+
+ String uom = rs.getString(18);
+ if (uom != null) {
+ sensorConnection.setUom(uom);
+ }
+
+ String sensor_id = rs.getString(37);
+ if (sensor_id != null) {
+ sensorConnection.setSensorID(sensor_id);
+ }
+
+ String sensor_name = rs.getString(38);
+ if (sensor_name != null) {
+ sensorConnection.setSensorName(sensor_name);
+ }
+
+ String observation_id = rs.getString(35);
+ if (observation_id != null) {
+ sensorConnection.setObservationID(observation_id);
+ }
+
+ String datastream_id = rs.getString(30);
+ if (datastream_id != null) {
+ sensorConnection.setDataStreamID(datastream_id);
+ }
+
+ String base_url = rs.getString(27);
+ if (base_url != null) {
+ try {
+ sensorConnection.setBaseURL(URI.create(base_url));
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid base_url for TimeSeries id=" + timeSeriesId + ": " + base_url);
+ }
+ }
+
+ String auth_type = rs.getString(25);
+ String auth_type_codespace = rs.getString(26);
+ if (auth_type != null) {
+ Code code = new Code();
+ code.setValue(auth_type);
+ code.setCodeSpace(auth_type_codespace);
+ sensorConnection.setAuthType(code);
+ }
+
+ String link_to_observation = rs.getString(31);
+ if (link_to_observation != null) {
+ sensorConnection.setLinkToObservation(link_to_observation);
+ }
+
+ String link_to_sensor_description = rs.getString(32);
+ if (link_to_sensor_description != null) {
+ sensorConnection.setLinkToSensorDescription(link_to_sensor_description);
+ }
+
+ String mqtt_server = rs.getString(33);
+ if (mqtt_server != null) {
+ sensorConnection.setMqtServer(mqtt_server);
+ }
+
+ String mqtt_topic = rs.getString(34);
+ if (mqtt_topic != null) {
+ sensorConnection.setMqtTopic(mqtt_topic);
+ }
+ }
+ result.add(abstractTimeSeries);
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+
+ private String getColumnNames() {
+ return "id, objectclass_id, acquisition_method, acquisition_method_codespace, interpolation_type, source, " +
+ "period_begin, period_end, start_time, start_day, start_month, temporal_extent, temporal_extent_unit, " +
+ "time_interval, time_interval_unit, values_list, values_list_uom, uom, file_uri, num_of_header_lines, " +
+ "field_separator, record_separator, value_column_number, decimal_symbol, auth_type, auth_type_codespace, " +
+ "base_url, connection_type, connection_type_codespace, datastream_id, link_to_observation, " +
+ "link_to_sensor_description, mqtt_server, mqtt_topic, observation_id, observation_property, " +
+ "sensor_id, sensor_name";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/UrbanFunctionAreaExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/UrbanFunctionAreaExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3853f7d5067d5df2f966472e87c74f98b2bebe16
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/UrbanFunctionAreaExporter.java
@@ -0,0 +1,87 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeries;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeriesProperty;
+import org.citygml4j.ade.energy.model.supportingClasses.UrbanFunctionArea;
+import org.citygml4j.model.gml.basicTypes.Code;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class UrbanFunctionAreaExporter implements ADEExporter {
+
+ private PreparedStatement ps;
+ private String module;
+ private CityObjectPropertiesExporter cityObjectPropertiesExporter;
+ private TimeSeriesExporter timeSeriesExporter;
+
+
+ public UrbanFunctionAreaExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ String select = "select type, type_codespace, code, code_codespace from " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.URBAN_FUNCTION_AREA)) +
+ " where ";
+
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+ ps = connection.prepareStatement(select + "id = ?");
+ cityObjectPropertiesExporter = manager.getExporter(CityObjectPropertiesExporter.class);
+ timeSeriesExporter = manager.getExporter(TimeSeriesExporter.class);
+ }
+
+ public UrbanFunctionArea doExport(UrbanFunctionArea uaf, long objectId, AbstractType> objectType, ProjectionFilter projectionFilter) throws SQLException {
+ ps.setLong(1, objectId);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ while (rs.next()) {
+
+ String type = rs.getString(1);
+ String typeCodespace = rs.getString(2);
+ String code = rs.getString(3);
+ String codeCodespace = rs.getString(4);
+
+ Code typeCode = new Code();
+ if (typeCodespace != null) {
+ typeCode.setCodeSpace(typeCodespace);
+ }
+ if (type != null) {
+ typeCode.setValue(type);
+ }
+ uaf.setType(typeCode);
+
+ Code code1 = new Code();
+ if (codeCodespace != null) {
+ code1.setCodeSpace(codeCodespace);
+ }
+ if (code != null) {
+ code1.setValue(code);
+ }
+ uaf.setCode(code1);
+
+ if (projectionFilter.containsProperty("timeSeries", module)) {
+ for (AbstractTimeSeries timeSeries : timeSeriesExporter.doExport(objectId)) {
+ AbstractTimeSeriesProperty property = new AbstractTimeSeriesProperty(timeSeries);
+ uaf.addGenericApplicationPropertyOfCityObject(property);
+ }
+ }
+ }
+
+ } catch (CityGMLExportException e) {
+ throw new RuntimeException(e);
+ }
+ return uaf;
+ }
+
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherDataExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherDataExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e4dbac1ce5213790c8f2e76ee30315d854f00da
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherDataExporter.java
@@ -0,0 +1,184 @@
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.database.schema.mapping.ObjectType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.operation.exporter.database.content.GMLConverter;
+import org.citydb.core.query.filter.projection.CombinedProjectionFilter;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citydb.sqlbuilder.expression.PlaceHolder;
+import org.citydb.sqlbuilder.schema.Table;
+import org.citydb.sqlbuilder.select.Select;
+import org.citydb.sqlbuilder.select.operator.comparison.ComparisonFactory;
+import org.citygml4j.ade.energy.model.core.ReferencePointProperty;
+import org.citygml4j.ade.energy.model.core.WeatherData;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeries;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeriesProperty;
+import org.citygml4j.model.gml.basicTypes.Code;
+import org.citygml4j.model.gml.basicTypes.Measure;
+import org.citygml4j.model.gml.geometry.primitives.Point;
+import org.citygml4j.model.gml.geometry.primitives.PointProperty;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class WeatherDataExporter implements ADEExporter {
+
+ private final CityGMLExportHelper helper;
+ private final int objectClassId;
+
+ private PreparedStatement ps;
+ private TimeSeriesExporter timeSeriesExporter;
+ private GMLConverter gmlConverter;
+ private String module;
+
+ public WeatherDataExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.helper = helper;
+ objectClassId = manager.getObjectMapper().getObjectClassId(WeatherData.class);
+
+ String tableName = manager.getSchemaMapper().getTableName(ADETable.WEATHER_DATA);
+ CombinedProjectionFilter projectionFilter = helper.getCombinedProjectionFilter(tableName);
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+
+ Table table = new Table(helper.getTableNameWithSchema(tableName));
+
+ Select select = new Select().addProjection(
+ table.getColumn("id"),
+ table.getColumn("type"),
+ table.getColumn("type_codespace"),
+ table.getColumn("value_type"),
+ table.getColumn("value_type_codespace"),
+ table.getColumn("yearly_value"),
+ table.getColumn("yearly_value_uom"),
+ table.getColumn("library_code"),
+ table.getColumn("library_code_codespace"),
+ table.getColumn("time_series_id"),
+ table.getColumn("cityobject_id")
+ );
+
+ if (projectionFilter.containsProperty("position", module))
+ select.addProjection(table.getColumn("position"));
+
+ select.addSelection(ComparisonFactory.equalTo(table.getColumn("cityobject_id"), new PlaceHolder<>()));
+
+ ps = connection.prepareStatement(select.toString());
+
+ timeSeriesExporter = manager.getExporter(TimeSeriesExporter.class);
+ gmlConverter = helper.getGMLConverter();
+ }
+
+ public Collection doExport(long parentId) throws CityGMLExportException, SQLException {
+ ps.setLong(1, parentId);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ Collection result = new ArrayList<>();
+
+ while (rs.next()) {
+ long weatherDataId = rs.getLong(1);
+
+ WeatherData weatherData = helper.createObject(weatherDataId, objectClassId, WeatherData.class);
+ if (weatherData == null) {
+ helper.logOrThrowErrorMessage("Failed to instantiate " + helper.getObjectSignature(objectClassId, weatherDataId) + " as weather data object.");
+ continue;
+ }
+
+ ObjectType objectType = helper.getObjectType(objectClassId);
+ ProjectionFilter projectionFilter = helper.getProjectionFilter(objectType);
+
+ weatherData.setId(String.valueOf(weatherDataId));
+
+ // Set type
+ String typeValue = rs.getString(2);
+ String typeCodeSpace = rs.getString(3);
+ if (typeValue != null || typeCodeSpace != null) {
+ Code type = new Code();
+ type.setValue(typeValue);
+ type.setCodeSpace(typeCodeSpace);
+ type.setParent(weatherData);
+ weatherData.setType(type);
+ }
+
+ // Set value type
+ String valueTypeValue = rs.getString(4);
+ String valueTypeCodeSpace = rs.getString(5);
+ if (valueTypeValue != null || valueTypeCodeSpace != null) {
+ Code valueType = new Code();
+ valueType.setValue(valueTypeValue);
+ valueType.setCodeSpace(valueTypeCodeSpace);
+ valueType.setParent(weatherData);
+ weatherData.setValueType(valueType);
+ }
+
+ // Set yearly value and UOM
+ double yearlyValue = rs.getDouble(6);
+ if (!rs.wasNull()) {
+ Measure yearlyMeasure = new Measure();
+ yearlyMeasure.setValue(yearlyValue);
+ String yearlyValueUom = rs.getString(7);
+ if (yearlyValueUom != null) {
+ yearlyMeasure.setUom(yearlyValueUom);
+ }
+ yearlyMeasure.setParent(weatherData);
+ weatherData.setYearlyValue(yearlyMeasure);
+ }
+
+ // Set library code
+ String libraryCodeValue = rs.getString(8);
+ String libraryCodeSpace = rs.getString(9);
+ if (libraryCodeValue != null || libraryCodeSpace != null) {
+ Code libraryCode = new Code();
+ libraryCode.setValue(libraryCodeValue);
+ libraryCode.setCodeSpace(libraryCodeSpace);
+ libraryCode.setParent(weatherData);
+ weatherData.setLibraryCode(libraryCode);
+ }
+
+ // Set time series
+ long timeSeriesId = rs.getLong(10);
+ if (!rs.wasNull()) {
+ Collection timeSeries = timeSeriesExporter.doExport(timeSeriesId);
+ if (timeSeries != null && !timeSeries.isEmpty()) {
+ AbstractTimeSeries firstSeries = timeSeries.iterator().next();
+ weatherData.setTimeDependentValues(new AbstractTimeSeriesProperty(firstSeries));
+ }
+ }
+
+ // Set position (if requested)
+ if (projectionFilter.containsProperty("position", module)) {
+ Object pointObj = rs.getObject("position");
+ if (pointObj != null) {
+ try {
+ GeometryObject point = helper.getDatabaseAdapter().getGeometryConverter().getPoint(pointObj);
+ if (point != null) {
+ Point gmlPoint = gmlConverter.getPoint(point);
+ PointProperty pointProperty = new PointProperty(gmlPoint);
+ ReferencePointProperty refPointProp = new ReferencePointProperty(pointProperty);
+ weatherData.setPosition(refPointProp);
+ }
+ } catch (Exception e) {
+ // Skip invalid geometry to continue export
+ }
+ }
+ }
+
+ result.add(weatherData);
+ }
+
+ return result;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherStationExporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherStationExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d9c2c05992ab91c10ce2dd492e36bfaa1011165
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/exporter/WeatherStationExporter.java
@@ -0,0 +1,131 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.exporter;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.exporter.ADEExporter;
+import org.citydb.core.ade.exporter.CityGMLExportHelper;
+import org.citydb.core.database.schema.mapping.AbstractType;
+import org.citydb.core.operation.exporter.CityGMLExportException;
+import org.citydb.core.operation.exporter.database.content.GMLConverter;
+import org.citydb.core.query.filter.projection.ProjectionFilter;
+import org.citydb.sqlbuilder.expression.PlaceHolder;
+import org.citydb.sqlbuilder.schema.Table;
+import org.citydb.sqlbuilder.select.Select;
+import org.citydb.sqlbuilder.select.operator.comparison.ComparisonFactory;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.module.EnergyADEModule;
+import org.citygml4j.ade.energy.model.supportingClasses.WeatherStation;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class WeatherStationExporter implements ADEExporter {
+ private final CityGMLExportHelper helper;
+ private final int weatherDataObjectClassId;
+
+ private PreparedStatement ps;
+ private TimeSeriesExporter timeSeriesExporter;
+ private WeatherDataExporter weatherDataExporter;
+ private GMLConverter gmlConverter;
+ private String module;
+
+ public WeatherStationExporter(Connection connection, CityGMLExportHelper helper, ExportManager manager) throws CityGMLExportException, SQLException {
+ this.helper = helper;
+ weatherDataObjectClassId = manager.getObjectMapper().getObjectClassId(WeatherData.class);
+
+ String tableName = manager.getSchemaMapper().getTableName(ADETable.CITYOBJECT);
+ module = EnergyADEModule.v2_0.getNamespaceURI();
+
+ Table table = new Table(helper.getTableNameWithSchema(tableName));
+ Select select = new Select().addProjection(table.getColumn("id"));
+ select.addSelection(ComparisonFactory.equalTo(table.getColumn("id"), new PlaceHolder<>()));
+ ps = connection.prepareStatement(select.toString());
+
+ timeSeriesExporter = manager.getExporter(TimeSeriesExporter.class);
+ weatherDataExporter = manager.getExporter(WeatherDataExporter.class);
+ gmlConverter = helper.getGMLConverter();
+ }
+
+ public void doExport(WeatherStation weatherStation, long objectId, AbstractType> objectType, ProjectionFilter projectionFilter) throws CityGMLExportException, SQLException {
+ ps.setLong(1, objectId);
+
+// try (ResultSet rs = ps.executeQuery()) {
+// while (rs.next()) {
+//
+// long weatherDataId = rs.getLong("id");
+// if (!rs.wasNull()) {
+// WeatherData weatherData = helper.createObject(weatherDataId, weatherDataObjectClassId, WeatherData.class);
+// if (weatherData == null) {
+// helper.logOrThrowErrorMessage("Failed to instantiate " + helper.getObjectSignature(weatherDataObjectClassId, weatherDataId) + " as weather data object.");
+// continue;
+// }
+//
+// ObjectType weatherDataObjectType = helper.getObjectType(weatherDataObjectClassId);
+// ProjectionFilter weatherDataProjectionFilter = helper.getProjectionFilter(weatherDataObjectType);
+//
+//// weatherData.setType(new Code(rs.getString("weatherdatatype")));
+////
+//// long valuesId = rs.getLong("values_id");
+// if (!rs.wasNull()) {
+// AbstractTimeSeries timeSeries = timeSeriesExporter.doExport(objectId);
+// if (timeSeries != null)
+// weatherData.setTimeDependentValues(new AbstractTimeSeriesProperty(timeSeries));
+// }
+//
+// if (weatherDataProjectionFilter.containsProperty("position", module)) {
+// Object pointObj = rs.getObject("position");
+// if (pointObj != null) {
+// GeometryObject point = helper.getDatabaseAdapter().getGeometryConverter().getPoint(pointObj);
+// if (point != null) {
+//
+// PointProperty pointProperty = new PointProperty();
+// pointProperty.setGeometry(point);
+//
+//
+// ReferencePointProperty referencePointProperty = new ReferencePointProperty(pointProperty);
+//
+// weatherData.setPosition(referencePointProperty);
+// }
+// }
+// }
+//
+// weatherStation.addParameter(new WeatherDataProperty(weatherData));
+// }
+// }
+// }
+ }
+
+
+ @Override
+ public void close() throws CityGMLExportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractBuildingImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractBuildingImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..5233a49567c198f6da2d56008b947b0e282d357d
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractBuildingImporter.java
@@ -0,0 +1,83 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.ADEPropertyCollection;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.database.schema.mapping.FeatureType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.AbstractBuilding;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Collections;
+
+public class AbstractBuildingImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+ private final SchemaMapper schemaMapper;
+
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public AbstractBuildingImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.schemaMapper = manager.getSchemaMapper();
+
+ ps = connection.prepareStatement(
+ "INSERT INTO " + helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.BUILDING)) +
+ " (id, type, type_codespace, is_protected, constr_weight, constr_weight_codespace, attic_thm_status, basement_thm_status) " +
+ "VALUES (" + String.join(", ", Collections.nCopies(8, "?")) + ")"
+ );
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+
+ public void doImport(ADEPropertyCollection properties, AbstractBuilding building, long parentId, FeatureType parentType) throws CityGMLImportException, SQLException {
+
+ ps.setLong(1, parentId);
+
+ ps.setString(2, building.getBdgType() != null ? building.getBdgType().getValue() : null);
+
+
+ ps.setString(3, building.getBdgType() != null ? building.getBdgType().getCodeSpace() : null);
+
+ ps.setInt(4, building.isBdgIsProtected() ? 0 : 1);
+
+ ps.setString(5, building.getBdgConstructionWeight() != null ? building.getBdgConstructionWeight().getValue() : null);
+ ps.setString(6, building.getBdgConstructionWeight() != null ? building.getBdgConstructionWeight().getCodeSpace() : null);
+
+ ps.setString(7, building.getBdgAtticThermalStatus() != null ? building.getBdgAtticThermalStatus().toString() : null);
+ ps.setString(8, building.getBdgBasementThermalStatus() != null ? building.getBdgBasementThermalStatus().toString() : null);
+
+
+ GeometryObject geometryObject = null;
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(schemaMapper.getTableName(ADETable.BUILDING));
+ }
+
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractDeviceImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractDeviceImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d6af2824fe6d7dbcd19c4bd8c33a2bbc7ba79a4
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractDeviceImporter.java
@@ -0,0 +1,114 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citygml4j.ade.energy.model.core.AbstractDevice;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+public class AbstractDeviceImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+ private final SchemaMapper schemaMapper;
+
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public AbstractDeviceImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.helper = helper;
+ this.connection = connection;
+
+ this.schemaMapper = manager.getSchemaMapper();
+
+ ps = connection.prepareStatement(
+ "INSERT INTO " + helper.getTableNameWithSchema(schemaMapper.getTableName(ADETable.DEVICE)) + " " +
+ "(id, objectclass_id, model, num_of_devices, year_of_manufacture, installed_power, installed_power_uom, " +
+ "nominal_efficiency, nominal_efficiency_uom, efficiency_indicator, heat_diss, heat_diss_uom, heat_diss_conv, " +
+ "heat_diss_conv_uom, heat_diss_lat, heat_diss_lat_uom, heat_diss_rad, heat_diss_rad_uom, heat_source, " +
+ "cop_source_temp, cop_source_temp_uom, cop_operation_temp, cop_operation_temp_uom, has_condensation, type, " +
+ "type_codespace, installation_side, max_cover_ratio, max_cover_ratio_uom, transmittance_id, cityobject_id) " +
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+ );
+ }
+
+ public void doImport(AbstractDevice abstractDevice, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ ps.setInt(2, objectType != null ? objectType.getObjectClassId() : 0);
+ ps.setString(3, abstractDevice != null ? abstractDevice.getModel() : null);
+ ps.setInt(4, abstractDevice != null ? abstractDevice.getNumberOfDevices() : 0);
+ ps.setInt(5, abstractDevice != null ? abstractDevice.getYearOfManufacture() : 0);
+
+ ps.setDouble(6, (abstractDevice != null && abstractDevice.getInstalledPower() != null) ?
+ abstractDevice.getInstalledPower().getValue() : 0.0);
+ ps.setString(7, (abstractDevice != null && abstractDevice.getInstalledPower() != null) ?
+ abstractDevice.getInstalledPower().getUom() : null);
+
+ ps.setDouble(8, (abstractDevice != null && abstractDevice.getNominalEfficiency() != null) ?
+ abstractDevice.getNominalEfficiency().getValue() : 0.0);
+ ps.setString(9, (abstractDevice != null && abstractDevice.getNominalEfficiency() != null) ?
+ abstractDevice.getNominalEfficiency().getUom() : null);
+
+ ps.setString(10, abstractDevice != null ? abstractDevice.getEfficiencyIndicator() : null);
+
+ ps.setDouble(11, (abstractDevice != null && abstractDevice.getHeatDissipation() != null) ?
+ abstractDevice.getHeatDissipation().getValue() : 0.0);
+ ps.setString(12, (abstractDevice != null && abstractDevice.getHeatDissipation() != null) ?
+ abstractDevice.getHeatDissipation().getUom() : null);
+
+ ps.setDouble(13, (abstractDevice != null && abstractDevice.getHeatDissipationConvectiveFraction() != null) ?
+ abstractDevice.getHeatDissipationConvectiveFraction().getValue() : 0.0);
+ ps.setString(14, (abstractDevice != null && abstractDevice.getHeatDissipationConvectiveFraction() != null) ?
+ abstractDevice.getHeatDissipationConvectiveFraction().getUom() : null);
+
+ ps.setDouble(15, (abstractDevice != null && abstractDevice.getHeatDissipationLatentFraction() != null) ?
+ abstractDevice.getHeatDissipationLatentFraction().getValue() : 0.0);
+ ps.setString(16, (abstractDevice != null && abstractDevice.getHeatDissipationLatentFraction() != null) ?
+ abstractDevice.getHeatDissipationLatentFraction().getUom() : null);
+
+ ps.setDouble(17, (abstractDevice != null && abstractDevice.getHeatDissipationRadiantFraction() != null) ?
+ abstractDevice.getHeatDissipationRadiantFraction().getValue() : 0.0);
+ ps.setString(18, (abstractDevice != null && abstractDevice.getHeatDissipationRadiantFraction() != null) ?
+ abstractDevice.getHeatDissipationRadiantFraction().getUom() : null);
+
+ ps.setNull(19, Types.VARCHAR);
+ ps.setNull(20, Types.DOUBLE);
+ ps.setNull(21, Types.VARCHAR);
+ ps.setNull(22, Types.DOUBLE);
+ ps.setNull(23, Types.VARCHAR);
+ ps.setNull(24, Types.DOUBLE);
+ ps.setNull(25, Types.VARCHAR);
+ ps.setNull(26, Types.VARCHAR);
+ ps.setNull(27, Types.VARCHAR);
+ ps.setNull(28, Types.DOUBLE);
+ ps.setNull(29, Types.VARCHAR);
+ ps.setNull(30, Types.BIGINT);
+ ps.setNull(31, Types.BIGINT);
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractQualifiedAttributeImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractQualifiedAttributeImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6091a2267129dc9730925669e5f5c90c3a669b43
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/AbstractQualifiedAttributeImporter.java
@@ -0,0 +1,138 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADESequence;
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.database.schema.mapping.ComplexType;
+import org.citydb.core.database.schema.mapping.ObjectType;
+import org.citydb.core.database.schema.mapping.SchemaMapping;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citydb.core.registry.ObjectRegistry;
+import org.citydb.core.util.Util;
+import org.citygml4j.ade.energy.model.core.AbstractQualifiedAttribute;
+import org.citygml4j.ade.energy.model.core.QualifiedArea;
+import org.citygml4j.ade.energy.model.core.QualifiedHeight;
+import org.citygml4j.ade.energy.model.core.QualifiedVolume;
+import org.sig3d.citygml.energyADE2beta7.AbstractQualifiedAttributeType;
+import org.sig3d.citygml.energyADE2beta7.QualifiedAreaType;
+import org.sig3d.citygml.energyADE2beta7.QualifiedHeightType;
+import org.sig3d.citygml.energyADE2beta7.QualifiedVolumeType;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Collections;
+
+public class AbstractQualifiedAttributeImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+ private final ImportManager manager;
+ private SchemaMapper schemaMapper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public AbstractQualifiedAttributeImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.manager = manager;
+ this.schemaMapper = manager.getSchemaMapper();
+
+ ps = connection.prepareStatement(
+ "INSERT INTO " + helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.QUALIFIED_ATTRIBUTE)) +
+ "(id, objectclass_id, type, type_codespace, value, value_uom, description, source, building_id, building_partition_id) " +
+ "VALUES (" + String.join(", ", Collections.nCopies(10, "?")) + ")"
+ );
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(AbstractQualifiedAttributeType abstractQualifiedAttribute, long parentId) throws CityGMLImportException, SQLException {
+
+ setAbstractQualifiedAttributeToNull();
+ long objectId = helper.getNextSequenceValue(schemaMapper.getSequenceName(ADESequence.QUALIFIED_ATTRIBUTE_SEQ));
+
+ ps.setLong(1, objectId);
+
+ ps.setLong(9, parentId);
+
+
+ if (abstractQualifiedAttribute.isSetDescription())
+ ps.setString(7, abstractQualifiedAttribute.getDescription());
+ if (abstractQualifiedAttribute.isSetSource())
+ ps.setString(8, abstractQualifiedAttribute.getSource());
+ if (abstractQualifiedAttribute.isSetValue()) {
+ ps.setDouble(5, abstractQualifiedAttribute.getValue().getValue());
+ ps.setString(6, abstractQualifiedAttribute.getValue().getUom());
+ }
+
+ if (abstractQualifiedAttribute instanceof QualifiedHeightType qualifiedHeight) {
+ if (qualifiedHeight.isSetType()) {
+ SchemaMapping schemaMapping = ObjectRegistry.getInstance().getSchemaMapping();
+ ComplexType qualifiedHeightType = schemaMapping.getComplexType("QualifiedHeight", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassId = qualifiedHeightType.getObjectClassId();
+ ps.setInt(2, objectClassId);
+ ps.setString(3, qualifiedHeight.getType().getValue());
+ ps.setString(4, qualifiedHeight.getType().getCodeSpace());
+ }
+ } else if (abstractQualifiedAttribute instanceof QualifiedAreaType qualifiedArea) {
+ if (qualifiedArea.isSetType()) {
+ SchemaMapping schemaMapping = ObjectRegistry.getInstance().getSchemaMapping();
+ ComplexType qualifiedAreaType = schemaMapping.getComplexType("QualifiedArea", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassId = qualifiedAreaType.getObjectClassId();
+ ps.setInt(2, objectClassId);
+ ps.setString(3, qualifiedArea.getType().getValue());
+ ps.setString(4, qualifiedArea.getType().getCodeSpace());
+ }
+ } else if (abstractQualifiedAttribute instanceof QualifiedVolumeType qualifiedVolume) {
+ if (qualifiedVolume.isSetType()){
+ SchemaMapping schemaMapping = ObjectRegistry.getInstance().getSchemaMapping();
+ ComplexType qualifiedVolumeType = schemaMapping.getComplexType("QualifiedVolume", "http://www.citygml.org/ade/energy/2.0");
+ int objectClassId = qualifiedVolumeType.getObjectClassId();
+ ps.setInt(2, objectClassId);
+ ps.setString(3, qualifiedVolume.getType().getValue());
+ ps.setString(4, qualifiedVolume.getType().getCodeSpace());
+ }
+ }
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(schemaMapper.getTableName(ADETable.QUALIFIED_ATTRIBUTE));
+
+ }
+
+ private void setAbstractQualifiedAttributeToNull() throws SQLException {
+
+ ps.setNull(1, Types.BIGINT); // id
+ ps.setNull(2, Types.INTEGER); // objectclass_id
+ ps.setNull(3, Types.VARCHAR); // type
+ ps.setNull(4, Types.VARCHAR); // type_codespace
+ ps.setNull(5, Types.DOUBLE); // value
+ ps.setNull(6, Types.VARCHAR); // value_uom
+ ps.setNull(7, Types.VARCHAR); // description
+ ps.setNull(8, Types.VARCHAR); // source
+ ps.setNull(9, Types.BIGINT); // building_id
+ ps.setNull(10, Types.BIGINT); // building_partition_id
+
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/BuildingPropertiesImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/BuildingPropertiesImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3340a8342043cf8bc923a6c283123a6a41bf2259
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/BuildingPropertiesImporter.java
@@ -0,0 +1,207 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.ADEPropertyCollection;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.FeatureType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.model.citygml.building.AbstractBuilding;
+import org.sig3d.citygml.energyADE2beta7.QualifiedAreaType;
+import org.sig3d.citygml.energyADE2beta7.QualifiedHeightType;
+import org.sig3d.citygml.energyADE2beta7.QualifiedVolumeType;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+public class BuildingPropertiesImporter implements ADEImporter {
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+ private final SchemaMapper schemaMapper;
+ private final ImportManager manager;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ private AbstractQualifiedAttributeImporter abstractQualifiedAttributeImporter;
+ private RefurbishmentMeasureImporter refurbishmentMeasureImporter;
+
+ public BuildingPropertiesImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.schemaMapper = manager.getSchemaMapper();
+ this.manager = manager;
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(schemaMapper.getTableName(ADETable.BUILDING)) + " " +
+ "(id, type, type_codespace, is_protected, constr_weight, constr_weight_codespace, attic_thm_status, basement_thm_status) " +
+ "values (?, ?, ?, ?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ abstractQualifiedAttributeImporter = manager.getImporter(AbstractQualifiedAttributeImporter.class);
+ refurbishmentMeasureImporter = manager.getImporter(RefurbishmentMeasureImporter.class);
+ }
+
+ public void doImport(ADEPropertyCollection properties, AbstractBuilding abstractBuilding, long parentId, FeatureType parentType) throws CityGMLImportException, SQLException {
+ ps.setLong(1, parentId);
+
+ setBuildingNull();
+
+ if (properties.contains(BuildingTypeProperty.class)){
+ for (BuildingTypeProperty propertyElement : properties.getAll(BuildingTypeProperty.class)) {
+ String type = propertyElement.getValue().getValue();
+ ps.setString(2, type);
+ String typeCodeSpace = propertyElement.getValue().getCodeSpace();
+ ps.setString(3, typeCodeSpace);
+ }
+ }
+ if (properties.contains(BuildingIsProtectedProperty.class)) {
+ for (BuildingIsProtectedProperty propertyElement : properties.getAll(BuildingIsProtectedProperty.class)) {
+ Boolean isProtected = propertyElement.getValue();
+ ps.setInt(4, (isProtected != null && isProtected) ? 1 : 0);
+ }
+ }
+ if (properties.contains(BuildingConstructionWeightProperty.class)) {
+ for (BuildingConstructionWeightProperty propertyElement : properties.getAll(BuildingConstructionWeightProperty.class)) {
+ String weight = propertyElement.getValue().getValue();
+ ps.setString(5, weight);
+ String weightCodeSpace = propertyElement.getValue().getCodeSpace();
+ ps.setString(6, weightCodeSpace);
+ }
+ }
+ if (properties.contains(BuildingAtticThermalStatusProperty.class)) {
+ for (BuildingAtticThermalStatusProperty propertyElement : properties.getAll(BuildingAtticThermalStatusProperty.class)) {
+ String atticThermalStatus = propertyElement.getValue().value();
+ ps.setString(7, atticThermalStatus);
+ }
+ }
+ if (properties.contains(BuildingBasementThermalStatusProperty.class)){
+ for (BuildingBasementThermalStatusProperty propertyElement : properties.getAll(BuildingBasementThermalStatusProperty.class)) {
+ String buildingBasementThermalStatus = propertyElement.getValue().value();
+ ps.setString(8, buildingBasementThermalStatus);
+ }
+ }
+ if (properties.contains(QualifiedAreaProperty.class)){
+ for (QualifiedAreaProperty propertyElement : properties.getAll(QualifiedAreaProperty.class)) {
+ QualifiedAreaType qualifiedArea = propertyElement.getValue().getQualifiedArea();
+ if (qualifiedArea != null) {
+ abstractQualifiedAttributeImporter.doImport(qualifiedArea, parentId);
+ }
+ }
+ }
+ if (properties.contains(QualifiedHeightProperty.class)){
+ for (QualifiedHeightProperty propertyElement : properties.getAll(QualifiedHeightProperty.class)) {
+ QualifiedHeightType qualifiedHeightType = propertyElement.getValue().getQualifiedHeight();
+ if (qualifiedHeightType != null) {
+ abstractQualifiedAttributeImporter.doImport(qualifiedHeightType, parentId);
+ }
+ }
+ }
+ if (properties.contains(QualifiedVolumeProperty.class)){
+ for (QualifiedVolumeProperty propertyElement : properties.getAll(QualifiedVolumeProperty.class)) {
+ QualifiedVolumeType qualifiedVolumeType = propertyElement.getValue().getQualifiedVolume();
+ if (qualifiedVolumeType != null) {
+ abstractQualifiedAttributeImporter.doImport(qualifiedVolumeType, parentId);
+ }
+ }
+ }
+
+ if (properties.contains(RefurbishmentMeasureProperty.class)){
+ for (RefurbishmentMeasureProperty propertyElement : properties.getAll(RefurbishmentMeasureProperty.class)) {
+ RefurbishmentMeasure refurbishmentMeasure = propertyElement.getRefurbishmentMeasure();
+ if (refurbishmentMeasure != null) {
+ helper.importObject(refurbishmentMeasure, ForeignKeys.create().with("buildingId", parentId));
+ }
+ }
+ }
+
+// if (properties.contains(UsageZoneProperty.class)) {
+// for (UsageZoneProperty propertyElement : properties.getAll(UsageZoneProperty.class)) {
+// AbstractUsageZone usageZone = propertyElement.getValue().getAbstractUsageZone();
+// if (usageZone != null) {
+// helper.importObject(usageZone, ForeignKeys.create().with("buildingId", parentId));
+// propertyElement.getValue().unsetAbstractUsageZone();
+// } else {
+// String href = propertyElement.getValue().getHref();
+// if (href != null && href.length() != 0)
+// helper.logOrThrowUnsupportedXLinkMessage(parent, AbstractUsageZone.class, href);
+// }
+// }
+// }
+//
+// if (properties.contains(ThermalZonePropertyElement.class)) {
+// for (ThermalZonePropertyElement propertyElement : properties.getAll(ThermalZonePropertyElement.class)) {
+// AbstractThermalZone thermalZone = propertyElement.getValue().getAbstractThermalZone();
+// if (thermalZone != null) {
+// helper.importObject(thermalZone, ForeignKeys.create().with("buildingId", parentId));
+// propertyElement.getValue().unsetAbstractThermalZone();
+// } else {
+// String href = propertyElement.getValue().getHref();
+// if (href != null && href.length() != 0)
+// helper.logOrThrowUnsupportedXLinkMessage(parent, AbstractThermalZone.class, href);
+// }
+// }
+// }
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(schemaMapper.getTableName(ADETable.BUILDING));
+ }
+
+ private void setBuildingNull() throws SQLException {
+ ps.setNull(2, Types.VARCHAR);
+ ps.setNull(3, Types.VARCHAR);
+ ps.setNull(4, Types.INTEGER);
+ ps.setNull(5, Types.VARCHAR);
+ ps.setNull(6, Types.VARCHAR);
+ ps.setNull(7, Types.VARCHAR);
+ ps.setNull(8, Types.VARCHAR);
+ }
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectPropertiesImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectPropertiesImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..559aa7757de8c5e61653b5692facffd207c35829
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectPropertiesImporter.java
@@ -0,0 +1,142 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.ADEPropertyCollection;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.FeatureType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.citygml.core.AbstractCityObject;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class CityObjectPropertiesImporter implements ADEImporter {
+ private final CityGMLImportHelper helper;
+ private final SchemaMapper schemaMapper;
+ private final ImportManager manager;
+
+ private PreparedStatement ps;
+ private int batchCounter;
+ private Connection connection;
+
+ public CityObjectPropertiesImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.helper = helper;
+ this.schemaMapper = manager.getSchemaMapper();
+ this.manager = manager;
+ this.connection=connection;
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(schemaMapper.getTableName(ADETable.CITYOBJECT)) + " " +
+ "(id, ref_point) " +
+ "values (?,?)");
+ }
+
+ public void doImport(ADEPropertyCollection properties, AbstractCityObject parent, long parentId, FeatureType parentType) throws CityGMLImportException, SQLException {
+ ps.setLong(1, parentId);
+ GeometryObject geometryObject = null;
+ ReferencePointProperty referencePoint = properties.getFirst(ReferencePointProperty.class);
+ if (referencePoint != null && referencePoint.isSetValue())
+ geometryObject = helper.getGeometryConverter().getPoint(referencePoint.getValue());
+ if (geometryObject != null)
+ ps.setObject(2, helper.getDatabaseAdapter().getGeometryConverter().getDatabaseObject(geometryObject, connection));
+ else
+ ps.setNull(2, helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryType(),
+ helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryTypeName());
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(schemaMapper.getTableName(ADETable.CITYOBJECT));
+
+ if (properties.contains(AbstractResourceProperty.class)) {
+
+ for (AbstractResourceProperty propertyElement : properties.getAll(AbstractResourceProperty.class)) {
+ AbstractResource resource = propertyElement.getAbstractResource();
+ if (resource != null) {
+ helper.importObject(resource, ForeignKeys.create().with("cityObjectId", parentId));
+ propertyElement.unsetAbstractResource();
+ } else {
+ String href = propertyElement.getHref();
+ if (href != null && href.length() != 0)
+ helper.logOrThrowUnsupportedXLinkMessage(parent, AbstractResource.class, href);
+ }
+ }
+ }
+
+ if (properties.contains(EnergyProperty.class)) {
+ for (EnergyProperty propertyElement : properties.getAll(EnergyProperty.class)) {
+ Energy energyDemand = propertyElement.getEnergy();
+ if (energyDemand != null) {
+ helper.importObject(energyDemand, ForeignKeys.create().with("cityObjectId", parentId));
+ propertyElement.unsetEnergy();
+ } else {
+ String href = propertyElement.getHref();
+ if (href != null && href.length() != 0)
+ helper.logOrThrowUnsupportedXLinkMessage(parent, Energy.class, href);
+ }
+ }
+ }
+
+ if (properties.contains(WeatherDataProperty.class)) {
+ for (WeatherDataProperty propertyElement : properties.getAll(WeatherDataProperty.class)) {
+ WeatherData weatherData = propertyElement.getWeatherData();
+ if (weatherData != null) {
+ helper.importObject(weatherData, ForeignKeys.create().with("cityObjectId", parentId));
+ propertyElement.unsetWeatherData();
+ } else {
+ String href = propertyElement.getHref();
+ if (href != null && href.length() != 0)
+ helper.logOrThrowUnsupportedXLinkMessage(parent, WeatherData.class, href);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectRelationImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectRelationImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d1945bcd7e88f62d23bda330268174dd33f06bb
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/CityObjectRelationImporter.java
@@ -0,0 +1,68 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.CityObjectRelation;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class CityObjectRelationImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public CityObjectRelationImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement("INSERT INTO " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.UTL_NTW_CONNECTION)) + " " +
+ "(id, ng2_cityobject_id, cityobject_id, relation_type, relation_type_codespace) " +
+ "VALUES (?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+
+ }
+
+ public void doImport(CityObjectRelation cityObjectRelation, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ if (cityObjectRelation.isSetRelation()) {
+ ps.setString(4, cityObjectRelation.getRelationType().getValue());
+ ps.setString(5, cityObjectRelation.getRelationType().getCodeSpace());
+ }
+
+
+ //set correctly
+ ps.setLong(2, objectType.getObjectClassId());
+ ps.setLong(3, objectType.getObjectClassId());
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/DeviceOperationImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/DeviceOperationImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc0aca461afd949d2a261a7587f244fc0ca4510f
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/DeviceOperationImporter.java
@@ -0,0 +1,63 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citygml4j.ade.energy.model.core.DeviceOperation;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class DeviceOperationImporter implements ADEImporter {
+
+ private final CityGMLImportHelper helper;
+ private final SchemaMapper schemaMapper;
+
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public DeviceOperationImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.helper = helper;
+ this.schemaMapper = manager.getSchemaMapper();
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(schemaMapper.getTableName(ADETable.DEVICE_OPERATION)) + " " +
+ "(id, type, type_codespace, yearly_global_efficiency, schedule_id, device_id) " +
+ "values (?, ?, ?, ?, ?,?)");
+ }
+
+ public void doImport(DeviceOperation deviceOperation, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ ps.setString(2,
+ deviceOperation.getType() != null ?
+ deviceOperation.getType().getValue() : null);
+
+ ps.setString(3,
+ deviceOperation.getType() != null ?
+ deviceOperation.getType().getCodeSpace() : null);
+
+ ps.setDouble(4,
+ deviceOperation.getYearlyGlobalEfficiency() != null ?
+ deviceOperation.getYearlyGlobalEfficiency() : 0.0);
+
+ }
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/EnergyPerformanceCertificateImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/EnergyPerformanceCertificateImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..015f5724b4701f44caba54a97591d04990307f14
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/EnergyPerformanceCertificateImporter.java
@@ -0,0 +1,90 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.EnergyPerformanceCertificate;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Collections;
+
+public class EnergyPerformanceCertificateImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public EnergyPerformanceCertificateImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ PreparedStatement ps = connection.prepareStatement(
+ "INSERT INTO " + helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.ENERGY_PERF_CERT)) +
+ " (id, type, type_codespace, label, value, value_uom, issue_date, expiration_date, cert_method, cert_uri, cityobject_id) " +
+ "VALUES (" + String.join(", ", Collections.nCopies(11, "?")) + ")"
+ );
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+
+ public void doImport(EnergyPerformanceCertificate energyPerformanceCertificate, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+
+ ps.setLong(1, objectId);
+ if (energyPerformanceCertificate.isSetType()) {
+ ps.setString(2, energyPerformanceCertificate.getType().getValue());
+ ps.setString(3, energyPerformanceCertificate.getType().getCodeSpace());
+ }
+ if (energyPerformanceCertificate.isSetLabel())
+ ps.setString(4, energyPerformanceCertificate.getLabel());
+ if (energyPerformanceCertificate.isSetValue()){
+ ps.setDouble(5, energyPerformanceCertificate.getValue().getValue());
+ ps.setString(6, energyPerformanceCertificate.getValue().getUom());
+ }
+ if (energyPerformanceCertificate.isSetIssueDate()){
+ XMLGregorianCalendar xmlCal = energyPerformanceCertificate.getIssueDate();
+ Timestamp timestamp = new Timestamp(xmlCal.toGregorianCalendar().getTimeInMillis());
+ ps.setTimestamp(7, timestamp);
+ }
+ if (energyPerformanceCertificate.isSetExpirationDate()){
+ XMLGregorianCalendar xmlCal = energyPerformanceCertificate.getExpirationDate();
+ Timestamp timestamp = new Timestamp(xmlCal.toGregorianCalendar().getTimeInMillis());
+ ps.setTimestamp(8, timestamp);
+ }
+ if (energyPerformanceCertificate.isSetCertificationMethod())
+ ps.setString(9, energyPerformanceCertificate.getCertificationMethod());
+ if (energyPerformanceCertificate.isSetCertificationURI())
+ ps.setString(10, energyPerformanceCertificate.getCertificationURI().toString());
+ ps.setLong(11, objectId);
+
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/ImportManager.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/ImportManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..df1b659a21ff5f827f19f96e7473af817a54a55b
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/ImportManager.java
@@ -0,0 +1,160 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.importer;
+
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.ADEExtension;
+import org.citydb.core.ade.importer.*;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.database.schema.mapping.FeatureType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.citygml.ade.binding.ADEModelObject;
+import org.citygml4j.model.citygml.building.AbstractBuilding;
+import org.citygml4j.model.citygml.core.AbstractCityObject;
+import org.citygml4j.model.gml.feature.AbstractFeature;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ImportManager implements ADEImportManager {
+ private final ADEExtension adeExtension;
+ private final Map, ADEImporter> importers;
+ private final SchemaMapper schemaMapper;
+
+ private Connection connection;
+ private CityGMLImportHelper helper;
+
+ public ImportManager(ADEExtension adeExtension, SchemaMapper schemaMapper) {
+ this.adeExtension = adeExtension;
+ this.schemaMapper = schemaMapper;
+ importers = new HashMap<>();
+ }
+
+ @Override
+ public void init(Connection connection, CityGMLImportHelper helper) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ }
+
+ @Override
+ public void importObject(ADEModelObject object, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ if(object instanceof AbstractTimeSeries)
+ getImporter(TimeSeriesImporter.class).doImport((AbstractTimeSeries) object, objectId, objectType, foreignKeys);
+ else if (object instanceof AbstractDevice)
+ getImporter(AbstractDeviceImporter.class).doImport((AbstractDevice) object, objectId, objectType, foreignKeys);
+ else if (object instanceof DeviceOperation)
+ getImporter(DeviceOperationImporter.class).doImport((DeviceOperation) object, objectId, objectType, foreignKeys);
+ else if (object instanceof AbstractResource)
+ getImporter(ResourceImporter.class).doImport((AbstractResource) object, objectId, objectType, foreignKeys);
+ else if(object instanceof UrbanFunctionArea)
+ getImporter(UrbanFunctionAreaImporter.class).doImport((UrbanFunctionArea) object, objectId, objectType, foreignKeys);
+ else if(object instanceof RefurbishmentMeasure)
+ getImporter(RefurbishmentMeasureImporter.class).doImport((RefurbishmentMeasure) object, objectId, objectType, foreignKeys);
+ else if(object instanceof WeatherStation)
+ getImporter(WeatherStationImporter.class).doImport((WeatherStation) object, objectId, objectType, foreignKeys);
+ else if (object instanceof WeatherData)
+ getImporter(WeatherDataImporter.class).doImport((WeatherData) object, objectId, objectType, foreignKeys);
+
+
+ }
+
+ @Override
+ public void importGenericApplicationProperties(ADEPropertyCollection properties, AbstractFeature parent, long parentId, FeatureType parentType) throws CityGMLImportException, SQLException {
+ if (parent instanceof AbstractCityObject)
+ getImporter(CityObjectPropertiesImporter.class).doImport(properties, (AbstractCityObject) parent, parentId, parentType);
+ if (parent instanceof AbstractBuilding
+ && properties.containsOneOf(QualifiedHeightProperty.class,
+ QualifiedAreaProperty.class, QualifiedVolumeProperty.class, RefurbishmentMeasureProperty.class))
+ getImporter(BuildingPropertiesImporter.class).doImport(properties,(AbstractBuilding) parent, parentId, parentType);
+ }
+
+ @Override
+ public void executeBatch(String tableName) throws CityGMLImportException, SQLException {
+ ADETable adeTable = schemaMapper.fromTableName(tableName);
+ if (adeTable != null) {
+ ADEImporter importer = importers.get(adeTable.getImporterClass());
+ if (importer != null)
+ importer.executeBatch();
+ } else
+ throw new CityGMLImportException("The table " + tableName + " not managed by the ADE extension for '" + adeExtension.getMetadata().getIdentifier() + "'.");
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ for (ADEImporter importer : importers.values())
+ importer.close();
+ }
+
+ protected SchemaMapper getSchemaMapper() {
+ return schemaMapper;
+ }
+
+ protected T getImporter(Class type) throws CityGMLImportException, SQLException {
+ ADEImporter importer = importers.get(type);
+
+ if (importer == null) {
+ if(type== AbstractDeviceImporter.class)
+ importer = new AbstractDeviceImporter(connection, helper, this);
+ else if(type== CityObjectPropertiesImporter.class)
+ importer = new CityObjectPropertiesImporter(connection, helper, this);
+ else if(type== DeviceOperationImporter.class)
+ importer = new DeviceOperationImporter(connection, helper, this);
+ else if(type== TimeSeriesImporter.class)
+ importer = new TimeSeriesImporter(connection, helper, this);
+ else if(type== ResourceImporter.class)
+ importer = new ResourceImporter(connection, helper, this);
+// else if(type== WaterImporter.class)
+// importer = new WaterImporter(connection, helper, this);
+ else if(type == UrbanFunctionAreaImporter.class)
+ importer = new UrbanFunctionAreaImporter(connection, helper, this);
+ else if (type == WeatherStationImporter.class)
+ importer = new WeatherStationImporter(connection, helper, this);
+ else if (type == WeatherDataImporter.class)
+ importer = new WeatherDataImporter(connection, helper, this);
+ else if (type == RefurbishmentMeasureImporter.class)
+ importer = new RefurbishmentMeasureImporter(connection, helper, this);
+ else if (type == BuildingPropertiesImporter.class)
+ importer = new BuildingPropertiesImporter(connection, helper, this);
+ else if (type == AbstractQualifiedAttributeImporter.class)
+ importer = new AbstractQualifiedAttributeImporter(connection, helper, this);
+ else throw new SQLException("Failed to build ADE importer of type " + type.getName() + ".");
+
+
+ importers.put(type, importer);
+ }
+
+ return type.cast(importer);
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/RefurbishmentMeasureImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/RefurbishmentMeasureImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..45564cbe4c2f141e7f70e02c7bbc77845d9c76a4
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/RefurbishmentMeasureImporter.java
@@ -0,0 +1,93 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADESequence;
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import de.stuttgart.hft.ade.energy2.schema.SchemaMapper;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.RefurbishmentMeasure;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.sql.*;
+
+public class RefurbishmentMeasureImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+ private SchemaMapper schemaMapper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public RefurbishmentMeasureImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+ this.schemaMapper = manager.getSchemaMapper();
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.REFURBISHMENT_MEASURE)) + " " +
+ "(id, type, type_codespace, start_date, end_date, library_code, library_code_codespace, building_id, building_partition_id) " +
+ "values (?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(RefurbishmentMeasure refurbishmentMeasure, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ setRefurbishmentNull(refurbishmentMeasure);
+ if (refurbishmentMeasure.isSetType()) {
+ ps.setString(2, refurbishmentMeasure.getType().getValue());
+ ps.setString(3, refurbishmentMeasure.getType().getCodeSpace());
+ }
+ if (refurbishmentMeasure.isSetStartDate()) {
+ XMLGregorianCalendar xmlCal = refurbishmentMeasure.getStartDate();
+ Timestamp timestamp = new Timestamp(xmlCal.toGregorianCalendar().getTimeInMillis());
+ ps.setTimestamp(4, timestamp);
+ }
+ if (refurbishmentMeasure.isSetEndDate()) {
+ XMLGregorianCalendar xmlCal = refurbishmentMeasure.getEndDate();
+ Timestamp timestamp = new Timestamp(xmlCal.toGregorianCalendar().getTimeInMillis());
+ ps.setTimestamp(5, timestamp);
+ }
+ if (refurbishmentMeasure.isSetLibraryCode()) {
+ ps.setString(6, refurbishmentMeasure.getLibraryCode().getValue());
+ ps.setString(7, refurbishmentMeasure.getLibraryCode().getCodeSpace());
+ }
+
+ ps.setLong(8, foreignKeys.get("buildingId")); //building id
+ ps.setNull(9, Types.BIGINT); //building partionId is null
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(schemaMapper.getTableName(ADETable.REFURBISHMENT_MEASURE));
+ }
+
+ private void setRefurbishmentNull(RefurbishmentMeasure refurbishmentMeasure) throws SQLException {
+ ps.setNull(2, Types.VARCHAR); // type
+ ps.setNull(3, Types.VARCHAR); // type_codespace
+ ps.setNull(4, Types.DATE); // start_date
+ ps.setNull(5, Types.DATE); // end_date
+ ps.setNull(6, Types.VARCHAR); // library_code
+ ps.setNull(7, Types.VARCHAR); // library_code_codespace
+ ps.setNull(8, Types.BIGINT); // building_id
+ ps.setNull(9, Types.BIGINT); // building_partition_id
+ }
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/ResourceImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/ResourceImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..4661db3261afb1b952e418fbdc2ba87cb8f85901
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/ResourceImporter.java
@@ -0,0 +1,268 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.AbstractResource;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Collections;
+
+public class ResourceImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public ResourceImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement(
+ "INSERT INTO " + helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.RESOURCE)) +
+ "(id, objectclass_id, type, type_codespace, enduse, enduse_codespace, status, " +
+ "operation_type, operation_type_codespace, year, amount_type, amount_type_codespace, amount, " +
+ "amount_uom, time_series_id, is_amount_normalized, normalization_param, normalization_value, " +
+ "normalization_value_uom, co2_equivalent, co2_equivalent_uom, costs_money, costs_money_uom, " +
+ "yields_money, yields_money_uom, energy_carrier, energy_carrier_codespace, maximum_load, " +
+ "maximum_load_uom, source, source_codespace, is_dangerous, is_recyclable, cityobject_id) " +
+ "VALUES (" + String.join(", ", Collections.nCopies(34, "?")) + ")"
+ );
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(AbstractResource abstractResource, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+
+ setResourceToNull();
+ ps.setLong(1, objectId);
+ ps.setLong(2, objectType.getObjectClassId());
+ ps.setLong(34, foreignKeys.get("cityObjectId"));
+ setAbstractResourceProperties(abstractResource);
+
+ if (abstractResource instanceof Energy) {
+ Energy energy = (Energy) abstractResource;
+ if (energy.getEnergyTypeValue() != null) {
+ ps.setString(3, energy.getEnergyTypeValue().getValue());
+ ps.setString(4, energy.getEnergyTypeValue().getCodeSpace());
+ }
+ if (energy.getEnergyEndUseValue() != null) {
+ ps.setString(5, energy.getEnergyEndUseValue().getValue());
+ ps.setString(6, energy.getEnergyEndUseValue().getCodeSpace());
+ }
+ if (energy.getEnergyCarrierValue() != null) {
+ ps.setString(26, energy.getEnergyCarrierValue().getValue());
+ ps.setString(27, energy.getEnergyCarrierValue().getCodeSpace());
+ }
+ if (energy.getMaximumLoad() != null) {
+ ps.setDouble(28, energy.getMaximumLoad().getValue());
+ ps.setString(29, energy.getMaximumLoad().getUom());
+
+ }
+ if (energy.getEnergySourceValue() != null) {
+ ps.setString(30, energy.getEnergySourceValue().getValue());
+ ps.setString(31, energy.getEnergySourceValue().getCodeSpace());
+ }
+ } else if (abstractResource instanceof Water) {
+
+ Water water = (Water) abstractResource;
+ if (water.getWaterTypeValue() != null) {
+ ps.setString(3, water.getWaterTypeValue().getValue());
+ ps.setString(4, water.getWaterTypeValue().getCodeSpace());
+ }
+ if (water.getWaterEndUseValue() != null) {
+ ps.setString(5, water.getWaterEndUseValue().getValue());
+ ps.setString(6, water.getWaterEndUseValue().getCodeSpace());
+ }
+
+ } else if (abstractResource instanceof Waste) {
+ Waste waste = (Waste) abstractResource;
+ if (waste.getWasteTypeValue() != null) {
+ ps.setString(3, waste.getWasteTypeValue().getValue());
+ ps.setString(4, waste.getWasteTypeValue().getCodeSpace());
+ }
+ if (waste.getWasteEndUseValue() != null) {
+ ps.setString(5, waste.getWasteEndUseValue().getValue());
+ ps.setString(6, waste.getWasteEndUseValue().getCodeSpace());
+ }
+ if (waste.isSetAmountNormalized()) {
+ ps.setInt(32, 1); // True -> 1
+ }
+ if (waste.isRecyclable()) {
+ ps.setInt(33, 1);
+ }
+ } else if (abstractResource instanceof Food) {
+ Food food = (Food) abstractResource;
+ if (food.getFoodTypeValue() != null) {
+ ps.setString(3, food.getFoodTypeValue().getValue());
+ ps.setString(4, food.getFoodTypeValue().getCodeSpace());
+ }
+ if (food.getFoodEndUseValue() != null) {
+ ps.setString(5, food.getFoodEndUseValue().getValue());
+ ps.setString(6, food.getFoodEndUseValue().getCodeSpace());
+ }
+ } else if (abstractResource instanceof ConstructionMaterial) {
+
+ ConstructionMaterial constructionMaterial = (ConstructionMaterial) abstractResource;
+ if (constructionMaterial.getConstructionMaterialTypeValue() != null) {
+ ps.setString(3, constructionMaterial.getConstructionMaterialTypeValue().getValue());
+ ps.setString(4, constructionMaterial.getConstructionMaterialTypeValue().getCodeSpace());
+ }
+ if (constructionMaterial.getConstructionMaterialEndUseValue() != null) {
+ ps.setString(5, constructionMaterial.getConstructionMaterialEndUseValue().getValue());
+ ps.setString(6, constructionMaterial.getConstructionMaterialEndUseValue().getCodeSpace());
+ }
+ } else if (abstractResource instanceof OtherResource){
+ OtherResource otherResource = (OtherResource) abstractResource;
+ if (otherResource.getOtherResourceTypeValue() != null) {
+ ps.setString(3, otherResource.getOtherResourceTypeValue().getValue());
+ ps.setString(4, otherResource.getOtherResourceTypeValue().getCodeSpace());
+ }
+ if (otherResource.getOtherResourceEndUseValue() != null) {
+ ps.setString(5, otherResource.getOtherResourceEndUseValue().getValue());
+ ps.setString(6, otherResource.getOtherResourceEndUseValue().getCodeSpace());
+ }
+ } else if(abstractResource instanceof UrbanSpace){
+ UrbanSpace urbanSpace = (UrbanSpace) abstractResource;
+ if (urbanSpace.isSetType()){
+ ps.setString(3, urbanSpace.getType().getValue());
+ ps.setString(4, urbanSpace.getType().getCodeSpace());
+ }
+ if (urbanSpace.isSetEndUse()) {
+ ps.setString(5, urbanSpace.getEndUse().getValue());
+ ps.setString(6, urbanSpace.getEndUse().getCodeSpace());
+ }
+
+ }
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ private void setAbstractResourceProperties(AbstractResource abstractResource) throws SQLException, CityGMLImportException {
+
+ if (abstractResource.getStatus() != null) {
+ ps.setString(7, abstractResource.getStatus().value());
+ }
+
+ if (abstractResource.getOperationType() != null) {
+ ps.setString(8, abstractResource.getOperationType().getValue());
+ ps.setString(9, abstractResource.getOperationType().getCodeSpace());
+ }
+
+ if (abstractResource.getAmountType() != null) {
+ ps.setString(11, abstractResource.getAmountType().getValue());
+ ps.setString(12, abstractResource.getAmountType().getCodeSpace());
+ }
+
+ if (abstractResource.getAmount() != null) {
+ ps.setDouble(13, abstractResource.getAmount().getValue());
+ ps.setString(14, abstractResource.getAmount().getUom());
+ }
+
+ if (abstractResource.isSetTimeDependentAmount()){
+ long timeSeriesId = helper.importObject(abstractResource.getTimeDependentAmount().getAbstractTimeSeries(), null);
+ ps.setLong(15, timeSeriesId);
+
+ }
+
+ // Handling boolean-to-numeric conversion
+ if (abstractResource.isSetAmountNormalized()) {
+ ps.setInt(16, 1); // True -> 1
+ } else {
+ ps.setInt(16, 0);
+ }
+
+ if (abstractResource.getNormalizationValue() != null) {
+ ps.setDouble(18, abstractResource.getNormalizationValue().getValue());
+ ps.setString(19, abstractResource.getNormalizationValue().getUom());
+ }
+
+ if (abstractResource.getNormalizationParameter() != null) {
+ ps.setString(17, abstractResource.getNormalizationParameter());
+ }
+
+ if (abstractResource.getCo2Equivalent() != null) {
+ ps.setDouble(20, abstractResource.getCo2Equivalent().getValue());
+ ps.setString(21, abstractResource.getCo2Equivalent().getUom());
+ }
+
+ if (abstractResource.getYear() != null) {
+ ps.setInt(10, abstractResource.getYear());
+ }
+
+ if (abstractResource.getCostsMoney() != null) {
+ ps.setDouble(22, abstractResource.getCostsMoney().getValue());
+ ps.setString(23, abstractResource.getCostsMoney().getUom());
+ }
+
+ if (abstractResource.getYieldsMoney() != null) {
+ ps.setDouble(24, abstractResource.getYieldsMoney().getValue());
+ ps.setString(25, abstractResource.getYieldsMoney().getUom());
+ }
+ }
+
+ private void setResourceToNull() throws SQLException {
+
+ ps.setNull(1, Types.BIGINT); // id
+ ps.setNull(2, Types.INTEGER); // objectclass_id
+ ps.setNull(3, Types.VARCHAR); // type
+ ps.setNull(4, Types.VARCHAR); // type_codespace
+ ps.setNull(5, Types.VARCHAR); // enduse
+ ps.setNull(6, Types.VARCHAR); // enduse_codespace
+ ps.setNull(7, Types.VARCHAR); // status
+ ps.setNull(8, Types.VARCHAR); // operation_type
+ ps.setNull(9, Types.VARCHAR); // operation_type_codespace
+ ps.setNull(10, Types.INTEGER); // year
+ ps.setNull(11, Types.VARCHAR); // amount_type
+ ps.setNull(12, Types.VARCHAR); // amount_type_codespace
+ ps.setNull(13, Types.NUMERIC); // amount
+ ps.setNull(14, Types.VARCHAR); // amount_uom
+ ps.setNull(15, Types.BIGINT); // time_series_id
+ ps.setNull(16, Types.NUMERIC); // is_amount_normalized
+ ps.setNull(17, Types.VARCHAR); // normalization_param
+ ps.setNull(18, Types.NUMERIC); // normalization_value
+ ps.setNull(19, Types.VARCHAR); // normalization_value_uom
+ ps.setNull(20, Types.NUMERIC); // co2_equivalent
+ ps.setNull(21, Types.VARCHAR); // co2_equivalent_uom
+ ps.setNull(22, Types.NUMERIC); // costs_money
+ ps.setNull(23, Types.VARCHAR); // costs_money_uom
+ ps.setNull(24, Types.NUMERIC); // yields_money
+ ps.setNull(25, Types.NUMERIC); // yields_money_uom
+ ps.setNull(26, Types.VARCHAR); // energy_carrier
+ ps.setNull(27, Types.VARCHAR); // energy_carrier_codespace
+ ps.setNull(28, Types.NUMERIC); // maximum_load
+ ps.setNull(29, Types.VARCHAR); // maximum_load_uom
+ ps.setNull(30, Types.VARCHAR); // source
+ ps.setNull(31, Types.VARCHAR); // source_codespace
+ ps.setNull(32, Types.NUMERIC); // is_dangerous
+ ps.setNull(33, Types.NUMERIC); // is_recyclable
+ ps.setNull(34, Types.BIGINT); // cityobject_id
+
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/TimeSeriesImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/TimeSeriesImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..120ac5972349af9f12b2f11e9f76e02a4ba3c95c
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/TimeSeriesImporter.java
@@ -0,0 +1,276 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.AttributeValueJoiner;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+
+import java.sql.*;
+import java.time.LocalTime;
+import java.util.Collections;
+
+public class TimeSeriesImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private AttributeValueJoiner valueJoiner;
+ private PreparedStatement psTimeSeries;
+ private int batchCounter;
+
+ public TimeSeriesImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ String tableName = helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.TIME_SERIES));
+ String sql = "INSERT INTO " + tableName + " (" + getColumnNames() + ") VALUES (" + getPlaceholders(38) + ") ON CONFLICT (id) DO NOTHING";
+
+ psTimeSeries = connection.prepareStatement(sql);
+ valueJoiner = helper.getAttributeValueJoiner();
+ }
+
+ public void doImport(AbstractTimeSeries abstractTimeSeries, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+
+ setTimeSeriesToNull();
+ psTimeSeries.setLong(1, objectId);
+ psTimeSeries.setLong(2, objectType.getObjectClassId());
+ setAbstractTimeseriesProperties(abstractTimeSeries);
+ //contains weatherdata
+ if (abstractTimeSeries instanceof RegularTimeSeries) {
+ RegularTimeSeries regularTimeSeries = (RegularTimeSeries) abstractTimeSeries;
+
+ if (regularTimeSeries.isSetValues() && regularTimeSeries.getValues().isSetValue()) {
+ String values = valueJoiner.join(" ", regularTimeSeries.getValues().getValue());
+ psTimeSeries.setString(16, values);
+ psTimeSeries.setString(17, regularTimeSeries.getValues().getUom());
+ }
+ if (regularTimeSeries.isSetTemporalExtent()){
+ Timestamp beginPosition = Timestamp.from(regularTimeSeries.getTemporalExtent().getTimePeriod().getBeginPosition().toInstant());
+ Timestamp endPosition = Timestamp.from(regularTimeSeries.getTemporalExtent().getTimePeriod().getEndPosition().toInstant());
+ psTimeSeries.setTimestamp(7, beginPosition);
+ psTimeSeries.setTimestamp(8, endPosition);
+ }
+ if (regularTimeSeries.isSetTimeInterval()) {
+ psTimeSeries.setDouble(14, regularTimeSeries.getTimeInterval().getValue());
+ psTimeSeries.setString(15, regularTimeSeries.getTimeInterval().getUnit());
+ }
+ } else if (abstractTimeSeries instanceof RegularTimeSeriesFile) {
+
+ RegularTimeSeriesFile timeSeriesFile = (RegularTimeSeriesFile) abstractTimeSeries;
+ if (timeSeriesFile.isSetUom())
+ psTimeSeries.setString(18, timeSeriesFile.getUom());
+ if (timeSeriesFile.isSetFileURI())
+ psTimeSeries.setString(19, timeSeriesFile.getFileURI().toString());
+ if (timeSeriesFile.isSetNumberOfHeaderLines())
+ psTimeSeries.setLong(20, timeSeriesFile.getNumberOfHeaderLines());
+ if (timeSeriesFile.isSetFieldSeparator())
+ psTimeSeries.setString(21, timeSeriesFile.getFieldSeparator());
+ if (timeSeriesFile.isSetRecordSeparator() )
+ psTimeSeries.setString(22, timeSeriesFile.getRecordSeparator());
+ if (timeSeriesFile.isSetDecimalSymbol() )
+ psTimeSeries.setString(24, timeSeriesFile.getDecimalSymbol());
+ if (timeSeriesFile.isSetValueColumnNumber())
+ psTimeSeries.setLong(23, timeSeriesFile.getValueColumnNumber());
+ if (timeSeriesFile.isSetTemporalExtent()){
+ Timestamp beginPosition = Timestamp.from(timeSeriesFile.getTemporalExtent().getTimePeriod().getBeginPosition().toInstant());
+ Timestamp endPosition = Timestamp.from(timeSeriesFile.getTemporalExtent().getTimePeriod().getEndPosition().toInstant());
+ psTimeSeries.setTimestamp(7, beginPosition);
+ psTimeSeries.setTimestamp(8, endPosition);
+ }
+ if (timeSeriesFile.isSetTimeInterval()) {
+ psTimeSeries.setDouble(14, timeSeriesFile.getTimeInterval().getValue());
+ psTimeSeries.setString(15, timeSeriesFile.getTimeInterval().getUnit());
+ }
+ } else if (abstractTimeSeries instanceof TypicalValuesTimeSeries) {
+
+ TypicalValuesTimeSeries timeSeries = (TypicalValuesTimeSeries) abstractTimeSeries;
+
+ if (timeSeries.isSetStartTime()) {
+ psTimeSeries.setObject(9, timeSeries.getStartTime());
+ }
+ if (timeSeries.isSetStartDay()) {
+ psTimeSeries.setInt(10, timeSeries.getStartDay());
+ }
+ if (timeSeries.isSetStartMonth()) {
+ psTimeSeries.setInt(11, timeSeries.getStartMonth());
+ }
+ if (timeSeries.isSetValues() && timeSeries.getValues().isSetValue()) {
+ String values = valueJoiner.join(" ", timeSeries.getValues().getValue());
+ psTimeSeries.setString(16, values);
+ psTimeSeries.setString(17, timeSeries.getValues().getUom());
+ }
+ if (timeSeries.isSetTemporalExtent()){
+ psTimeSeries.setDouble(12, timeSeries.getTemporalExtent().getValue());
+ psTimeSeries.setString(13, timeSeries.getTemporalExtent().getUnit());
+ }
+ if (timeSeries.isSetTimeInterval()) {
+ psTimeSeries.setDouble(14, timeSeries.getTimeInterval().getValue());
+ psTimeSeries.setString(15, timeSeries.getTimeInterval().getUnit());
+ }
+ } else if (abstractTimeSeries instanceof TypicalValuesTimeSeriesFile) {
+ TypicalValuesTimeSeriesFile file = (TypicalValuesTimeSeriesFile) abstractTimeSeries;
+ if (file.isSetStartTime()) {
+ LocalTime localTime = file.getStartTime().toLocalTime();
+ Time sqlTime = Time.valueOf(localTime);
+ psTimeSeries.setTime(9, sqlTime);
+ }
+ if (file.isSetStartDay()) {
+ psTimeSeries.setInt(10, file.getStartDay());
+ }
+ if (file.isSetStartMonth()) {
+ psTimeSeries.setInt(11, file.getStartMonth());
+ }
+ if (file.isSetUom())
+ psTimeSeries.setString(18, file.getUom());
+ if (file.isSetFileURI())
+ psTimeSeries.setString(19, file.getFileURI().toString());
+
+ if (file.isSetTemporalExtent()){
+ psTimeSeries.setDouble(12, file.getTemporalExtent().getValue());
+ psTimeSeries.setString(13, file.getTemporalExtent().getUnit());
+ }
+ if (file.isSetTimeInterval()) {
+ psTimeSeries.setDouble(14, file.getTimeInterval().getValue());
+ psTimeSeries.setString(15, file.getTimeInterval().getUnit());
+ }
+ if (file.isSetNumberOfHeaderLines())
+ psTimeSeries.setLong(20, file.getNumberOfHeaderLines());
+ if (file.isSetFieldSeparator())
+ psTimeSeries.setString(21, file.getFieldSeparator());
+ if (file.isSetRecordSeparator())
+ psTimeSeries.setString(22, file.getRecordSeparator());
+ if (file.isSetDecimalSymbol())
+ psTimeSeries.setString(24, file.getDecimalSymbol());
+ if (file.isSetValueColumnNumber())
+ psTimeSeries.setInt(23, file.getValueColumnNumber());
+
+ } else if (abstractTimeSeries instanceof SensorConnection) {
+ SensorConnection sensorConnection = (SensorConnection) abstractTimeSeries;
+ if (sensorConnection.isSetTemporalExtent()) {
+ psTimeSeries.setDouble(12, sensorConnection.getTemporalExtent().getValue());
+ psTimeSeries.setString(13, sensorConnection.getTemporalExtent().getUnit());
+ }
+ if (sensorConnection.isSetConnectionType()) {
+ psTimeSeries.setString(28, sensorConnection.getConnectionType().getValue());
+ psTimeSeries.setString(27, sensorConnection.getConnectionType().getCodeSpace());
+ }
+ if (sensorConnection.isSetObservationProperty())
+ psTimeSeries.setString(36, sensorConnection.getObservationProperty());
+ if (sensorConnection.isSetUom())
+ psTimeSeries.setString(18, sensorConnection.getUom());
+ if (sensorConnection.isSetSensorID())
+ psTimeSeries.setString(37, sensorConnection.getSensorID());
+ if (sensorConnection.isSetSensorName())
+ psTimeSeries.setString(38, sensorConnection.getSensorName());
+ if (sensorConnection.isSetObservationID())
+ psTimeSeries.setString(35, sensorConnection.getObservationID());
+ if (sensorConnection.isSetObservationProperty())
+ psTimeSeries.setString(36, sensorConnection.getObservationProperty());
+ if (sensorConnection.isSetDataStreamID())
+ psTimeSeries.setString(30, sensorConnection.getDataStreamID());
+ if (sensorConnection.isSetBaseURL())
+ psTimeSeries.setString(27, sensorConnection.getBaseURL().toString());
+ if (sensorConnection.isSetAuthType())
+ psTimeSeries.setString(25, sensorConnection.getAuthType().getValue());
+ psTimeSeries.setString(26, sensorConnection.getAuthType().getCodeSpace());
+ if (sensorConnection.isSetMqtServer())
+ psTimeSeries.setString(33, sensorConnection.getMqtServer());
+ if (sensorConnection.isSetMqtTopic())
+ psTimeSeries.setString(34, sensorConnection.getMqtTopic());
+ if (sensorConnection.isSetLinkToObservation())
+ psTimeSeries.setString(31, sensorConnection.getLinkToObservation());
+ if (sensorConnection.isSetLinkToSensorDescription())
+ psTimeSeries.setString(32, sensorConnection.getLinkToSensorDescription());
+ }
+ psTimeSeries.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ private void setTimeSeriesToNull() throws SQLException {
+
+ psTimeSeries.setNull(1, Types.INTEGER); // id
+ psTimeSeries.setNull(2, Types.INTEGER); // objectclass_id
+ psTimeSeries.setNull(3, Types.VARCHAR); // acquisition_method
+ psTimeSeries.setNull(4, Types.VARCHAR); // acquisition_method_codespace
+ psTimeSeries.setNull(5, Types.VARCHAR); // interpolation_type
+ psTimeSeries.setNull(6, Types.VARCHAR); // source
+ psTimeSeries.setNull(7, Types.TIMESTAMP); // period_begin
+ psTimeSeries.setNull(8, Types.TIMESTAMP); // period_end
+ psTimeSeries.setNull(9, Types.TIME); // start_time
+ psTimeSeries.setNull(10, Types.INTEGER); // start_day
+ psTimeSeries.setNull(11, Types.INTEGER); // start_month
+ psTimeSeries.setNull(12, Types.NUMERIC); // temporal_extent
+ psTimeSeries.setNull(13, Types.VARCHAR); // temporal_extent_unit
+ psTimeSeries.setNull(14, Types.NUMERIC); // time_interval
+ psTimeSeries.setNull(15, Types.VARCHAR); // time_interval_unit
+ psTimeSeries.setNull(16, Types.VARCHAR); // values_list
+ psTimeSeries.setNull(17, Types.VARCHAR); // values_list_uom
+ psTimeSeries.setNull(18, Types.VARCHAR); // uom
+ psTimeSeries.setNull(19, Types.VARCHAR); // file_uri
+ psTimeSeries.setNull(20, Types.INTEGER); // num_of_header_lines
+ psTimeSeries.setNull(21, Types.VARCHAR); // field_separator
+ psTimeSeries.setNull(22, Types.VARCHAR); // record_separator
+ psTimeSeries.setNull(23, Types.INTEGER); // value_column_number
+ psTimeSeries.setNull(24, Types.VARCHAR); // decimal_symbol
+ psTimeSeries.setNull(25, Types.VARCHAR); // auth_type
+ psTimeSeries.setNull(26, Types.VARCHAR); // auth_type_codespace
+ psTimeSeries.setNull(27, Types.VARCHAR); // base_url
+ psTimeSeries.setNull(28, Types.VARCHAR); // connection_type
+ psTimeSeries.setNull(29, Types.VARCHAR); // connection_type_codespace
+ psTimeSeries.setNull(30, Types.VARCHAR); // datastream_id
+ psTimeSeries.setNull(31, Types.VARCHAR); // link_to_observation
+ psTimeSeries.setNull(32, Types.VARCHAR); // link_to_sensor_description
+ psTimeSeries.setNull(33, Types.VARCHAR); // mqtt_server
+ psTimeSeries.setNull(34, Types.VARCHAR); // mqtt_topic
+ psTimeSeries.setNull(35, Types.VARCHAR); // observation_id
+ psTimeSeries.setNull(36, Types.VARCHAR); // observation_property
+ psTimeSeries.setNull(37, Types.VARCHAR); // sensor_id
+ psTimeSeries.setNull(38, Types.VARCHAR); // sensor_name
+
+ }
+
+ private void setAbstractTimeseriesProperties(AbstractTimeSeries abstractTimeSeries) throws SQLException {
+
+ if (abstractTimeSeries.isSetAcquisitionMethod()) {
+ psTimeSeries.setString(3, abstractTimeSeries.getAcquisitionMethod().getValue());
+ psTimeSeries.setString(4, abstractTimeSeries.getAcquisitionMethod().getCodeSpace());
+ }
+ if (abstractTimeSeries.isSetInterpolationTypeValue())
+ psTimeSeries.setString(5, abstractTimeSeries.getInterpolationTypeValue().value());
+ if (abstractTimeSeries.isSetSource())
+ psTimeSeries.setString(6, abstractTimeSeries.getSource());
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ psTimeSeries.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ psTimeSeries.close();
+ }
+
+ private String getColumnNames() {
+ return "id, objectclass_id, acquisition_method, acquisition_method_codespace, interpolation_type, source, " +
+ "period_begin, period_end, start_time, start_day, start_month, temporal_extent, temporal_extent_unit, " +
+ "time_interval, time_interval_unit, values_list, values_list_uom, uom, file_uri, num_of_header_lines, " +
+ "field_separator, record_separator, value_column_number, decimal_symbol, auth_type, auth_type_codespace, " +
+ "base_url, connection_type, connection_type_codespace, datastream_id, link_to_observation, " +
+ "link_to_sensor_description, mqtt_server, mqtt_topic, observation_id, observation_property, " +
+ "sensor_id, sensor_name";
+ }
+
+ private String getPlaceholders(int count) {
+ return String.join(",", Collections.nCopies(count, "?"));
+ }
+
+ }
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/UrbanFunctionAreaImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/UrbanFunctionAreaImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..571a0b71125d2516a53a0974df155d8cf423b3d9
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/UrbanFunctionAreaImporter.java
@@ -0,0 +1,75 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.supportingClasses.UrbanFunctionArea;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+public class UrbanFunctionAreaImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public UrbanFunctionAreaImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.URBAN_FUNCTION_AREA)) + " " +
+ "(id, type, type_codespace, code, code_codespace) " +
+ "values (?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(UrbanFunctionArea urbanFunctionArea, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+ setUrbanFunctionAreaNull();
+ if (urbanFunctionArea.isSetType()) {
+ ps.setString(2, urbanFunctionArea.getType().getValue());
+ ps.setString(3, urbanFunctionArea.getType().getCodeSpace());
+ }
+ if (urbanFunctionArea.isSetCode()){
+ ps.setString(4, urbanFunctionArea.getCode().getValue());
+ ps.setString(5, urbanFunctionArea.getCode().getCodeSpace());
+ }
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+
+ }
+
+ private void setUrbanFunctionAreaNull() throws SQLException {
+ ps.setNull(2, Types.VARCHAR); // type
+ ps.setNull(3, Types.VARCHAR); // type_codespace
+ ps.setNull(4, Types.VARCHAR); // code
+ ps.setNull(5, Types.VARCHAR); // code_codespace
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/UtilityNetworkConnectionImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/UtilityNetworkConnectionImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..aeff0488c2833e12aae15024b2f6a6dc4b8dec98
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/UtilityNetworkConnectionImporter.java
@@ -0,0 +1,89 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.UtilityNetworkConnection;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class UtilityNetworkConnectionImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public UtilityNetworkConnectionImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement("INSERT INTO " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.UTL_NTW_CONNECTION)) + " " +
+ "(id, network_type, network_type_codespace, connection_status, function_in_network, " +
+ "function_in_network_codespace, usage_in_network, usage_in_network_codespace, " +
+ "network_id, network_node_id, cityobject_id) " +
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(UtilityNetworkConnection networkConnection, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ if (networkConnection.isSetType()) {
+ ps.setString(2, networkConnection.getNetworkType().getValue());
+ ps.setString(3, networkConnection.getNetworkType().getCodeSpace());
+ }
+
+ if (networkConnection.isSetConnectionStatus()) {
+ ps.setString(4, networkConnection.getConnectionStatus().toString());
+ }
+
+ if (networkConnection.isSetFunctionInNetwork()) {
+ ps.setString(5, networkConnection.getFunctionInNetwork().getValue());
+ ps.setString(6, networkConnection.getFunctionInNetwork().getCodeSpace());
+ }
+
+ if (networkConnection.isSetUsageInNetwork()) {
+ ps.setString(7, networkConnection.getUsageInNetwork().getValue());
+ ps.setString(8, networkConnection.getUsageInNetwork().getCodeSpace());
+ }
+
+ if (networkConnection.isSetNetworkID()) {
+ ps.setString(9, networkConnection.getNetworkID());
+ }
+
+ if (networkConnection.isSetNetworkNodeID()) {
+ ps.setString(10, networkConnection.getNetworkNodeID());
+ }
+
+ //set correctly
+ ps.setLong(11, objectType.getObjectClassId());
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherDataImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherDataImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..ddf69cd7d2e144794d42d152fe24722e803f6ace
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherDataImporter.java
@@ -0,0 +1,123 @@
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.core.ReferencePointProperty;
+import org.citygml4j.ade.energy.model.core.WeatherData;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeries;
+import org.citygml4j.ade.energy.model.supportingClasses.AbstractTimeSeriesProperty;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+public class WeatherDataImporter implements ADEImporter {
+
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public WeatherDataImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws SQLException {
+
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.WEATHER_DATA)) + " " +
+ "(id, type, type_codespace, value_type, value_type_codespace, yearly_value, yearly_value_uom, library_code, library_code_codespace, time_series_id, cityObject_id, position) " +
+ "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(WeatherData weatherData, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ long cityObjectId = foreignKeys.get("cityObjectId");
+ setWeatherDataNull(weatherData);
+
+ ps.setLong(1, objectId);
+
+ if(weatherData.isSetType()){
+ ps.setString(2, weatherData.getType().getValue());
+ ps.setString(3, weatherData.getType().getCodeSpace());
+ }
+
+ if (weatherData.isSetValueType()){
+ ps.setString(4, weatherData.getValueType().getValue());
+ ps.setString(5, weatherData.getValueType().getCodeSpace());
+ }
+
+ if (weatherData.isSetYearlyValue()){
+ ps.setDouble(6, weatherData.getYearlyValue().getValue());
+ ps.setString(7, weatherData.getYearlyValue().getUom());
+ }
+
+ if (weatherData.isSetLibraryCode()){
+ ps.setString(8, weatherData.getLibraryCode().getValue());
+ ps.setString(9, weatherData.getLibraryCode().getCodeSpace());
+ }
+
+ if (cityObjectId != 0) {
+ ps.setLong(11, cityObjectId);
+ }
+
+ if (weatherData.isSetPosition()){
+
+ GeometryObject geometryObject = null;
+ ReferencePointProperty referencePoint = weatherData.getPosition();
+ if (referencePoint != null && referencePoint.isSetValue())
+ geometryObject = helper.getGeometryConverter().getPoint(referencePoint.getValue());
+ if (geometryObject != null)
+ ps.setObject(12, helper.getDatabaseAdapter().getGeometryConverter().getDatabaseObject(geometryObject, connection));
+ else
+ ps.setNull(12, helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryType(),
+ helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryTypeName());
+ }
+
+ if (weatherData.getTimeDependentValues() != null){
+ long timeSeriesId = helper.importObject(weatherData.getTimeDependentValues().getAbstractTimeSeries(), null);
+ ps.setLong(10, timeSeriesId);
+ }
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+ }
+
+ public void setWeatherDataNull(WeatherData weatherData) throws SQLException {
+ ps.setNull(1, Types.INTEGER);
+ ps.setNull(2, Types.VARCHAR);
+ ps.setNull(3, Types.VARCHAR);
+ ps.setNull(4, Types.VARCHAR);
+ ps.setNull(5, Types.VARCHAR);
+ ps.setNull(6, Types.BIGINT);
+ ps.setNull(7, Types.VARCHAR);
+ ps.setNull(8, Types.VARCHAR);
+ ps.setNull(9, Types.VARCHAR);
+ ps.setNull(10, Types.BIGINT);
+ ps.setNull(11, Types.BIGINT);
+ ps.setNull(12, Types.BINARY);
+ }
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherStationImporter.java b/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherStationImporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..238edaf0b96b613f16b27cfd9fa2fd4fd3f7c843
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/importer/WeatherStationImporter.java
@@ -0,0 +1,94 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.importer;
+
+import de.stuttgart.hft.ade.energy2.schema.ADETable;
+import org.citydb.config.geometry.GeometryObject;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citydb.core.ade.importer.CityGMLImportHelper;
+import org.citydb.core.ade.importer.ForeignKeys;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.operation.importer.CityGMLImportException;
+import org.citydb.core.operation.importer.util.GeometryConverter;
+import org.citygml4j.ade.energy.model.supportingClasses.WeatherStation;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class WeatherStationImporter implements ADEImporter {
+ private final Connection connection;
+ private final CityGMLImportHelper helper;
+
+ private GeometryConverter geometryConverter;
+ private PreparedStatement ps;
+ private int batchCounter;
+
+ public WeatherStationImporter(Connection connection, CityGMLImportHelper helper, ImportManager manager) throws CityGMLImportException, SQLException {
+ this.connection = connection;
+ this.helper = helper;
+
+ ps = connection.prepareStatement("insert into " +
+ helper.getTableNameWithSchema(manager.getSchemaMapper().getTableName(ADETable.CITYOBJECT)) + " " +
+ "(id, ref_point) " +
+ "values (?, ?)");
+
+ geometryConverter = helper.getGeometryConverter();
+ }
+
+ public void doImport(WeatherStation weatherStation, long objectId, AbstractObjectType> objectType, ForeignKeys foreignKeys) throws CityGMLImportException, SQLException {
+ ps.setLong(1, objectId);
+
+ GeometryObject geometryObject = null;
+
+ if (geometryObject != null)
+ ps.setObject(2, helper.getDatabaseAdapter().getGeometryConverter().getDatabaseObject(geometryObject, connection));
+ else
+ ps.setNull(2, helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryType(),
+ helper.getDatabaseAdapter().getGeometryConverter().getNullGeometryTypeName());
+
+ ps.addBatch();
+ if (++batchCounter == helper.getDatabaseAdapter().getMaxBatchSize())
+ helper.executeBatch(objectType);
+
+ }
+
+ @Override
+ public void executeBatch() throws CityGMLImportException, SQLException {
+ if (batchCounter > 0) {
+ ps.executeBatch();
+ batchCounter = 0;
+ }
+ }
+
+ @Override
+ public void close() throws CityGMLImportException, SQLException {
+ ps.close();
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADESequence.java b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADESequence.java
new file mode 100644
index 0000000000000000000000000000000000000000..de2a2c2214755e83bffb33a6d771553eb44494f2
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADESequence.java
@@ -0,0 +1,43 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.schema;
+
+public enum ADESequence {
+ VOLUMETYPE_SEQ,
+ FLOORAREA_SEQ,
+ QUALIFIED_ATTRIBUTE_SEQ,
+ HEATEXCHANGETYPE_SEQ,
+ TRANSMITTANCE_SEQ,
+ OPTICALPROPERTIES_SEQ,
+ REFLECTANCE_SEQ,
+ TIMEVALUESPROPERTI_SEQ,
+ PERIODOFYEAR_SEQ,
+ DAILYSCHEDULE_SEQ,
+ REFURBISHMENT_MEASURE_SEQ
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADETable.java b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADETable.java
new file mode 100644
index 0000000000000000000000000000000000000000..43f11d65fbe30906ed2babc1ddc76e0c8d209ee6
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ADETable.java
@@ -0,0 +1,88 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.schema;
+
+import de.stuttgart.hft.ade.energy2.importer.*;
+import org.citydb.core.ade.importer.ADEImporter;
+import org.citygml4j.ade.energy.model.core.AbstractQualifiedAttribute;
+
+public enum ADETable {
+ ADDRESS_TO_BUILDING_UNIT(null),
+ BUILDING(BuildingPropertiesImporter.class),
+ BUILDING_PARTITION(null),
+ CITYOBJECT(CityObjectPropertiesImporter.class),
+ CTYOBJ_RELATION(null),
+ DEVICE(AbstractDeviceImporter.class),
+ DEVICE_OPERATION(DeviceOperationImporter.class),
+ ENERGY_PERF_CERT(EnergyPerformanceCertificateImporter.class),
+ FACILITIES(null),
+ HEAT_EXCHANGE_TYPE(null),
+ IMAGE_TEXTURE(null),
+ LAYERED_CONSTRUCTION(null),
+ LAYER_COMPONENT(null),
+ LAYER(null),
+ LIBRARY(null),
+ MATERIAL(null),
+ OCCUPANTS(null),
+ OPENING(null),
+ OPTICAL_PROPERTY(null),
+ PERIOD_OF_YEAR(null),
+ QUALIFIED_ATTRIBUTE(AbstractQualifiedAttributeImporter.class),
+ RESOURCE(ResourceImporter.class),
+ REFURBISHMENT_MEASURE(RefurbishmentMeasureImporter.class),
+ SCHEDULE(null),
+ SYSTEM_OPERATION(null),
+ SOLAR_COLLECTOR(null),
+ STORAGE_SYSTEM(null),
+ STORAGE_DEVICE(null),
+ SENSOR_CONNECTION(null),
+ SOLAR_ENERGY_SYSTEM(null),
+ SUITABILITY(null),
+ SCHEDULE_COMPONENT(null),
+ THERMAL_BOUNDARY(null),
+ THERMAL_OPENING(null),
+ THEM_SURF_TO_THERMAL_ZONE(null),
+ THEMATIC_SURFACE(null),
+ THERMAL_ZONE(null),
+ TIME_SERIES(TimeSeriesImporter.class),
+ URBAN_FUNCTION_AREA(UrbanFunctionAreaImporter.class),
+ USAGE_ZONE(null),
+ UTL_NTW_CONNECTION(UtilityNetworkConnectionImporter.class),
+ WEATHER_DATA(WeatherDataImporter.class);
+
+ private Class extends ADEImporter> importerClass;
+
+ ADETable(Class extends ADEImporter> importerClass) {
+ this.importerClass = importerClass;
+ }
+
+ public Class extends ADEImporter> getImporterClass() {
+ return importerClass;
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/schema/ObjectMapper.java b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ObjectMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..4463ee2c8f6afc36020c5887c35f2465fe9e0f2f
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/schema/ObjectMapper.java
@@ -0,0 +1,140 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.schema;
+
+import org.citydb.core.ade.ADEExtensionException;
+import org.citydb.core.ade.ADEObjectMapper;
+import org.citydb.core.database.schema.mapping.AbstractObjectType;
+import org.citydb.core.database.schema.mapping.SchemaMapping;
+import org.citygml4j.ade.energy.model.core.*;
+import org.citygml4j.ade.energy.model.supportingClasses.*;
+import org.citygml4j.model.gml.base.AbstractGML;
+import org.citygml4j.model.module.citygml.CityGMLVersion;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class ObjectMapper implements ADEObjectMapper {
+ private Map, Integer> objectClassIds = new HashMap<>();
+
+ public void populateObjectClassIds(SchemaMapping schemaMapping) throws ADEExtensionException {
+ for (AbstractObjectType> type : schemaMapping.getAbstractObjectTypes()) {
+ int objectClassId = type.getObjectClassId();
+
+ switch (type.getPath()) {
+ case "AbstractSchedule":
+ objectClassIds.put(AbstractSchedule.class, objectClassId);
+ break;
+ case "AbstractTimeSeries":
+ objectClassIds.put(AbstractTimeSeries.class, objectClassId);
+ break;
+ case "RegularTimeSeries":
+ objectClassIds.put(RegularTimeSeries.class, objectClassId);
+ break;
+ case "RegularTimeSeriesFile":
+ objectClassIds.put(RegularTimeSeriesFile.class, objectClassId);
+ break;
+ case "TypicalValuesTimeSeries":
+ objectClassIds.put(TypicalValuesTimeSeries.class, objectClassId);
+ break;
+ case "TypicalValuesTimeSeriesFile":
+ objectClassIds.put(TypicalValuesTimeSeriesFile.class, objectClassId);
+ break;
+ case "SensorConnection":
+ objectClassIds.put(SensorConnection.class, objectClassId);
+ break;
+ case "AbstractResource":
+ objectClassIds.put(AbstractResource.class, objectClassId);
+ case "UrbanFunctionArea":
+ objectClassIds.put(UrbanFunctionArea.class, objectClassId);
+ break;
+ case "RefurbishmentMeasure":
+ objectClassIds.put(RefurbishmentMeasure.class, objectClassId);
+ break;
+ case "WeatherData":
+ objectClassIds.put(WeatherData.class, objectClassId);
+ break;
+ case "WeatherStation":
+ objectClassIds.put(WeatherStation.class, objectClassId);
+ break;
+ case "Water":
+ objectClassIds.put(Water.class, objectClassId);
+ break;
+ case "Energy":
+ objectClassIds.put(Energy.class, objectClassId);
+ break;
+ case "AbstractDevice":
+ objectClassIds.put(AbstractDevice.class, objectClassId);
+ case "DeviceOperation":
+ objectClassIds.put(DeviceOperation.class, objectClassId);
+ break;
+ case "UtilityNetworkConnection":
+ objectClassIds.put(UtilityNetworkConnection.class, objectClassId);
+ break;
+ case "AbstractBuilding":
+ objectClassIds.put(AbstractBuilding.class, objectClassId);
+ break;
+ case "QualifiedVolume":
+ objectClassIds.put(QualifiedVolume.class, objectClassId);
+ break;
+ case "QualifiedHeight":
+ objectClassIds.put(QualifiedHeight.class, objectClassId);
+ break;
+ case "QualifiedArea":
+ objectClassIds.put(QualifiedArea.class, objectClassId);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public AbstractGML createObject(int objectClassId, CityGMLVersion version) {
+ if (version == CityGMLVersion.v2_0_0) {
+ for (Entry, Integer> entry : objectClassIds.entrySet()) {
+ if (entry.getValue() == objectClassId) {
+ try {
+ return entry.getKey().getDeclaredConstructor().newInstance();
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
+ InvocationTargetException e) {
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public int getObjectClassId(Class extends AbstractGML> adeObjectClass) {
+ Integer objectClassId = objectClassIds.get(adeObjectClass);
+ return objectClassId != null ? objectClassId : 0;
+ }
+}
diff --git a/src/main/java/de/stuttgart/hft/ade/energy2/schema/SchemaMapper.java b/src/main/java/de/stuttgart/hft/ade/energy2/schema/SchemaMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f7746f7d9bcbf27829996e9b3b245b232535a32
--- /dev/null
+++ b/src/main/java/de/stuttgart/hft/ade/energy2/schema/SchemaMapper.java
@@ -0,0 +1,64 @@
+/*
+ * 3D City Database - The Open Source CityGML Database
+ * https://www.3dcitydb.org/
+ *
+ * Copyright 2013 - 2024
+ * Chair of Geoinformatics
+ * Technical University of Munich, Germany
+ * https://www.lrg.tum.de/gis/
+ *
+ * The 3D City Database is jointly developed with the following
+ * cooperation partners:
+ *
+ * Virtual City Systems, Berlin
+ * M.O.S.S. Computer Grafik Systeme GmbH, Taufkirchen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.stuttgart.hft.ade.energy2.schema;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+public class SchemaMapper {
+ private EnumMap tableNames = new EnumMap<>(ADETable.class);
+ private EnumMap sequenceNames = new EnumMap<>(ADESequence.class);
+
+ public void populateSchemaNames(String prefix) {
+ for (ADETable table : ADETable.values())
+ tableNames.put(table, prefix + "_" + table.toString().toLowerCase());
+
+ for (ADESequence sequence : ADESequence.values())
+ sequenceNames.put(sequence, prefix + "_" + sequence.toString().toLowerCase());
+ }
+
+ public String getTableName(ADETable table) {
+ return tableNames.get(table);
+ }
+
+ public ADETable fromTableName(String tableName) {
+ tableName = tableName.toLowerCase();
+
+ for (Map.Entry entry : tableNames.entrySet()) {
+ if (entry.getValue().equals(tableName))
+ return entry.getKey();
+ }
+
+ return null;
+ }
+
+ public String getSequenceName(ADESequence sequence) {
+ return sequenceNames.get(sequence);
+ }
+}
diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..f60b961e2594b8127a0dc3e99829138e616d7fcb
--- /dev/null
+++ b/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: de.stuttgart.hft.EnergyADEExtension
+
diff --git a/src/main/resources/services/org.citydb.core.ade.ADEExtension b/src/main/resources/services/org.citydb.core.ade.ADEExtension
new file mode 100644
index 0000000000000000000000000000000000000000..70ec67016b232da19eaa9c7cb1d824c9fff995ab
--- /dev/null
+++ b/src/main/resources/services/org.citydb.core.ade.ADEExtension
@@ -0,0 +1 @@
+de.stuttgart.hft.EnergyADEExtension
\ No newline at end of file