"561698 -  Merge 'org.eclipse.mdm.api.odsadapter/mkoller/contrib' into 'mkoller/contrib'"

Signed-off-by: Simon Skoczylas <simon.skoczylas@karakun.com>
diff --git a/org.eclipse.mdm.api.odsadapter/.gitignore b/org.eclipse.mdm.api.odsadapter/.gitignore
new file mode 100644
index 0000000..12a6d10
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/.gitignore
@@ -0,0 +1,18 @@
+# eclipse
+.classpath
+.project
+.settings/
+bin/
+src/gen/
+
+# gradle
+.gradle
+build/
+
+# intellij
+.idea/
+out/
+*.ipr
+*.iml
+*.iws
+/bin/
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/LICENSE.txt b/org.eclipse.mdm.api.odsadapter/LICENSE.txt
new file mode 100644
index 0000000..e48e096
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/LICENSE.txt
@@ -0,0 +1,277 @@
+Eclipse Public License - v 2.0
+
+    THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+    PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+    OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a) in the case of the initial Contributor, the initial content
+     Distributed under this Agreement, and
+
+  b) in the case of each subsequent Contributor:
+     i) changes to the Program, and
+     ii) additions to the Program;
+  where such changes and/or additions to the Program originate from
+  and are Distributed by that particular Contributor. A Contribution
+  "originates" from a Contributor if it was added to the Program by
+  such Contributor itself or anyone acting on such Contributor's behalf.
+  Contributions do not include changes or additions to the Program that
+  are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+  a) Subject to the terms of this Agreement, each Contributor hereby
+  grants Recipient a non-exclusive, worldwide, royalty-free copyright
+  license to reproduce, prepare Derivative Works of, publicly display,
+  publicly perform, Distribute and sublicense the Contribution of such
+  Contributor, if any, and such Derivative Works.
+
+  b) Subject to the terms of this Agreement, each Contributor hereby
+  grants Recipient a non-exclusive, worldwide, royalty-free patent
+  license under Licensed Patents to make, use, sell, offer to sell,
+  import and otherwise transfer the Contribution of such Contributor,
+  if any, in Source Code or other form. This patent license shall
+  apply to the combination of the Contribution and the Program if, at
+  the time the Contribution is added by the Contributor, such addition
+  of the Contribution causes such combination to be covered by the
+  Licensed Patents. The patent license shall not apply to any other
+  combinations which include the Contribution. No hardware per se is
+  licensed hereunder.
+
+  c) Recipient understands that although each Contributor grants the
+  licenses to its Contributions set forth herein, no assurances are
+  provided by any Contributor that the Program does not infringe the
+  patent or other intellectual property rights of any other entity.
+  Each Contributor disclaims any liability to Recipient for claims
+  brought by any other entity based on infringement of intellectual
+  property rights or otherwise. As a condition to exercising the
+  rights and licenses granted hereunder, each Recipient hereby
+  assumes sole responsibility to secure any other intellectual
+  property rights needed, if any. For example, if a third party
+  patent license is required to allow Recipient to Distribute the
+  Program, it is Recipient's responsibility to acquire that license
+  before distributing the Program.
+
+  d) Each Contributor represents that to its knowledge it has
+  sufficient copyright rights in its Contribution, if any, to grant
+  the copyright license set forth in this Agreement.
+
+  e) Notwithstanding the terms of any Secondary License, no
+  Contributor makes additional grants to any Recipient (other than
+  those set forth in this Agreement) as a result of such Recipient's
+  receipt of the Program under the terms of a Secondary License
+  (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+  a) the Program must also be made available as Source Code, in
+  accordance with section 3.2, and the Contributor must accompany
+  the Program with a statement that the Source Code for the Program
+  is available under this Agreement, and informs Recipients how to
+  obtain it in a reasonable manner on or through a medium customarily
+  used for software exchange; and
+
+  b) the Contributor may Distribute the Program under a license
+  different than this Agreement, provided that such license:
+     i) effectively disclaims on behalf of all other Contributors all
+     warranties and conditions, express and implied, including
+     warranties or conditions of title and non-infringement, and
+     implied warranties or conditions of merchantability and fitness
+     for a particular purpose;
+
+     ii) effectively excludes on behalf of all other Contributors all
+     liability for damages, including direct, indirect, special,
+     incidental and consequential damages, such as lost profits;
+
+     iii) does not attempt to limit or alter the recipients' rights
+     in the Source Code under section 3.2; and
+
+     iv) requires any subsequent distribution of the Program by any
+     party to be under a license that satisfies the requirements
+     of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+  a) it must be made available under this Agreement, or if the
+  Program (i) is combined with other material in a separate file or
+  files made available under a Secondary License, and (ii) the initial
+  Contributor attached to the Source Code the notice described in
+  Exhibit A of this Agreement, then the Program may be made available
+  under the terms of such Secondary Licenses, and
+
+  b) a copy of this Agreement must be included with each copy of
+  the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+Exhibit A - Form of Secondary Licenses Notice
+
+"This Source Code may also be made available under the following
+Secondary Licenses when the conditions for such availability set forth
+in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+version(s), and exceptions or additional permissions here}."
+
+  Simply including a copy of this Agreement, including this Exhibit A
+  is not sufficient to license the Source Code under Secondary Licenses.
+
+  If it is not possible or desirable to put the notice in a particular
+  file, then You may include the notice in a location (such as a LICENSE
+  file in a relevant directory) where a recipient would be likely to
+  look for such a notice.
+
+  You may add additional accurate notices of copyright ownership.
diff --git a/org.eclipse.mdm.api.odsadapter/NOTICE.txt b/org.eclipse.mdm.api.odsadapter/NOTICE.txt
new file mode 100644
index 0000000..56281c6
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/NOTICE.txt
@@ -0,0 +1,382 @@
+# Notices for Eclipse MDM|BL
+
+This content is produced and maintained by the Eclipse MDM|BL project,
+it is a project of the openMDM(R) Eclipse Working Group.
+
+* Project home: https://projects.eclipse.org/projects/technology.mdmbl
+
+## Trademarks
+
+Eclipse MDM|BL, MDM|BL and Eclipse openMDM(R) logo are registered trademarks
+of the Eclipse Foundation.
+
+## Copyright
+
+All content is the property of the following respective authors or their employers.
+For more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+Copyright (c) 2016-2019 Gigatronik Ingolstadt GmbH
+Copyright (c) 2016-2020 Peak Solution GmbH
+Copyright (c) 2017-2018 science + computing AG Tuebingen (ATOS SE)
+Copyright (c) 2017-2018 Canoo Engineering AG
+Copyright (c) 2017 Florian Schmitt
+Copyright (c) 2017-2020 Angelika Wittek
+Copyright (c) 2018-2019 Elektronische Fahrwerksysteme GMBH
+Copyright (c) 2018-2020 Karakun AG
+Copyright (c) 2018-2020 Alexander Nehmer
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v. 2.0 which is available at
+http://www.eclipse.org/legal/epl-2.0.
+
+SPDX-License-Identifier: EPL-2.0
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+org.eclipse.mdm.api.base.git	    - The openMDM(R) API.
+org.eclipse.mdm.api.default.git	    - Extension of the openMDM(R) API containing default elements.
+org.eclipse.mdm.api.odsadapter.git	- ODS implementation of persistence adapter.
+org.eclipse.mdm.nucleus.git	        - Core building blocks for the openMDM Business Logic and Web Frontend.
+
+## Third-party Content
+
+The Content includes items that have been sourced from third parties as set out below.
+If you did not receive this Content directly from the Eclipse Foundation, the following
+is provided for informational purposes only, and you should look to
+the Redistributor's license for terms and conditions of use.
+
+antlr4-4.5.3.jar(2.5.3)
+    * License: New BSD license
+
+aopalliance-repackaged-2.5.0-b05.jar (2.5.0-b05)
+    * License: CDDL
+
+commons-codec-1.2.jar (1.2)
+    * License: Apache License, 2.0
+
+commons-httpclient-3.1.jar  (3.1)
+    * License: Apache License, 2.0
+
+commons-lang3-3.8.1.jar (3.8.1)
+    * License: Apache License, 2.0
+
+commons-text-1.6.jar (1.6)
+    * License: Apache License, 2.0
+
+gson-2.7.jar (2.7)
+    * License: Apache License, 2.0
+
+Google Guava Version: 25.0-jre  (25.0)
+    * License: Apache License, 2.0
+
+Gradle Wrapper (4.10.2)
+    * License: Apache License, 2.0
+
+hk2-api-2.5.0-b05.jar (2.5.0-b05)
+    * License: CDDL-1.1
+
+hk2-locator-2.5.0-b05.jar(2.5.0-b05)
+    * License: CDDL
+
+hk2-utils-2.5.0-b05.jar (2.5.0-b05)
+    * License: CDDL
+
+jackson-annotations-2.9.0.jar  (2.9.0)
+    * License: Apache License, 2.0
+
+jackson-core-2.9.2.jar(2.9.2)
+    * License: Apache License, 2.0
+
+jackson-databind-2.9.2.jar  (2.9.2)
+    * License: Apache License, 2.0
+
+jackson-jaxrs-base-2.9.2.jar(2.9.2)
+    * License: Apache License, 2.0
+
+jackson-jaxrs-json-provider-2.9.2.jar(2.9.2)
+    * License: Apache License, 2.0
+
+jackson-module-jaxb-annotations-2.9.2.jar  (2.9.2)
+    * License: Apache License, 2.0
+
+javassist-3.20.0-GA.jar  (2.20.0-GA)
+    * License: Apache 2.0
+
+jcl-over-slf4j-1.7.25.jar(1.7.25)
+    * License: MIT License
+    * Licence Path: https://www.slf4j.org/license.html
+    * Project URL:  https://www.slf4j.org
+    * Source URL:   https://github.com/qos-ch/slf4j
+
+jersey-client-2.23.2.jar (2.23.2)
+     * License: CDDL
+
+jersey-common-2.23.2.jar (2.23.2)
+    * License: CDDL
+
+jersey-container-servlet-2.23.2.jar  (2.23.2)
+    * License: CDDL
+
+jersey-container-servlet-core-2.23.3.jar(2.23.2)
+    * License: CDDL
+
+jersey-guava-2.23.2.jar  (2.23.2)
+    * License: Apache License, 2.0
+
+jersey-media-jaxb-2.23.2.jar(2.23.2)
+    * License: CDDL
+
+jersey-media-sse-2.23.2.jar (2.23.2)
+    * License: CDDL
+
+jersey-media-multipart-2.23.2.jar (2.23.2)
+    * License: CDDL
+
+jersey-server-2.23.2.jar (2.23.2)
+    * License: Apache-2.0
+
+log4j-over-slf4j-1.7.25.jar (1.7.25)
+    * License: Apache-2.0
+
+logback-classic-1.2.3.jar(1.2.3)
+    * License: Eclipse Public License 1.0
+
+logback-core-1.2.3.jar(1.2.3)
+    * License: Eclipse Public License 1.0
+
+mimepull-1.9.6.jar (1.9.4)
+    * License: CDDL
+
+openatfx-0.7.4.jar (0.7.4)
+    * License: Apache-2.0
+
+osgi-resource-locator-1.0.1.jar(1.0.1)
+    * License: CDDL
+
+protobuf-java-3.2.0.jar (3.2.0)
+    * License: New BSD license
+
+protobuf-java-util-3.2.0.jar  (3.2.0)
+    * License: New BSD license
+
+swagger-annotations-2.0.8.jar (2.0.8)
+    * License: Apache-2.0
+
+swagger-ui-3.23.0.jar (3.23.0)
+    * License: Apache-2.0
+
+slf4j-api-1.7.25.jar  (1.7.25)
+    * License: MIT license
+    * Licence Path: https://www.slf4j.org/license.html
+    * Project URL: https://github.com/qos-ch/slf4j
+    * Source URL:  https://github.com/qos-ch/slf4j/releases/tag/v_1.7.25
+
+stax2-api-3.1.4.jar (3.1.4)
+    * License: BSD-2-Clause
+
+validation-api-1.1.0.Final.jar (1.1.0.Final)
+  * License: Apache License, 2.0
+
+vavr-0.9.1-sources.jar (0.9.1)
+  * License: Apache License, 2.0
+
+vavr-match-0.9.1.jar (0.9.1)
+  * License: Apache License, 2.0
+
+woodstox-core-asl-4.4.1.jar (4.4.1)
+  * License: Apache License, 2.0
+
+
+FFAMFAMFAM Silk Icon, Version 1.3
+    * License: Creative Commons Attribution 3.0 License
+    * Licence Path: https://creativecommons.org/licenses/by/3.0/
+    * Project: http://www.famfamfam.com/lab/icons/silk/
+    * Source:  http://www.famfamfam.com/lab/icons/silk/
+
+@angular/animations:7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io/api/animations
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/cdk:7.1.1
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io/api
+    * Source:  https://github.com/angular/angular/releases/tag/7.1.1
+
+
+@angular/common@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io/api/common
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4r
+
+@angular/compiler@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/core@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/forms@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/http@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/platform-browser-dynamic@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/platform-browser@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+@angular/router@7.2.4
+    * License: MIT
+    * Licence Path: https://github.com/angular/angular/blob/master/LICENSE
+    * Project: https://angular.io
+    * Source:  https://github.com/angular/angular/releases/tag/7.2.4
+
+bootstrap@4.1.3
+    * License: MIT
+    * Licence Path: https://github.com/twbs/bootstrap/raw/master/LICENSE
+    * Project: https://getbootstrap.com/
+    * Source:  https://github.com/twbs/bootstrap
+
+class-transformer@0.1.6
+    * License: MIT
+    * Licence Path: https://github.com/typestack/class-transformer/blob/master/LICENSE
+    * Project: https://github.com/pleerock/class-transformer
+    * Source:  https://github.com/pleerock/class-transformer
+
+core-js@2.6.0
+    * License: MIT
+    * Licence Path: https://github.com/zloirock/core-js/raw/master/LICENSE
+    * Project: https://github.com/zloirock/core-js
+    * Source:  https://github.com/zloirock/core-js/releases/tag/v2.6.0
+
+file-saver@1.3.3
+    * License: MIT
+    * Licence Path: https://github.com/eligrey/FileSaver.js/raw/master/LICENSE.md
+    * Project: https://github.com/eligrey/FileSaver.js
+    * Source:  https://github.com/eligrey/FileSaver.js
+
+font-awesome@4.7.0
+    * License: MIT
+    * Licence Path: https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt
+    * Project: https://fontawesome.com/
+    * Source:  https://github.com/FortAwesome/Font-Awesome
+
+ng2-split-pane@1.3.1
+    * License: MIT
+    * Licence Path: https://github.com/wannabegeek/ng2-split-pane/raw/master/LICENSE
+    * Project: https://github.com/wannabegeek/ng2-split-pane
+    * Source:  https://github.com/wannabegeek/ng2-split-pane
+
+ngx-bootstrap@3.1.2
+    * License: MIT
+    * Licence Path: https://github.com/valor-software/ngx-bootstrap/blob/v3.1.2/LICENSE
+    * Project: https://valor-software.com/ngx-bootstrap
+    * Source:  https://github.com/valor-software/ngx-bootstrap/tree/v3.1.2
+
+@ngx-translate/core@11.0.1
+    * License: MIT 
+    * Licence Path:   https://github.com/ngx-translate/core/blob/v11.0.1/LICENSE  
+    * Project URL:    http://www.ngx-translate.com/
+    * Source URL:     https://github.com/ngx-translate/core
+
+@ngx-translate/http-loader@4.0.0
+    * License: MIT 
+    * Licence Path:   https://github.com/ngx-translate/http-loader/blob/v4.0.0/LICENSE  
+    * Project URL:    http://www.ngx-translate.com/
+    * Source URL:     https://github.com/ngx-translate/http-loader/tree/v4.0.0
+
+primeicons:1.0.0
+    * License: MIT
+    * Licence Path: https://github.com/primefaces/primeicons/blob/1.0.0/LICENSE
+    * Project: https://www.primefaces.org/primeng
+    * Source:  https://github.com/primefaces/primeicons/tree/1.0.0
+
+primeng@7.0.1
+    * License: MIT
+    * Licence Path: https://github.com/primefaces/primeng/blob/7.0.1/LICENSE.md
+    * Project: https://www.primefaces.org/primeng
+    * Source:  https://github.com/primefaces/primeng/tree/7.0.1
+
+rxjs@6.3.3
+    * License: Apache-2.0
+    * Project: https://rxjs-dev.firebaseapp.com/
+    * Source:  https://github.com/ReactiveX/rxjs/tree/6.3.3
+
+rxjs-compat:6.3.3
+    * License: Apache-2.0
+    * Project: https://rxjs-dev.firebaseapp.com/
+    * Source:  https://github.com/ReactiveX/rxjs/tree/6.3.3/compat
+
+tslib@1.9.0
+    * License: Apache-2.0
+    * Project: https://github.com/Microsoft/tslib
+    * Source:  https://github.com/Microsoft/tslib/tree/1.9.0
+
+zone.js@0.8.26
+    * License: MIT
+    * Licence Path: https://github.com/angular/zone.js/raw/master/LICENSE
+    * Project: https://github.com/angular
+    * Source:  https://github.com/angular/zone.js/releases/tag/v0.8.26
+
+OMG Event Service Specification (1.2)
+
+* License: LicenseRef - Object-Management-Group-License
+* Project: https://www.omg.org/spec/EVNT/1.2/
+* Source: https://www.omg.org/spec/EVNT/1.2/pdf
+
+OMG Notification Service Specification (1.1)
+
+* License: LicenseRef - Object-Management-Group-License
+* Project: https://www.omg.org/spec/NOT/
+* Source: https://www.omg.org/spec/NOT/1.1/PDF
+
+ods530.idl
+Date: Hoehenkirchen, 06/01/2016
+"The ASAM Board of Directors releases the IDL files for use under the EPL to the Eclipse IWG openMDM.
+This is valid for all versions of ASAM ODS 5.3.x.
+This permission is valid under the conditions of Eclipse will not modify the file."
+
+AvalonEvent.idl, CorbaFileServer.idl
+Date: 08/15/2016
+"Herewith, we release the generated Client-Source-Code generated from our CORBA IDLs, namely
+* CORBANotification Service (generated from „AvalonEvent.idl”)
+* CORBAFileServer (generated from „CorbaFileServer.idl“),
+Under the Eclipse Public License (EPL). This agreement does not include the „AvalonEvent.idl“ and
+„CorbaFileServer.idl“ itself, which remain protected property of HighQSoft. "
+
+## Cryptography
+
+Content may contain encryption software. The country in which you are currently
+may have restrictions on the import, possession, and use, and/or re-export to
+another country, of encryption software. BEFORE using any encryption software,
+please check the country's laws, regulations and policies concerning the import,
+possession, or use, and re-export of encryption software, to see if this is
+permitted.
diff --git a/org.eclipse.mdm.api.odsadapter/README.md b/org.eclipse.mdm.api.odsadapter/README.md
new file mode 100644
index 0000000..80e73da
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/README.md
@@ -0,0 +1,164 @@
+# MDM5 API #
+
+
+This document describes the services defined in the MDM5 API.
+
+
+## 1. Introduction ##
+
+The MDM5 API consists of the following projects:
+
+
+-   **org.eclipse.mdm.api.base**\
+    Defines the core services and entities. Entities contained in this
+    project must be supported by all implementations.
+
+-   **org.eclipse.mdm.api.default**\
+    Extends the core API with catalog and template entities to organize
+    the storage of context data.
+
+-   **org.eclipse.mdm.api.odsadapter**\
+    Implements both org.eclipse.mdm.api.base and org.eclipse.mdm.default
+    using the query based ASAM ODS OO API.
+
+
+## 2. EntityManager ##
+
+Once a connection to a persistence (e.g. ODS server) is established, the
+entity manager allows to load entities of any kind and provides access
+to available services.
+
+
+Returned entities are always complete. This means they are loaded with
+all of their properties and related entities (as exposed by their API).
+Therefore it does not matter how entities are retrieved (e.g. entity
+manager or search service). The entity manager provides various methods
+to load instances by their id, load parent or child entities for a given
+entity or filter loaded entities with a given naming pattern. Context
+data may be loaded for TestStep or Measurement entities.
+
+
+Mass data may be loaded by defining a corresponding request. Such a
+request consists of a ChannelGroup and a subset of related Channels.
+Finally, a range is defined to loaded stored values iteratively or all at
+once. This allows a fine grained access to stored mass data.
+
+
+### 2.1. SearchService ###
+
+The search service allows to search for entities like Test, TestStep,
+Measurement and Channel across hierarchies. So one can, for example,
+search for Tests and apply filter criteria for context data of related
+TestSteps and Measurements without defining any joins. This is done by
+the internally used search queries. Each search query defines a set of
+supported entity types and hence all of its attributes may be used for
+selections or filter criteria. The search service allows to query
+possible filter values for each supported attribute.
+
+
+In addition to that a query string may be used to search for entities.
+This query string is evaluated and processed by a full text search
+which returns a result consisting of Test, TestStep or Measurement
+entities.
+
+
+### 2.2. Notification ###
+
+TODO
+
+
+### 2.3. FileService ###
+
+The file service may be used to download externally linked files, query
+their size or open a consumable download stream for a given externally
+linked file. Sequential or parallel download of multiple files is
+possible as well. A download request with multiple files may have
+multiple links to the same file. In such a case this file is downloaded
+only once and all links will point to the same local copy of the
+downloaded file. Since downloading large files may take its time to
+complete, one can pass a listener to track the overall progress.
+
+NOTE:
+```
+This service does not allow manually uploading or deleting files. Instead 
+files are automatically uploaded / deleted while entities are written 
+within a Section 2.5, "Transaction".
+```
+
+### 2.4. EntityFactory ###
+
+The entity factory is the only way to create new entities. Each entity
+returned by this service is considered to be virtual, since it does not
+have an id until it is written. Entities with informational relations
+like Quantity (references a Unit) or Unit (references a
+PhysicalDimension) may only reference already persisted entities. This
+means that a new Quantity may only be created with an already persisted
+Unit and a new Unit may only be created with an already persisted
+PhysicalDimension.
+
+
+On the other hand, it is possible to create parent / child trees
+consisting of virtual or persisted entities (parent and child entities
+are internally linked together). Within a transaction such trees are
+recursively processed, therefore it is not required to explicitly
+create, update or delete child entities, instead it is sufficient and
+highly recommended to write only the root entity of the tree(s). The
+transaction service recursively resolves such trees and executes batch
+insert-, update- or delete-statements for the children.
+
+
+### 2.5. Transaction ###
+
+The transaction service effectively modifies the stored contents.
+Entities are grouped by their type before they are processed. Each group
+is processed at once with a batch statement. Each written entity is
+scanned for externally linked files. New ones are automatically uploaded,
+while removed ones are deleted. In case of errors any changes made to the
+persistence are cancelled and hence any successfully uploaded file has to
+be deleted. Unfortunately, the removal of uploaded files cannot be
+guaranteed (e.g. a broken connection), instead a delete request for the
+uploaded files is send on a best effort basis.
+
+IMPORTANT:
+```
+Externally linked files of deleted entities are only removed if the
+entity is an instance of FilesAttachable (Test, TestStep, Measurement).
+In any other case, externally linked files are not removed since this 
+may have an impact on other entities which reference the same file.
+```
+
+Besides the modification of entities, it is possible to write mass data
+by defining write requests. A write request describes in detail how the
+mass data of a Channel is organized (e.g. values are explicit or
+generated, stored in externally linked files etc.).
+
+
+
+## 3. Connect to an ODS Server ##
+
+The ODS entity manager factory is used to connect to an ODS server. It
+takes parameters, shown in the example below, to establish a
+connection. On success an entity manager is returned.
+
+```java
+    Map<String, String> connectionParameters = new HashMap<>();
+    connectionParameters.put(ODSEntityManagerFactory.PARAM_NAMESERVICE, "corbaloc::1.2@<SERVER>:<PORT>/NameService");
+    connectionParameters.put(ODSEntityManagerFactory.PARAM_SERVICENAME, "<SERVICE>.ASAM-ODS");
+    connectionParameters.put(ODSEntityManagerFactory.PARAM_USER, "sa");
+    connectionParameters.put(ODSEntityManagerFactory.PARAM_PASSWORD, "sa");
+    EntityManager entityManager = new ODSEntityManagerFactory().connect(connectionParameters);
+    // do something useful
+    entityManager.close();
+```
+
+## 4. Copyright and License ##
+Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ SPDX-License-Identifier: EPL-2.0
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/build.gradle b/org.eclipse.mdm.api.odsadapter/build.gradle
new file mode 100644
index 0000000..4a95a97
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/build.gradle
@@ -0,0 +1,193 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+description = 'MDM API - ODSAdapter'
+group = 'org.eclipse.mdm'
+version = '5.2.0M1-SNAPSHOT'
+
+apply plugin: 'java'
+apply plugin: 'maven'
+apply plugin: 'eclipse'
+apply plugin: 'com.google.protobuf'
+
+buildscript {
+	repositories {
+		mavenCentral()
+	}
+	dependencies {
+		classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
+	}
+}
+
+repositories {
+	jcenter()
+	mavenLocal()
+	mavenCentral()
+}
+
+sourceSets {
+
+	generated {
+		java {
+			srcDir 'src/gen/java'
+			srcDir 'build/generated/source/proto/main/java'
+		}
+	}
+
+	main {
+		compileClasspath += generated.output
+		runtimeClasspath += generated.output
+	}
+
+	test {
+		compileClasspath += generated.output
+		runtimeClasspath += generated.output
+	}
+}
+
+configurations.all {
+	exclude group: 'javax.inject', module: 'javax.inject'
+	exclude group: 'commons-logging', module: 'commons-logging'
+	
+	// exclude guava dependencies
+	exclude group: 'com.google.code.findbugs', module: 'jsr305'
+	exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
+	exclude group: 'com.google.j2objc', module: 'j2objc-annotations'
+	exclude group: 'org.codehaus.mojo', module: 'animal-sniffer-annotations'
+	exclude group: 'org.checkerframework', module: 'checker-compat-qual'
+}
+
+dependencies {
+	compileOnly 'javax:javaee-api:7.0'
+
+	// logging
+	compile 'org.slf4j:slf4j-api:1.7.25'
+	// httpclient uses commons-logging
+	compile 'org.slf4j:jcl-over-slf4j:1.7.25'
+
+	// MDM5 API
+	compile "org.eclipse.mdm:org.eclipse.mdm.api.base:${version}"
+	compile "org.eclipse.mdm:org.eclipse.mdm.api.default:${version}"
+
+	// compile CORBA idl using JDK tools
+	generatedCompile files(System.getenv('JAVA_HOME') + '/lib/tools.jar')
+    generatedCompile files('src/main/idl/')
+    
+	// Peak notification service
+	compile 'com.google.protobuf:protobuf-java:3.2.0'
+	compile 'com.google.protobuf:protobuf-java-util:3.2.0'
+	compile 'com.google.guava:guava:25.0-jre'
+	compile 'org.glassfish.jersey.core:jersey-client:2.23.2'
+	compile 'org.glassfish.jersey.media:jersey-media-sse:2.23.2'
+	generatedCompile 'com.google.protobuf:protobuf-java:3.2.0'
+
+	// querying es
+	compile 'commons-httpclient:commons-httpclient:3.1'
+	compile 'org.apache.commons:commons-text:1.6'
+
+	// testing
+	testCompile 'junit:junit:4.12'
+	testRuntime 'org.slf4j:slf4j-simple:1.7.25'
+	testCompile 'org.mockito:mockito-core:2.13.0'
+	testCompile 'org.assertj:assertj-core:3.6.2'
+	
+	testCompile "org.elasticsearch.client:elasticsearch-rest-client:6.4.1"
+	testCompile "org.testcontainers:elasticsearch:1.12.5"
+}
+
+test {
+	if(project.hasProperty('host')) {
+		systemProperty 'host', project.property('host')
+	} else {
+		systemProperty 'host', '<host>'
+	}
+
+	if(project.hasProperty('port')) {
+		systemProperty 'port', project.property('port')
+	} else {
+		systemProperty 'port', '2809'
+	}
+	
+	if(project.hasProperty('service')) {
+		systemProperty 'service', project.property('service')
+	} else {
+		systemProperty 'service', '<service>'
+	}
+
+	jvmArgs '-Dorg.slf4j.simpleLogger.defaultLogLevel=debug'
+}
+
+protobuf {
+	protoc {
+		artifact = 'com.google.protobuf:protoc:3.2.0'
+	}
+}
+
+
+task compileIDL(type: JavaExec) {
+	classpath = configurations.generatedCompile
+
+	main = 'com.sun.tools.corba.se.idl.toJavaPortable.Compile'
+
+	// add 'fallTIE' if <Type>POA & <Type>POATie have to be generated   
+	args '-fallTIE', '-td', 'src/gen/java/', 'src/main/idl/ods530.idl'
+
+	outputs.dir("src/gen/java")
+}
+
+task compileNotificationServiceIDL(type: JavaExec) {
+	classpath = configurations.generatedCompile
+
+	main = 'com.sun.tools.corba.se.idl.toJavaPortable.Compile'
+
+	args '-emitAll', '-fallTIE', '-i', 'src/main/idl/', '-td', 'src/gen/java/', 'src/main/idl/CosNotifyChannelAdmin.idl'
+
+	outputs.dir("src/gen/java")
+	outputs.upToDateWhen { false }
+}
+
+compileGeneratedJava {
+	inputs.dir("build/generated/source")
+	inputs.dir("src/gen/java")
+}
+
+// generate classes from idl and compile them
+compileGeneratedJava.dependsOn compileIDL
+compileGeneratedJava.dependsOn compileNotificationServiceIDL
+
+compileJava.dependsOn compileGeneratedJava
+
+jar {
+	from sourceSets.generated.output
+	dependsOn generatedClasses
+
+	metaInf { from 'NOTICE.txt' }
+	metaInf { from 'LICENSE.txt' }
+}
+
+task sourcesJar(type: Jar, dependsOn: classes) {
+	classifier = 'sources'
+	from sourceSets.main.allSource
+}
+
+artifacts {
+	archives sourcesJar
+}
+
+task deleteGenerated(type: Delete) {
+	delete 'src/gen'
+	delete 'build'
+}
+
+clean.dependsOn deleteGenerated
diff --git a/org.eclipse.mdm.api.odsadapter/gradle.properties b/org.eclipse.mdm.api.odsadapter/gradle.properties
new file mode 100644
index 0000000..2ab5436
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/gradle.properties
@@ -0,0 +1,16 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+ 
+sourceCompatibility=1.8
+targetCompatibility=1.8
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.jar b/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7a3265e
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.properties b/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b82e006
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME

+distributionPath=wrapper/dists

+zipStoreBase=GRADLE_USER_HOME

+zipStorePath=wrapper/dists

+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip

diff --git a/org.eclipse.mdm.api.odsadapter/gradlew b/org.eclipse.mdm.api.odsadapter/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$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=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# 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
+    ;;
+  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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/org.eclipse.mdm.api.odsadapter/gradlew.bat b/org.eclipse.mdm.api.odsadapter/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/gradlew.bat
@@ -0,0 +1,84 @@
+@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 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=

+

+@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 init

+

+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 init

+

+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

+

+:init

+@rem Get command-line arguments, handling Windows variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+

+: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 %CMD_LINE_ARGS%

+

+: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/org.eclipse.mdm.api.odsadapter/settings.gradle b/org.eclipse.mdm.api.odsadapter/settings.gradle
new file mode 100644
index 0000000..e1e8178
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/settings.gradle
@@ -0,0 +1,15 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+rootProject.name = 'org.eclipse.mdm.api.odsadapter'
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/doc/mdm5_api.adoc b/org.eclipse.mdm.api.odsadapter/src/main/doc/mdm5_api.adoc
new file mode 100644
index 0000000..ef765c3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/doc/mdm5_api.adoc
@@ -0,0 +1,84 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+= MDM5 API
+
+This document describes the services defined in the MDM5 API.
+
+== Introduction
+The MDM5 API consists of the following projects:
+
+* *org.eclipse.mdm.api.base* +
+    Defines the core services and entities. Entities contained in this project must be supported by all implementations.
+* *org.eclipse.mdm.api.default* +
+    Extends the core API with catalog and template entities to organize the storage of context data. 
+* *org.eclipse.mdm.api.odsadapter* +
+    Implements both org.eclipse.mdm.api.base and org.eclipse.mdm.default using the query based ASAM ODS OO API.
+    
+== EntityManager
+
+Once a connection to a persistence (e.g. ODS server) is established, the entity manager allows to load entities of any kind and provides access to available services. 
+
+Returned entities are always complete. This means they are loaded with all of their properties and related entities (as exposed by their API). Therefore it does not matter how entities are retrieved (e.g. entity manager or search service). The entity manager provides various methods to load instances by their id, load parent or child entities for a given entity or filter loaded entities with a given naming pattern. Context data may be loaded for TestStep or Measurement entities.
+
+Mass data may be loaded by defining a corresponding request. Such a request consists of a ChannelGroup and a subset of related Channels. Finally a range is defined to loaded stored values iteratively or all at once. This allows a fine grained access to stored mass data.
+
+=== SearchService
+The search service allows to search for entities like Test, TestStep, Measurement and Channel across hierarchies. So one can, for example, search for Tests and apply filter criteria for context data of related TestSteps and Measurements without defining any joins. This is done by the internally used search queries. Each search query defines a set of supported entity types and hence all of its attributes may be used for selections or filter criteria. The search service allows to query possible filter values for each supported attribute.
+
+In addition to that a query string may be used to search for entities. This query string is evaluated and processed by a full text search which returns a result consisting of Test, TestStep or Measurement entities.
+
+=== Notification
+TODO
+
+=== FileService
+The file service may be used to download externally linked files, query their size or open a consumable download stream for a given externally linked file. Sequential or parallel download of multiple files is possible as well. A download request with multiple files may have multiple links to the same file. In such a case this file is downloaded only once and all links will point to the same local copy of the downloaded file. Since downloading large files may take its time to complete, one can pass a listener to track the overall progress.
+
+[NOTE]
+====
+This service does not allow manually uploading or deleting files. Instead files are automatically uploaded / deleted while entities are written within a <<Transaction>>.
+====
+
+=== EntityFactory
+The entity factory is the only way to create new entities. Each entity returned by this service is considered to be virtual, since it does not have an id until it is written. Entities with informational relations like Quantity (references a Unit) or Unit (references a PhysicalDimension) may only reference already persisted entities. This means that a new Quantity may only be created with an already persisted Unit and a new Unit may only be created with an already persisted PhysicalDimension.
+
+On the other hand it is possible to create parent / child trees consisting of virtual or persisted entities (parent and child entities are internally linked together). Within a transaction such trees are recursively processed, therefore it is not required to explicitly create, update or delete child entities, instead it is sufficient and highly recommended to write only the root entity of the tree(s). The transaction service recursively resolves such trees and executes batch insert-, update- or delete-statements for the children.
+
+=== Transaction
+The transaction service effectively modifies the stored contents. Entities are grouped by their type before they are processed. Each group is processed at once with a batch statement. Each  written entity is scanned for externally linked files. New ones are automatically uploaded, while removed ones are deleted. In case of errors any changes made to the persistence are cancelled and hence any successfully uploaded file has to be deleted. Unfortunately the removal of uploaded files cannot be guaranteed (e.g. a broken connection), instead a delete request for the uploaded files is send on a best effort basis.
+
+[IMPORTANT]
+====
+Externally linked files of deleted entities are only removed if the entity is an instance of FilesAttachable (Test, TestStep, Measurement). In any other case externally linked files are not removed, since this may have an impact on other entities which reference the same file.
+====
+
+Besides the modification of entities, it is possible to write mass data by defining write requests. A write request describes in detail how the mass data of a Channel is organized (e.g. values are explicit or generated, stored in externally linked files etc.).
+
+== Connect to an ODS Server
+The ODS entity manager factory is used to connect to an ODS server. It takes parameters, shown in the exapmple below, to establish a connection. On success an entity manager is returned.
+
+[source,java]
+----
+Map<String, String> connectionParameters = new HashMap<>();
+connectionParameters.put(ODSEntityManagerFactory.PARAM_NAMESERVICE, "corbaloc::1.2@<SERVER>:<PORT>/NameService");
+connectionParameters.put(ODSEntityManagerFactory.PARAM_SERVICENAME, "<SERVICE>.ASAM-ODS");
+connectionParameters.put(ODSEntityManagerFactory.PARAM_USER, "sa");
+connectionParameters.put(ODSEntityManagerFactory.PARAM_PASSWORD, "sa");
+
+EntityManager entityManager = new ODSEntityManagerFactory().connect(connectionParameters);
+
+// do something useful
+
+entityManager.close();
+----
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventChannelAdmin.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventChannelAdmin.idl
new file mode 100644
index 0000000..8ddf3a3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventChannelAdmin.idl
@@ -0,0 +1,59 @@
+/**

+ * This module is taken from the standard CORBA Event Service

+ * 1.2, as described in:

+ *

+ * https://www.omg.org/spec/EVNT/1.2/

+ *

+ * The idl was extracted from the following PDF:

+ * formal/04-10-02 

+ */

+

+#ifndef _COS_EVENT_CHANNEL_ADMIN_IDL_

+#define _COS_EVENT_CHANNEL_ADMIN_IDL_

+

+#include "CosEventComm.idl"
+

+#pragma prefix "omg.org"

+
+module CosEventChannelAdmin {
+
+   exception AlreadyConnected {};
+   exception TypeError {};
+
+   interface ProxyPushConsumer: CosEventComm::PushConsumer {
+      void connect_push_supplier(in CosEventComm::PushSupplier push_supplier)
+         raises(AlreadyConnected);
+   };
+
+   interface ProxyPullSupplier: CosEventComm::PullSupplier {
+      void connect_pull_consumer(in CosEventComm::PullConsumer pull_consumer)
+         raises(AlreadyConnected);
+   };
+
+   interface ProxyPullConsumer: CosEventComm::PullConsumer {
+      void connect_pull_supplier(in CosEventComm::PullSupplier pull_supplier)
+         raises(AlreadyConnected,TypeError);
+   };
+
+   interface ProxyPushSupplier: CosEventComm::PushSupplier {
+      void connect_push_consumer(in CosEventComm::PushConsumer push_consumer)
+         raises(AlreadyConnected, TypeError);
+   };
+
+   interface ConsumerAdmin {
+      ProxyPushSupplier obtain_push_supplier();
+      ProxyPullSupplier obtain_pull_supplier();
+   };
+
+   interface SupplierAdmin {
+      ProxyPushConsumer obtain_push_consumer();
+      ProxyPullConsumer obtain_pull_consumer();
+   };
+
+   interface EventChannel {
+      ConsumerAdmin for_consumers();
+      SupplierAdmin for_suppliers();
+      void destroy();
+   };
+};
+#endif /* ifndef _COS_EVENT_CHANNEL_ADMIN_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventComm.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventComm.idl
new file mode 100644
index 0000000..ed88691
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosEventComm.idl
@@ -0,0 +1,41 @@
+/**

+ * This module is taken from the standard CORBA Event Service

+ * 1.2, as described in:

+ *

+ * https://www.omg.org/spec/EVNT/1.2/

+ *

+ * The idl was extracted from the following PDF:

+ * formal/04-10-02 

+ */

+ 

+#ifndef _COS_EVENT_COMM_IDL_

+#define _COS_EVENT_COMM_IDL_

+

+#pragma prefix "omg.org"

+

+module CosEventComm {
+
+   exception Disconnected{};
+
+   interface PushConsumer {
+      void push (in any data) raises(Disconnected);
+      void disconnect_push_consumer();
+   };
+
+    interface PushSupplier {
+      void disconnect_push_supplier();
+   };
+
+   interface PullSupplier {
+      any pull () raises(Disconnected);
+      any try_pull (out boolean has_event) raises(Disconnected);
+      void disconnect_pull_supplier();
+   };
+
+   interface PullConsumer {
+      void disconnect_pull_consumer();
+   };
+
+};
+
+#endif /* ifndef _COS_EVENT_COMM_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotification.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotification.idl
new file mode 100644
index 0000000..a789700
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotification.idl
@@ -0,0 +1,180 @@
+/**

+ * This module is taken from the standard CORBA Notification Service

+ * 1.1, as described in:

+ *

+ * https://www.omg.org/spec/NOT/1.1/

+ *

+ * The idl was extracted from the following PDF:

+ * formal/04-10-13

+ */

+

+#ifndef _COS_NOTIFICATION_IDL_

+#define _COS_NOTIFICATION_IDL_

+

+#pragma prefix "omg.org"

+

+module CosNotification {
+
+   typedef string Istring;
+   typedef Istring PropertyName;
+   typedef any PropertyValue;
+
+   struct Property {
+      PropertyName name;
+      PropertyValue value;
+   };
+   typedef sequence<Property> PropertySeq;
+
+   // The following are the same, but serve different purposes.
+   typedef PropertySeq OptionalHeaderFields;
+   typedef PropertySeq FilterableEventBody;
+   typedef PropertySeq QoSProperties;
+   typedef PropertySeq AdminProperties;
+
+   struct _EventType {
+      string domain_name;
+      string type_name;
+   };
+   typedef sequence<_EventType> EventTypeSeq;
+
+   struct PropertyRange {
+      PropertyValue low_val;
+      PropertyValue high_val;
+   };
+
+   struct NamedPropertyRange {
+      PropertyName name;
+      PropertyRange range;
+   };
+   typedef sequence<NamedPropertyRange> NamedPropertyRangeSeq;
+
+   enum QoSError_code {
+      UNSUPPORTED_PROPERTY,
+      UNAVAILABLE_PROPERTY,
+      UNSUPPORTED_VALUE,
+      UNAVAILABLE_VALUE,
+      BAD_PROPERTY,
+      BAD_TYPE,
+      BAD_VALUE
+   };
+
+   struct PropertyError {
+      QoSError_code code;
+      PropertyName name;
+      PropertyRange available_range;
+   };
+   typedef sequence<PropertyError> PropertyErrorSeq;
+
+   exception UnsupportedQoS { PropertyErrorSeq qos_err; };
+   exception UnsupportedAdmin { PropertyErrorSeq admin_err; };
+
+   // Define the Structured Event structure
+   struct FixedEventHeader {
+      _EventType event_type;
+      string event_name;
+   };
+
+   struct EventHeader {
+      FixedEventHeader fixed_header;
+      OptionalHeaderFields variable_header;
+   };
+
+   struct StructuredEvent {
+      EventHeader header;
+      FilterableEventBody filterable_data;
+      any remainder_of_body;
+   }; // StructuredEvent
+   typedef sequence<StructuredEvent> EventBatch;
+
+   // The following constant declarations define the standard
+   // QoS property names and the associated values each property
+   // can take on. The name/value pairs for each standard property
+   // are grouped, beginning with a string constant defined for the
+   // property name, followed by the values the property can take on.
+
+   const string EventReliability = "EventReliability";
+   const short BestEffort = 0;
+   const short Persistent = 1;
+
+   const string ConnectionReliability = "ConnectionReliability";
+   // Can take on the same values as EventReliability
+
+   const string Priority = "Priority";
+   const short LowestPriority = -32767;
+   const short HighestPriority = 32767;
+   const short DefaultPriority = 0;
+
+   const string StartTime = "StartTime";
+   // StartTime takes a value of type TimeBase::UtcT.
+
+   const string StopTime = "StopTime";
+   // StopTime takes a value of type TimeBase::UtcT.
+
+   const string Timeout = "Timeout";
+   // Timeout takes on a value of type TimeBase::TimeT
+
+   const string OrderPolicy = "OrderPolicy";
+   const short AnyOrder = 0;
+   const short FifoOrder = 1;
+   const short PriorityOrder = 2;
+   const short DeadlineOrder = 3;
+
+   const string DiscardPolicy = "DiscardPolicy";
+   // DiscardPolicy takes on the same values as OrderPolicy, plus
+   const short LifoOrder = 4;
+
+   const string MaximumBatchSize = "MaximumBatchSize";
+   // MaximumBatchSize takes on a value of type long
+
+   const string PacingInterval = "PacingInterval";
+   // PacingInterval takes on a value of type TimeBase::TimeT
+
+   const string StartTimeSupported = "StartTimeSupported";
+   // StartTimeSupported takes on a boolean value
+
+   const string StopTimeSupported = "StopTimeSupported";
+   // StopTimeSupported takes on a boolean value
+
+   const string MaxEventsPerConsumer = "MaxEventsPerConsumer";
+   // MaxEventsPerConsumer takes on a value of type long
+
+   interface QoSAdmin {
+
+      QoSProperties get_qos();
+
+      void set_qos ( in QoSProperties qos) raises ( UnsupportedQoS );
+
+      void validate_qos (
+            in QoSProperties required_qos,
+            out NamedPropertyRangeSeq available_qos ) raises ( UnsupportedQoS );
+
+   }; // QosAdmin
+
+   // Admin properties are defined in similar manner as QoS
+   // properties. The only difference is that these properties
+   // are related to channel administration policies, as opposed
+   // message quality of service
+
+   const string MaxQueueLength = "MaxQueueLength";
+   // MaxQueueLength takes on a value of type long
+
+   const string MaxConsumers = "MaxConsumers";
+   // MaxConsumers takes on a value of type long
+
+   const string MaxSuppliers = "MaxSuppliers";
+   // MaxSuppliers takes on a value of type long
+
+   const string RejectNewEvents = "RejectNewEvents";
+   // RejectNewEvents takes on a value of type Boolean
+
+   interface AdminPropertiesAdmin {
+
+      AdminProperties get_admin();
+
+      void set_admin (in AdminProperties admin) raises ( UnsupportedAdmin);
+
+   }; // AdminPropertiesAdmin
+
+}; // CosNotification
+
+#endif /* _COS_NOTIFICATION_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyChannelAdmin.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyChannelAdmin.idl
new file mode 100644
index 0000000..524d3ea
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyChannelAdmin.idl
@@ -0,0 +1,394 @@
+/**
+ * This module is taken from the standard CORBA Notification Service
+ * 1.1, as described in:
+ *
+ * https://www.omg.org/spec/NOT/1.1/
+ *
+ * The idl was extracted from the following PDF:
+ * formal/04-10-13
+ */
+
+#ifndef _COS_NOTIFY_CHANNEL_ADMIN_IDL_
+#define _COS_NOTIFY_CHANNEL_ADMIN_IDL_
+
+#include "CosNotification.idl"
+#include "CosNotifyFilter.idl"
+#include "CosNotifyComm.idl"
+#include "CosEventChannelAdmin.idl"
+
+#pragma prefix "omg.org"
+
+module CosNotifyChannelAdmin {
+
+   exception ConnectionAlreadyActive {};
+   exception ConnectionAlreadyInactive {};
+   exception NotConnected {};
+
+   // Forward declarations
+   interface ConsumerAdmin;
+   interface SupplierAdmin;
+   interface EventChannel;
+   interface EventChannelFactory;
+
+   enum ProxyType {
+      PUSH_ANY,
+      PULL_ANY,
+      PUSH_STRUCTURED,
+      PULL_STRUCTURED,
+      PUSH_SEQUENCE,
+      PULL_SEQUENCE,
+      PUSH_TYPED,
+      PULL_TYPED
+   };
+
+   enum ObtainInfoMode {
+      ALL_NOW_UPDATES_OFF,
+      ALL_NOW_UPDATES_ON,
+      NONE_NOW_UPDATES_OFF,
+      NONE_NOW_UPDATES_ON
+   };
+
+   interface ProxyConsumer :
+         CosNotification::QoSAdmin,
+         CosNotifyFilter::FilterAdmin {
+
+      readonly attribute ProxyType MyType;
+      readonly attribute SupplierAdmin MyAdmin;
+
+      CosNotification::EventTypeSeq obtain_subscription_types(
+            in ObtainInfoMode mode );
+
+      void validate_event_qos (
+            in CosNotification::QoSProperties required_qos,
+            out CosNotification::NamedPropertyRangeSeq available_qos)
+         raises (CosNotification::UnsupportedQoS);
+
+   }; // ProxyConsumer
+
+   interface ProxySupplier :
+         CosNotification::QoSAdmin,
+         CosNotifyFilter::FilterAdmin {
+
+      readonly attribute ProxyType MyType;
+      readonly attribute ConsumerAdmin MyAdmin;
+
+      attribute CosNotifyFilter::MappingFilter priority_filter;
+      attribute CosNotifyFilter::MappingFilter lifetime_filter;
+
+      CosNotification::EventTypeSeq obtain_offered_types(
+            in ObtainInfoMode mode );
+
+      void validate_event_qos (
+            in CosNotification::QoSProperties required_qos,
+            out CosNotification::NamedPropertyRangeSeq available_qos)
+         raises (CosNotification::UnsupportedQoS);
+
+   }; // ProxySupplier
+
+   interface ProxyPushConsumer :
+         ProxyConsumer,
+         CosNotifyComm::PushConsumer {
+
+      void connect_any_push_supplier (
+            in CosEventComm::PushSupplier push_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // ProxyPushConsumer
+
+   interface StructuredProxyPushConsumer :
+         ProxyConsumer,
+         CosNotifyComm::StructuredPushConsumer {
+
+      void connect_structured_push_supplier (
+            in CosNotifyComm::StructuredPushSupplier push_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // StructuredProxyPushConsumer
+
+   interface SequenceProxyPushConsumer :
+         ProxyConsumer,
+         CosNotifyComm::SequencePushConsumer {
+
+      void connect_sequence_push_supplier (
+            in CosNotifyComm::SequencePushSupplier push_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // SequenceProxyPushConsumer
+
+   interface ProxyPullSupplier :
+         ProxySupplier,
+         CosNotifyComm::PullSupplier {
+
+      void connect_any_pull_consumer (
+            in CosEventComm::PullConsumer pull_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // ProxyPullSupplier
+
+   interface StructuredProxyPullSupplier :
+         ProxySupplier,
+         CosNotifyComm::StructuredPullSupplier {
+
+      void connect_structured_pull_consumer (
+            in CosNotifyComm::StructuredPullConsumer pull_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // StructuredProxyPullSupplier
+
+   interface SequenceProxyPullSupplier :
+         ProxySupplier,
+         CosNotifyComm::SequencePullSupplier {
+
+      void connect_sequence_pull_consumer (
+            in CosNotifyComm::SequencePullConsumer pull_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected);
+
+   }; // SequenceProxyPullSupplier
+
+   interface ProxyPullConsumer :
+         ProxyConsumer,
+         CosNotifyComm::PullConsumer {
+
+      void connect_any_pull_supplier (
+            in CosEventComm::PullSupplier pull_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // ProxyPullConsumer
+
+   interface StructuredProxyPullConsumer :
+         ProxyConsumer,
+         CosNotifyComm::StructuredPullConsumer {
+
+      void connect_structured_pull_supplier (
+            in CosNotifyComm::StructuredPullSupplier pull_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // StructuredProxyPullConsumer
+
+   interface SequenceProxyPullConsumer :
+         ProxyConsumer,
+         CosNotifyComm::SequencePullConsumer {
+
+      void connect_sequence_pull_supplier (
+            in CosNotifyComm::SequencePullSupplier pull_supplier)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // SequenceProxyPullConsumer
+
+   interface ProxyPushSupplier :
+         ProxySupplier,
+         CosNotifyComm::PushSupplier {
+
+      void connect_any_push_consumer (
+            in CosEventComm::PushConsumer push_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // ProxyPushSupplier
+
+   interface StructuredProxyPushSupplier :
+         ProxySupplier,
+         CosNotifyComm::StructuredPushSupplier {
+
+      void connect_structured_push_consumer (
+            in CosNotifyComm::StructuredPushConsumer push_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // StructuredProxyPushSupplier
+
+   interface SequenceProxyPushSupplier :
+         ProxySupplier,
+         CosNotifyComm::SequencePushSupplier {
+
+      void connect_sequence_push_consumer (
+            in CosNotifyComm::SequencePushConsumer push_consumer)
+         raises(CosEventChannelAdmin::AlreadyConnected,
+                CosEventChannelAdmin::TypeError );
+
+      void suspend_connection()
+         raises(ConnectionAlreadyInactive, NotConnected);
+
+      void resume_connection()
+         raises(ConnectionAlreadyActive, NotConnected);
+
+   }; // SequenceProxyPushSupplier
+
+   typedef long ProxyID;
+   typedef sequence <ProxyID> ProxyIDSeq;
+
+   enum ClientType {
+      ANY_EVENT,
+      STRUCTURED_EVENT,
+      SEQUENCE_EVENT
+   };
+
+   enum InterFilterGroupOperator { AND_OP, OR_OP };
+
+   typedef long AdminID;
+   typedef sequence<AdminID> AdminIDSeq;
+
+   exception AdminNotFound {};
+   exception ProxyNotFound {};
+
+   struct AdminLimit {
+      CosNotification::PropertyName name;
+      CosNotification::PropertyValue value;
+   };
+
+   exception AdminLimitExceeded { AdminLimit admin_property_err; };
+
+   interface ConsumerAdmin :
+         CosNotification::QoSAdmin,
+         CosNotifyComm::NotifySubscribe,
+         CosNotifyFilter::FilterAdmin,
+         CosEventChannelAdmin::ConsumerAdmin {
+
+      readonly attribute AdminID MyID;
+      readonly attribute EventChannel MyChannel;
+
+      readonly attribute InterFilterGroupOperator MyOperator;
+
+      attribute CosNotifyFilter::MappingFilter priority_filter;
+      attribute CosNotifyFilter::MappingFilter lifetime_filter;
+
+      readonly attribute ProxyIDSeq pull_suppliers;
+      readonly attribute ProxyIDSeq push_suppliers;
+
+      ProxySupplier get_proxy_supplier ( in ProxyID proxy_id )
+         raises ( ProxyNotFound );
+
+      ProxySupplier obtain_notification_pull_supplier (
+            in ClientType ctype,
+            out ProxyID proxy_id)
+         raises ( AdminLimitExceeded );
+
+      ProxySupplier obtain_notification_push_supplier (
+            in ClientType ctype,
+            out ProxyID proxy_id)
+         raises ( AdminLimitExceeded );
+
+      void destroy();
+
+   }; // ConsumerAdmin
+
+   interface SupplierAdmin :
+         CosNotification::QoSAdmin,
+         CosNotifyComm::NotifyPublish,
+         CosNotifyFilter::FilterAdmin,
+         CosEventChannelAdmin::SupplierAdmin {
+
+      readonly attribute AdminID MyID;
+      readonly attribute EventChannel MyChannel;
+
+      readonly attribute InterFilterGroupOperator MyOperator;
+
+      readonly attribute ProxyIDSeq pull_consumers;
+      readonly attribute ProxyIDSeq push_consumers;
+
+      ProxyConsumer get_proxy_consumer ( in ProxyID proxy_id )
+         raises ( ProxyNotFound );
+
+      ProxyConsumer obtain_notification_pull_consumer (
+            in ClientType ctype,
+            out ProxyID proxy_id)
+         raises ( AdminLimitExceeded );
+
+      ProxyConsumer obtain_notification_push_consumer (
+            in ClientType ctype,
+            out ProxyID proxy_id)
+         raises ( AdminLimitExceeded );
+
+      void destroy();
+
+   }; // SupplierAdmin
+
+   interface EventChannel :
+      CosNotification::QoSAdmin,
+      CosNotification::AdminPropertiesAdmin,
+      CosEventChannelAdmin::EventChannel {
+
+      readonly attribute EventChannelFactory MyFactory;
+
+      readonly attribute ConsumerAdmin default_consumer_admin;
+      readonly attribute SupplierAdmin default_supplier_admin;
+
+      readonly attribute CosNotifyFilter::FilterFactory
+                  default_filter_factory;
+
+      ConsumerAdmin new_for_consumers(
+            in InterFilterGroupOperator op,
+            out AdminID id );
+
+      SupplierAdmin new_for_suppliers(
+            in InterFilterGroupOperator op,
+            out AdminID id );
+
+      ConsumerAdmin get_consumeradmin ( in AdminID id )
+         raises (AdminNotFound);
+
+      SupplierAdmin get_supplieradmin ( in AdminID id )
+         raises (AdminNotFound);
+
+      AdminIDSeq get_all_consumeradmins();
+      AdminIDSeq get_all_supplieradmins();
+
+   }; // EventChannel
+
+   typedef long ChannelID;
+   typedef sequence<ChannelID> ChannelIDSeq;
+
+   exception ChannelNotFound {};
+
+   interface EventChannelFactory {
+
+      EventChannel create_channel (
+            in CosNotification::QoSProperties initial_qos,
+            in CosNotification::AdminProperties initial_admin,
+            out ChannelID id)
+         raises(CosNotification::UnsupportedQoS,
+                CosNotification::UnsupportedAdmin );
+
+      ChannelIDSeq get_all_channels();
+
+      EventChannel get_event_channel ( in ChannelID id )
+         raises (ChannelNotFound);
+
+   }; // EventChannelFactory
+   
+}; // CosNotifyChannelAdmin
+
+#endif /* _COS_NOTIFY_CHANNEL_ADMIN_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyComm.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyComm.idl
new file mode 100644
index 0000000..33df3d7
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyComm.idl
@@ -0,0 +1,135 @@
+/**
+ * This module is taken from the standard CORBA Notification Service
+ * 1.1, as described in:
+ *
+ * https://www.omg.org/spec/NOT/1.1/
+ *
+ * The idl was extracted from the following PDF:
+ * formal/04-10-13
+ */
+
+#ifndef _COS_NOTIFY_COMM_IDL_
+#define _COS_NOTIFY_COMM_IDL_
+
+#include "CosNotification.idl"
+#include "CosEventComm.idl"
+
+#pragma prefix "omg.org"
+
+module CosNotifyComm {
+
+   exception InvalidEventType { CosNotification::_EventType type; };
+
+   interface NotifyPublish {
+
+      void offer_change (
+            in CosNotification::EventTypeSeq added,
+            in CosNotification::EventTypeSeq removed )
+         raises ( InvalidEventType );
+
+   }; // NotifyPublish
+
+   interface NotifySubscribe {
+
+      void subscription_change(
+            in CosNotification::EventTypeSeq added,
+            in CosNotification::EventTypeSeq removed )
+         raises ( InvalidEventType );
+
+   }; // NotifySubscribe
+
+   interface PushConsumer :
+      NotifyPublish,
+      CosEventComm::PushConsumer {
+   }; // PushConsumer
+
+   interface PullConsumer :
+      NotifyPublish,
+      CosEventComm::PullConsumer {
+   }; // PullConsumer
+
+   interface PullSupplier :
+      NotifySubscribe,
+      CosEventComm::PullSupplier {
+   }; // PullSupplier
+
+   interface PushSupplier :
+      NotifySubscribe,
+      CosEventComm::PushSupplier {
+   };
+
+   interface StructuredPushConsumer : NotifyPublish {
+
+      void push_structured_event(
+            in CosNotification::StructuredEvent notification)
+         raises(CosEventComm::Disconnected);
+
+      void disconnect_structured_push_consumer();
+
+   }; // StructuredPushConsumer
+
+   interface StructuredPullConsumer : NotifyPublish {
+      
+      void disconnect_structured_pull_consumer();
+
+   }; // StructuredPullConsumer
+
+   interface StructuredPullSupplier : NotifySubscribe {
+
+      CosNotification::StructuredEvent pull_structured_event()
+         raises(CosEventComm::Disconnected);
+
+      CosNotification::StructuredEvent try_pull_structured_event(
+            out boolean has_event)
+         raises(CosEventComm::Disconnected);
+
+      void disconnect_structured_pull_supplier();
+
+   }; // StructuredPullSupplier
+
+   interface StructuredPushSupplier : NotifySubscribe {
+      
+      void disconnect_structured_push_supplier();
+
+   }; // StructuredPushSupplier
+
+   interface SequencePushConsumer : NotifyPublish {
+
+      void push_structured_events(
+            in CosNotification::EventBatch notifications)
+         raises(CosEventComm::Disconnected);
+
+      void disconnect_sequence_push_consumer();
+
+   }; // SequencePushConsumer
+
+   interface SequencePullConsumer : NotifyPublish {
+      
+      void disconnect_sequence_pull_consumer();
+
+   }; // SequencePullConsumer
+
+   interface SequencePullSupplier : NotifySubscribe {
+
+      CosNotification::EventBatch pull_structured_events(
+            in long max_number )
+         raises(CosEventComm::Disconnected);
+
+      CosNotification::EventBatch try_pull_structured_events(
+            in long max_number,
+            out boolean has_event)
+         raises(CosEventComm::Disconnected);
+
+      void disconnect_sequence_pull_supplier();
+
+   }; // SequencePullSupplier
+
+   interface SequencePushSupplier : NotifySubscribe {
+      
+      void disconnect_sequence_push_supplier();
+
+   }; // SequencePushSupplier
+
+}; // CosNotifyComm
+
+#endif /* _COS_NOTIFY_COMM_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyFilter.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyFilter.idl
new file mode 100644
index 0000000..977cc3b
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/CosNotifyFilter.idl
@@ -0,0 +1,187 @@
+/**
+ * This module is taken from the standard CORBA Notification Service
+ * 1.1, as described in:
+ *
+ * https://www.omg.org/spec/NOT/1.1/
+ *
+ * The idl was extracted from the following PDF:
+ * formal/04-10-13
+ */
+
+#ifndef _COS_NOTIFY_FILTER_IDL_
+#define _COS_NOTIFY_FILTER_IDL_
+
+#include "CosNotifyComm.idl"
+
+#pragma prefix "omg.org"
+
+module CosNotifyFilter {
+
+   typedef long ConstraintID;
+
+   struct ConstraintExp {
+      CosNotification::EventTypeSeq event_types;
+      string constraint_expr;
+   };
+
+   typedef sequence<ConstraintID> ConstraintIDSeq;
+   typedef sequence<ConstraintExp> ConstraintExpSeq;
+
+   struct ConstraintInfo {
+      ConstraintExp constraint_expression;
+      ConstraintID constraint_id;
+   };
+
+   typedef sequence<ConstraintInfo> ConstraintInfoSeq;
+
+   struct MappingConstraintPair {
+      ConstraintExp constraint_expression;
+      any result_to_set;
+   };
+
+   typedef sequence<MappingConstraintPair> MappingConstraintPairSeq;
+
+   struct MappingConstraintInfo {
+      ConstraintExp constraint_expression;
+      ConstraintID constraint_id;
+      any value;
+   };
+
+   typedef sequence<MappingConstraintInfo> MappingConstraintInfoSeq;
+
+   typedef long CallbackID;
+   typedef sequence<CallbackID> CallbackIDSeq;
+
+   exception UnsupportedFilterableData {};
+   exception InvalidGrammar {};
+   exception InvalidConstraint {ConstraintExp constr;};
+   exception DuplicateConstraintID {ConstraintID id;};
+   exception ConstraintNotFound {ConstraintID id;};
+   
+   exception CallbackNotFound {};
+
+   exception InvalidValue {ConstraintExp constr; any value;};
+
+   interface Filter {
+
+      readonly attribute string constraint_grammar;
+
+      ConstraintInfoSeq add_constraints (
+            in ConstraintExpSeq constraint_list)
+         raises (InvalidConstraint);
+
+      void modify_constraints (
+            in ConstraintIDSeq del_list,
+            in ConstraintInfoSeq modify_list)
+         raises (InvalidConstraint, ConstraintNotFound);
+
+      ConstraintInfoSeq get_constraints(
+            in ConstraintIDSeq id_list)
+         raises (ConstraintNotFound);
+
+      ConstraintInfoSeq get_all_constraints();
+
+      void remove_all_constraints();
+
+      void destroy();
+
+      boolean match ( in any filterable_data )
+         raises (UnsupportedFilterableData);
+
+      boolean match_structured (
+            in CosNotification::StructuredEvent filterable_data )
+         raises (UnsupportedFilterableData);
+
+      boolean match_typed (
+            in CosNotification::PropertySeq filterable_data )
+         raises (UnsupportedFilterableData);
+
+      CallbackID attach_callback (
+            in CosNotifyComm::NotifySubscribe callback);
+
+      void detach_callback ( in CallbackID callback)
+         raises ( CallbackNotFound );
+
+      CallbackIDSeq get_callbacks();
+
+   }; // Filter
+
+   interface MappingFilter {
+
+      readonly attribute string constraint_grammar;
+
+      readonly attribute CORBA::TypeCode value_type;
+
+      readonly attribute any default_value;
+
+      MappingConstraintInfoSeq add_mapping_constraints (
+            in MappingConstraintPairSeq pair_list)
+         raises (InvalidConstraint, InvalidValue);
+
+      void modify_mapping_constraints (
+            in ConstraintIDSeq del_list,
+            in MappingConstraintInfoSeq modify_list)
+         raises (InvalidConstraint, InvalidValue,
+                  ConstraintNotFound);
+
+      MappingConstraintInfoSeq get_mapping_constraints (
+            in ConstraintIDSeq id_list)
+         raises (ConstraintNotFound);
+
+      MappingConstraintInfoSeq get_all_mapping_constraints();
+
+      void remove_all_mapping_constraints();
+
+      void destroy();
+
+      boolean match (
+            in any filterable_data,
+            out any result_to_set )
+         raises (UnsupportedFilterableData);
+
+      boolean match_structured (
+            in CosNotification::StructuredEvent filterable_data,
+            out any result_to_set)
+         raises (UnsupportedFilterableData);
+
+      boolean match_typed (
+            in CosNotification::PropertySeq filterable_data,
+            out any result_to_set)
+         raises (UnsupportedFilterableData);
+
+   }; // MappingFilter
+
+   interface FilterFactory {
+
+      Filter create_filter ( in string constraint_grammar)
+         raises (InvalidGrammar);
+
+      MappingFilter create_mapping_filter (
+            in string constraint_grammar,
+            in any default_value)
+         raises(InvalidGrammar);
+
+   }; // FilterFactory
+
+   typedef long FilterID;
+   typedef sequence<FilterID> FilterIDSeq;
+
+   exception FilterNotFound {};
+
+   interface FilterAdmin {
+
+      FilterID add_filter ( in Filter new_filter );
+
+      void remove_filter ( in FilterID filter ) raises ( FilterNotFound );
+
+      Filter get_filter ( in FilterID filter ) raises ( FilterNotFound );
+
+      FilterIDSeq get_all_filters();
+
+      void remove_all_filters();
+
+   }; // FilterAdmin
+
+}; // CosNotifyFilter
+
+#endif /* _COS_NOTIFY_FILTER_IDL_ */
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/about.html b/org.eclipse.mdm.api.odsadapter/src/main/idl/about.html
new file mode 100644
index 0000000..399c937
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/about.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!-- saved from url=(0044)https://eclipse.org/legal/epl/longabout.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p><em>October 4, 2016</em></p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL").  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+		
+		<h3>Third Party Content</h3>
+		<p>The Content includes items that have been sourced from third parties as set out below. If you 
+		did not receive this Content directly from the Eclipse Foundation, the following is provided 
+		for informational purposes only, and you should look to the Redistributor's license for 
+		terms and conditions of use.</p>
+		<p><em>
+		<strong>ods530.idl</strong> <br><br>
+		This file is part of the ASAM ODS standard and is not subject to modification. 
+		</em></p>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/idl.config b/org.eclipse.mdm.api.odsadapter/src/main/idl/idl.config
new file mode 100644
index 0000000..7c76796
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/idl.config
@@ -0,0 +1,6 @@
+PkgPrefix.CosEventComm=org.omg

+PkgPrefix.CosNotification=org.omg

+PkgPrefix.CosNotifyComm=org.omg

+PkgPrefix.CosNotifyFilter=org.omg

+PkgPrefix.CosEventChannelAdmin=org.omg

+PkgPrefix.CosNotifyChannelAdmin=org.omg
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/idl/ods530.idl b/org.eclipse.mdm.api.odsadapter/src/main/idl/ods530.idl
new file mode 100644
index 0000000..6071509
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/idl/ods530.idl
@@ -0,0 +1,10883 @@
+//    *********************************************
+//    *     ASAM ODS 5.3.0 Interface Definition     *
+//    *********************************************
+//
+//    Generated: Tue Nov 20 09:28:37 CET 2012
+//
+// More explanation for the method getInstancesEx of the interface
+// ApplElemAccess.   More details for the method setRelationType of the
+// interface ApplicationRelation.
+//
+// Method getRelationByBaseName of the interface ApplicationElement added.  
+// Method getInverseRelationName of instance BaseRelation added.   Better
+// explanation in the comments.  Removed unused error codes of the exceptions.
+//
+// 2003-12-31
+// ODS Version 5.0
+//
+// Add SelOpcode IS_NULL and IS_NOT_NULL.  Add exception AO_INVALID_DATATYPE
+// to the method setEnumerationDefinition of the interface ApplicationElement.
+//  Method getEnumerationDefinition added to the Interface BaseRelation.  Add
+// comment to methods getFormula and setFormula of interface Column.
+//
+// Add the variable CREATE_COSESSION_ALLOWED at the method newSession at the
+// interface AoFactory.   Add the methods createCoSession and getUser at the
+// interface AoSession.  Add values of localcolumn at the methods
+// getInstances, getInstancesExt and updateInstances of the interface
+// ApplElemAccess.  Comment of method setValue of the interface ValueMatrix
+// reworked.
+//
+// Correct the Method getRelationByBaseName of the interface
+// ApplicationElement to the Method getRelationsByBaseName, mistake in
+// Interface definition there are at some elements relations derived from the
+// same base relation allowed.
+//
+// Add, SUM to the AggrFunc.  Change comment of method getApplicationStructure
+// and getBaseStructure of the interface AoSession, the method
+// getApplicationStructure of the interface ApplicationElement.and the method
+// getRelation of the interface BaseStructure.  Add version string description
+// at method getInterfaceVersion of interface AoFactory.
+//
+// Add the Enumeration ValueMatrixMode.  Change the comment of the Methods
+// 13001, 13004, 13006, 14018, 14022, 16003, 21002, 24007  Add the exception
+// AO_INVALID_VALUEMATRIX_STRUCTURE for the method getValueMatrix of the
+// interface Measurement and ApplElemAccess.  Add the new method
+// getValueMatrixInMode of the interfaces Measurement (16005), SubMatrix
+// (21004) and ApplElemAccess   Add the methods getSequenceRepresentation
+// (13013), setSequenceRepresentation (13014), getGenerationParameters
+// (13015), setGenerationParameters (13016) and getRawDataType (13017) of the
+// interface Column.  Add the method getMode (22022) of the interface
+// ValueMatrix.  Little changes in description of the methods, specify which
+// object is modified, with the numbers 4008, 4009, 4010, 4011, 4012, 4013,
+// 4014, 4019, 5001, 5002, 5020, 5021, 5022, 5023, 6010, 6011, 6012, 6013,
+// 6014, 6015, 6016, 6018, 7002, 7003, 7014, 7015, 12001, 12006, 12007, 13005,
+// 14001, 14002, 14014, 14016, 14017, 22014, 22019.  Correct typing errors in
+// method 24005
+//
+// Correct the enumeration ValueMatrixMode. Correct typing errors at method
+// 13014. Extend explanation at 13015 and 13016
+//
+// Typing corrections in IDL:  Method 24005 comment changed. Change the word
+// 'calibrated' into     'recalculated' in method 4014 setUnit.
+//
+// Set the methods hasValueFlag and withValueFlag of the interface
+// ApplicationAttribute to deprecated. Change description of createAttribute
+// of interface ApplicationElement and ErrorCode AO_MISSING_VALUE.
+//
+// Add the interfaces ODSDirectory, ODSFile and ODSFileTransfer and
+// Enumeration FileOpenMode for the managed files. Add the methods
+// getODSDirectory in the interfaces ApplElemAccess and InstanceElement.
+//
+// Add the methods getEnumerationAttributes and getEnumerationStructure of the
+// interface AoSession with the required structures and sequences.
+//
+// Correct typing error's.
+//
+// Add AggrFunc DISTINCT, SelOpcode NOTLIKE and CI_NOTLIKE
+//
+// Remove ODSDirectory, change the way ODSFile is created. Change
+// FileOpenMode.
+//
+// Change the description of the method getUnit of the interface Column. 
+// Change the description of the methods of the interfaces ODSFile and
+// ODSFileTransfer.  Change the description of the enumerations
+// ValueMatrix_Mode and FileOpenMode.  Change the description of the structure
+// ApplRel.
+//
+// Remove Interface ODSFile and ODSFileTransfer and Enumeration FileOpneMode
+// with the methods which creates the ODSFile interface.
+//
+// 2009-09-25
+// Correct of some interfacaes and methods the description.   Finalize for
+// ASAM ODS version 5.2
+//
+// Add FOR_USER at auth parameter of method newSession of interface AoFactory 
+// Deprecated, solved by NVH Application model for following methods:
+// listScalingColumns, getScalingColumns, listColumnsScaledBy,
+// getColumnsScaledBy and addColumnScaledBy of interface ValueMatrix and the
+// methods isScaling and setScaling of interface Column
+//
+// Add AoSession.getId()  Add AoFactory.newSessionNameValue()  Add
+// SelOpcode.BETWEEN  Add AggrFunc.ORD  Add comment to
+// ApplElemAccess.getInstancesExt()
+//
+// Add method getODSFile at the interfaces ApplElemAccess and InstanceElement.
+//  Add the Interfaces ODSFile, ODSReadTransfer and ODSWriteTransfer.  Add
+// ErrorCode AO_FILE_LOCKED.  Add AoFile to the description of
+// AO_INVALID_BASETYPE
+//
+// Inherit ODSFile from InstanceElement. Rename method getOdsFile to
+// upcastOdsFile at interface InstanceElement. Add methods takeUnderControl
+// and removefromControl to the interface ODSFile. Method skipOctets returns
+// the real skipped number of octets.  Rename AggrFunc.ORD to AggrFunc.POINT
+//
+// Update description of the ODSFile methods and some error codes.
+//
+// Add the method getRelations at the interface BaseStructure.  Minor changes
+// in the description of some methods.  Add description for the exceptions
+// A_BAD_PARAMETER and AO_SYSTEM_PROBLEM at the method getOctetSeq of the
+// interface ODSReadTransfer.
+//
+// 2012-11-20
+// Final release ODS 5.3.0
+//
+//
+#ifndef ods_idl
+#define ods_idl
+
+module org {
+
+/**
+* ASAM services.
+*/
+module asam {
+
+/**
+* ASAM ODS service.
+*/
+module ods {
+interface AoFactory;
+interface AoSession;
+interface ApplicationAttribute;
+interface ApplicationElement;
+interface ApplicationRelation;
+interface ApplicationStructure;
+interface BaseAttribute;
+interface BaseElement;
+interface BaseRelation;
+interface BaseStructure;
+interface Blob;
+interface Column;
+interface InstanceElement;
+interface InstanceElementIterator;
+interface Measurement;
+interface NameIterator;
+interface NameValueIterator;
+interface NameValueUnitIterator;
+interface SMatLink;
+interface SubMatrix;
+interface ValueMatrix;
+interface NameValueUnitIdIterator;
+interface ApplElemAccess;
+interface QueryEvaluator;
+interface Query;
+interface NameValueUnitSequenceIterator;
+interface EnumerationDefinition;
+interface ElemResultSetExtSeqIterator;
+interface ODSFile;
+interface ODSReadTransfer;
+interface ODSWriteTransfer;
+
+/**
+* The ASAM ODS error severity flags.
+*/
+enum SeverityFlag {
+   SUCCESS,     // Ok.
+   INFORMATION, // Information.
+   WARNING,     // Warning.
+   ERROR        // Error.
+};
+
+/**
+* The ASAM ODS relation types.
+*/
+enum RelationType {
+   FATHER_CHILD, // Father-child relation.
+   INFO,         // Info relation.
+   INHERITANCE   // Inheritance relation.
+};
+
+/**
+* The ASAM ODS relationships.
+*/
+enum Relationship {
+   FATHER,    // Father.
+   CHILD,     // Child.
+   INFO_TO,   // Directed informational relationship.
+   INFO_FROM, // Directed informational relationship.
+   INFO_REL,  // Informational relationship (no direction)
+   SUPERTYPE, // Inheritance relationship: supertype.
+   SUBTYPE,   // Inheritance relationship: subtype.
+   ALL_REL    // Any of the relationships above.
+};
+
+/**
+* The ASAM ODS data types.
+*    DT_xxx  Basic data types.
+*    DS_xxx  Sequence of basic data type.
+*    ||
+*    |+- T == Type, S == Sequences.
+*    +-- D == Datatype.
+*/
+enum DataType {
+   DT_UNKNOWN,           // Unknown datatype.
+   DT_STRING,            // String.
+   DT_SHORT,             // Short value (16 bit).
+   DT_FLOAT,             // Float value (32 bit).
+   DT_BOOLEAN,           // Boolean value.
+   DT_BYTE,              // Byte value (8 bit).
+   DT_LONG,              // Long value (32 bit).
+   DT_DOUBLE,            // Double precision float value (64 bit).
+   DT_LONGLONG,          // LongLong value (64 bit).
+   DT_ID,                // LongLong value (64 bit). Not used. DT_LONGLONG is
+                         // used instead.
+   DT_DATE,              // Date. Meaning: YYYYMMDDhhmmsslllcccnnn....   -
+                         // YYYY = year, required.   - MM = month, optional.  
+                         // - DD =  day, optional.   - hh =  hour, optional.  
+                         // - mm =  minute, optional.   - ss =  second,
+                         // optional.   - lll =  millisec, optional, not
+                         // supported by Oracle timestamp.   - ccc =  microse,
+                         // optional, not supported by Oracle timestamp.   -
+                         // nnn =  nanosec, optional, not supported by Oracle
+                         // timestamp.
+   DT_BYTESTR,           // Bytestream.
+   DT_BLOB,              // Blob.
+   DT_COMPLEX,           // Complex value (32 bit each part).
+   DT_DCOMPLEX,          // Complex value (64 bit each part).
+   DS_STRING,            // String sequence.
+   DS_SHORT,             // Short sequence.
+   DS_FLOAT,             // Float sequence.
+   DS_BOOLEAN,           // Boolean sequene.
+   DS_BYTE,              // Byte sequence.
+   DS_LONG,              // Long sequence.
+   DS_DOUBLE,            // Double sequence.
+   DS_LONGLONG,          // Longlong sequence.
+   DS_COMPLEX,           // Complex sequence.
+   DS_DCOMPLEX,          // Double complex sequence.
+   DS_ID,                // LongLong sequence. Not used. DS_LONGLONG is used
+                         // instead.
+   DS_DATE,              // Date sequence.
+   DS_BYTESTR,           // Bytestream sequence.
+   DT_EXTERNALREFERENCE, // External reference.
+   DS_EXTERNALREFERENCE, // Sequence of external reference.
+   DT_ENUM,              // The enumeration datatype.
+   DS_ENUM               // The enumeration sequence datatype.
+};
+
+/**
+* The ASAM ODS build-up function codes for measurement views.
+*/
+enum BuildUpFunction {
+   BUP_JOIN,  // Join the columns
+   BUP_MERGE, // Merge the columns
+   BUP_SORT   // Sort the columns
+};
+
+/**
+* The ASAM ODS attribute type codes.
+*/
+enum AttrType {
+   APPLATTR_ONLY, // Report only application attributes.
+   INSTATTR_ONLY, // Report only instance attributes.
+   ALL            // All attributes.
+};
+
+/**
+* The ASAM ODS types for setting values.
+*/
+enum SetType {
+   APPEND, // Append data to the value matrix.
+   INSERT, // Insert data into the value matrix.
+   UPDATE, // Modify existing data of the value matrix.
+   REMOVE  // Remove the given information.
+};
+
+/**
+* The ASAM ODS error codes.
+*/
+enum ErrorCode {
+   AO_UNKNOWN_ERROR,
+   AO_ACCESS_DENIED,
+   AO_BAD_OPERATION,
+   AO_BAD_PARAMETER,
+   AO_CONNECT_FAILED,
+   AO_CONNECT_REFUSED,
+   AO_CONNECTION_LOST,
+   AO_DUPLICATE_BASE_ATTRIBUTE,
+   AO_DUPLICATE_NAME,
+   AO_DUPLICATE_VALUE,
+   AO_HAS_INSTANCES,
+   AO_HAS_REFERENCES,
+   AO_IMPLEMENTATION_PROBLEM,
+   AO_INCOMPATIBLE_UNITS,
+   AO_INVALID_ASAM_PATH,
+   AO_INVALID_ATTRIBUTE_TYPE,
+   AO_INVALID_BASE_ELEMENT,
+   AO_INVALID_BASETYPE,
+   AO_INVALID_BUILDUP_FUNCTION,
+   AO_INVALID_COLUMN,
+   AO_INVALID_COUNT,
+   AO_INVALID_DATATYPE,
+   AO_INVALID_ELEMENT,
+   AO_INVALID_LENGTH,
+   AO_INVALID_ORDINALNUMBER,
+   AO_INVALID_RELATION,
+   AO_INVALID_RELATION_RANGE,
+   AO_INVALID_RELATION_TYPE,
+   AO_INVALID_RELATIONSHIP,
+   AO_INVALID_SET_TYPE,
+   AO_INVALID_SMATLINK,
+   AO_INVALID_SUBMATRIX,
+   AO_IS_BASE_ATTRIBUTE,
+   AO_IS_BASE_RELATION,
+   AO_IS_MEASUREMENT_MATRIX,
+   AO_MATH_ERROR,
+   AO_MISSING_APPLICATION_ELEMENT,
+   AO_MISSING_ATTRIBUTE,
+   AO_MISSING_RELATION,
+   AO_MISSING_VALUE,
+   AO_NO_MEMORY,
+   AO_NO_PATH_TO_ELEMENT,
+   AO_NOT_FOUND,
+   AO_NOT_IMPLEMENTED,
+   AO_NOT_UNIQUE,
+   AO_OPEN_MODE_NOT_SUPPORTED,
+   AO_SESSION_LIMIT_REACHED,
+   AO_SESSION_NOT_ACTIVE,
+   AO_TRANSACTION_ALREADY_ACTIVE,
+   AO_TRANSACTION_NOT_ACTIVE,
+   AO_HAS_BASE_RELATION,
+   AO_HAS_BASE_ATTRIBUTE,
+   AO_UNKNOWN_UNIT,
+   AO_NO_SCALING_COLUMN,
+   AO_QUERY_TYPE_INVALID,
+   AO_QUERY_INVALID,
+   AO_QUERY_PROCESSING_ERROR,
+   AO_QUERY_TIMEOUT_EXCEEDED,
+   AO_QUERY_INCOMPLETE,
+   AO_QUERY_INVALID_RESULTTYPE,
+   AO_INVALID_VALUEMATRIX_STRUCTURE,
+   AO_FILE_LOCKED,
+   AO_SYSTEM_PROBLEM
+};
+
+/**
+* The selection operators.  SelOpcode gives query instructions like
+* "equal", "greater" etc. So far, these arguments were case sensitive.
+* There was a demand to add these arguments also for case insensitive
+* comparison operations. Therefore, the SelOpcodes for case insensitivity
+* were added. These arguments have the prefix “CI_”.
+*/
+enum SelOpcode {
+   EQ,          // Equal
+   NEQ,         // Not equal
+   LT,          // Less then
+   GT,          // Greater then
+   LTE,         // Less then equal
+   GTE,         // Greater then equal
+   INSET,       // In set, value can be a sequence.
+   NOTINSET,    // Not in set, value can be a sequence.
+   LIKE,        // like, use  pattern matching, see Pattern for the wildcard
+                // definitions.
+   CI_EQ,       // Equal. case insensitive for DT_STRING.
+   CI_NEQ,      // Not equal. case insensitive for DT_STRING.
+   CI_LT,       // Less then. case insensitive for DT_STRING.
+   CI_GT,       // Greater then. case insensitive for DT_STRING.
+   CI_LTE,      // Less then equal. case insensitive for DT_STRING.
+   CI_GTE,      // Greater then equal. case insensitive for DT_STRING.
+   CI_INSET,    // In set, value can be a sequence. case insensitive for
+                // DT_STRING.
+   CI_NOTINSET, // Not in set, value can be a sequence. case insensitive for
+                // DT_STRING.
+   CI_LIKE,     // like, use  pattern matching, see Pattern for the wildcard
+                // definitions. case insensitive for DT_STRING.
+   IS_NULL,     // Value is NULL
+   IS_NOT_NULL, // Value is not NULL
+   NOTLIKE,     // Not LIKE
+   CI_NOTLIKE,  // Not LIKE, case insensitive for DT_STRING.
+   BETWEEN      // Between; selects all instances where the value of 'attr'
+                // lies between the first two values given in 'value' (with
+                // 'attr', 'value' being elements of the SelValue structure;
+                // 'value' must be of data type S_*).
+};
+
+/**
+* Operator, bracket open and close.
+*/
+enum SelOperator {
+   AND,   // AND the two conditions.
+   OR,    // OR the two conditions.
+   NOT,   // Negate the next condition.
+   OPEN,  // Open brackets.
+   CLOSE  // Close brackets
+};
+
+/**
+* The ASAM ODS types for setting access rights.
+*/
+enum RightsSet {
+   SET_RIGHT,    // Set the given rights, overwrite the existing rights.
+   ADD_RIGHT,    // Add the given rights to the existing rights.
+   REMOVE_RIGHT  // Remove the given rights form the existing rights.
+};
+
+/**
+* Status of the query execution.
+*/
+enum QueryStatus {
+   COMPLETE,   // The execution is ready.
+   INCOMPLETE  // The execution is still running.
+};
+
+/**
+* The supported aggregate functions of the GetInstancesExt.
+*/
+enum AggrFunc {
+   NONE,     // No aggregate function is used for attribute.
+   COUNT,    // Count
+   DCOUNT,   // Distinct count
+   MIN,      // Min; only for numerical values
+   MAX,      // Max; only for numerical values
+   AVG,      // Average; only for numerical values
+   STDDEV,   // Standard deviation; only for numerical values
+   SUM,      // Sum; only for numerical values
+   DISTINCT, // Distinct
+   POINT     // The index of the values, only used by the attribute values of
+             // element AoLocalColumn
+};
+
+/**
+* The selection type.
+*/
+enum SelType {
+   SEL_VALUE_TYPE,    // Selection value.
+   SEL_OPERATOR_TYPE  // Selection logical operator.
+};
+
+/**
+* The type of the join.
+*/
+enum JoinType {
+   JTDEFAULT, // Force inner join.
+   JTOUTER    // Force outer join on destination AID.
+};
+
+/**
+* The mode of the value matrix.
+*/
+enum ValueMatrixMode {
+   CALCULATED, // The value matrix returns the calculated values.   The values
+               // of explicit columns are returned as they are stored in the
+               // physical storage.   The values of implicit columns are
+               // expanded and returned explicitly.  The values of raw columns
+               // are calculated according to the corresponding algorithm
+               // (using the calculation algorithms given by the values of the
+               // application attributes derived from the base attributes
+               // 'sequence_representation' and 'generation_parameters') and
+               // the resulting physical values are returned.  Writing to the
+               // value matrix is not allowed in this mode.
+   STORAGE     // The value matrix returns the values given in the physical
+               // storage.  The values of explicit columns are returned as
+               // they are stored in the physical storage.  The values of
+               // implicit columns are expanded and returned explicitly.  The
+               // values of raw columns are returned as they are stored
+               // (without using the calculation algorithms given by the
+               // values of the application attributes derived from the base
+               // attributes 'sequence_representation' and
+               // 'generation_parameters').  Writing to value matrix is
+               // allowed in this mode.
+};
+
+// Datatype definitions (T_xxx).
+typedef string     T_STRING;
+typedef boolean    T_BOOLEAN;
+typedef short      T_SHORT;
+typedef float      T_FLOAT;
+typedef octet      T_BYTE;
+typedef long       T_LONG;
+typedef double     T_DOUBLE;
+typedef T_STRING   Name;
+typedef T_STRING   Pattern;
+typedef T_STRING   BaseType;
+typedef T_STRING   T_DATE;
+typedef Blob       T_BLOB;
+
+// Sequence definitions (S_xxx).
+typedef sequence<T_BYTE> T_BYTESTR;
+typedef sequence<T_BOOLEAN> S_BOOLEAN;
+typedef sequence<T_BYTE> S_BYTE;
+typedef sequence<T_DOUBLE> S_DOUBLE;
+typedef sequence<T_FLOAT> S_FLOAT;
+typedef sequence<T_LONG> S_LONG;
+typedef sequence<T_SHORT> S_SHORT;
+typedef sequence<T_STRING> S_STRING;
+typedef sequence<BaseType> BaseTypeSequence;
+typedef sequence<Name> NameSequence;
+typedef sequence<Column> ColumnSequence;
+typedef sequence<SMatLink> SMatLinkSequence;
+typedef sequence<SubMatrix> SubMatrixSequence;
+typedef sequence<T_DATE> S_DATE;
+typedef sequence<T_BYTESTR> S_BYTESTR;
+typedef sequence<S_STRING> SS_STRING;
+typedef sequence<S_SHORT> SS_SHORT;
+typedef sequence<S_FLOAT> SS_FLOAT;
+typedef sequence<S_BOOLEAN> SS_BOOLEAN;
+typedef sequence<S_BYTE> SS_BYTE;
+typedef sequence<S_LONG> SS_LONG;
+typedef sequence<S_DOUBLE> SS_DOUBLE;
+typedef sequence<S_DATE> SS_DATE;
+typedef sequence<S_BYTESTR> SS_BYTESTR;
+typedef sequence<T_BLOB> S_BLOB;
+typedef sequence<ApplicationElement> ApplicationElementSequence;
+typedef sequence<ApplicationRelation> ApplicationRelationSequence;
+typedef sequence<ApplicationAttribute> ApplicationAttributeSequence;
+typedef sequence<BaseRelation> BaseRelationSequence;
+typedef sequence<BaseAttribute> BaseAttributeSequence;
+typedef sequence<BaseElement> BaseElementSequence;
+typedef sequence<InstanceElement> InstanceElementSequence;
+typedef sequence<SelOperator> SelOperatorSequence;
+
+/**
+* The ASAM ODS relation range structure.
+*/
+struct RelationRange {
+   T_SHORT min; // The minimum number in the range.
+   T_SHORT max; // The maximum number in the range. -1 means MANY without a
+                // specified maximum number.
+};
+
+/**
+* The ASAM ODS 64 bit integer structure.  This type is represented in the
+* datatype enumeration by DT_LONGLONG.
+*/
+struct T_LONGLONG {
+   T_LONG high; // The most significant 32 bits of the 64 bit value.
+   T_LONG low;  // The least significant 32 bits of the 64 bit value.
+};
+
+/**
+* The ASAM ODS complex data structure.  This type is represented in the
+* datatype enumeration by DT_COMPLEX.
+*/
+struct T_COMPLEX {
+   T_FLOAT r; // The real part of the complex number.
+   T_FLOAT i; // The imaginary part of the complex number.
+};
+
+/**
+* The ASAM ODS double-precision complex data structure. This type is
+* represented in the datatype enumeration by DT_DCOMPLEX.
+*/
+struct T_DCOMPLEX {
+   T_DOUBLE r; // The real part of the double precision complex number.
+   T_DOUBLE i; // The imaginary part of the double precision complex number.
+};
+
+/**
+* The ASAM ODS name-unit tuple structure.
+*/
+struct NameUnit {
+   Name     valName; // Attribute name or measured quantity name.
+   T_STRING unit;    // Column unit as string.
+};
+
+/**
+* The description of an reference object, the reference object can be an
+* internal ASAM ODS object or an external object. This type is
+* represented in the datatype enumeration by DT_EXTERNALREFERENCE.
+*/
+struct T_ExternalReference {
+   T_STRING description; // Description of the external reference.
+   T_STRING mimeType;    // MIME-type of the external object.
+   T_STRING location;    // Location of the external reference. (asam path or
+                         // URL)
+};
+
+/**
+* The application attribute information (metadata) definition. The same
+* information is available at the interface ApplicationAttribute
+*/
+struct ApplAttr {
+   Name       aaName;       // The application attribute name. The same name
+                            // is returned by the method getName() of the
+                            // ApplicationAttribute interface.     At the RPC
+                            // API this information was stored in the field
+                            // aAName of the structure AttrSeq and the request
+                            // AOP_GetAttr.
+   Name       baName;       // The name of the base attribute, empty ("") if
+                            // the application attribute is not derived from a
+                            // base attribute. The same name is returned by
+                            // the methods getName() of the BaseAttribute
+                            // interface. The base attribute is given by the
+                            // the method getBaseAttribute() of the interface
+                            // ApplicationAttribute.     At the RPC API this
+                            // information was stored in the field aBName of
+                            // the structure AttrSeq and the request
+                            // AOP_GetAttr.
+   DataType   dType;        // The attribute data type. The same data type is
+                            // given by the method getDataType of the
+                            // interface ApplicationAttribute.     At the RPC
+                            // API this information was stored in the field
+                            // aDataType of the structure AttrSeq and the
+                            // request AOP_GetAttr.
+   T_LONG     length;       // The maximum possible length of values. The same
+                            // length is returned by the method getLength() of
+                            // the interface ApplicationAttribute.
+   T_BOOLEAN  isObligatory; // The indicator for mandatory attributes, the
+                            // notNull indicator is set at the column of the
+                            // table in the physical storage.  The same
+                            // boolean is returned at the method
+                            // isObligatory() of the interface
+                            // ApplicationAttribute.
+   T_BOOLEAN  isUnique;     // The indicator for unique attributes. The same
+                            // boolean is returned by the method isUnique() of
+                            // the interface ApplicationAttribute.
+   T_LONGLONG unitId;       // Id of the unit if global defined. The same Id
+                            // is returned by the method getUnit() of the
+                            // interface ApplicationAttribute.     At the RPC
+                            // API this information was stored in the field
+                            // aUnit of the structure AttrSeq and the request
+                            // AOP_GetAttr.
+};
+
+/**
+* The application relation info structure. The same information is
+* available at the interface ApplicationRelation. 
+* 
+* A relation is the connection between two ASAM ODS elements; it may be
+* navigated in both
+* directions. The get- and set- methods are defined from the first
+* element, the getInverse- and
+* setInverse- methods work from the second element.
+*/
+struct ApplRel {
+   T_LONGLONG    elem1;            // The source application element Id. The
+                                   // given Id is the Id of the application
+                                   // element returned from the method
+                                   // getElem1() of the interface
+                                   // ApplicationRelation.     At the RPC API
+                                   // this information was stored in the field
+                                   // arAid1 of the structure ApplRelSeq and
+                                   // the request AOP_GetApplInf.
+   T_LONGLONG    elem2;            // The target application element Id. The
+                                   // given Id is the Id of the application
+                                   // element returned from the method
+                                   // getElem2() of the interface
+                                   // ApplicationRelation.     At the RPC API
+                                   // this information was stored in the field
+                                   // arAid2 of the structure ApplRelSeq and
+                                   // the request AOP_GetApplInf.
+   Name          arName;           // The relation name. The name is return
+                                   // with the method getName() of the
+                                   // interface ApplicationRelation.     At
+                                   // the RPC API this information was stored
+                                   // in the field arName of the structure
+                                   // ApplRelSeq and the request
+                                   // AOP_GetApplInf.
+   Name          invName;          // Name of the inverse relation. The name
+                                   // is return with the method
+                                   // getInverseName() of the interface
+                                   // ApplicationRelation. The invName is not
+                                   // available in the physical storage for
+                                   // relation databases.
+   Name          brName;           // Name of the base relation from the elem1
+                                   // to the elem2. The base relation is also
+                                   // not stored in the physical storage.
+   Name          invBrName;        // Name of the inverse base relation from
+                                   // the elem2 to the elem1. The base
+                                   // relation is also not stored in the
+                                   // physical storage.
+   RelationType  arRelationType;   // The type of the relation. Type of the
+                                   // relation is not stored in the physical
+                                   // storage. The relation type is return at
+                                   // the method getRelationType() of the
+                                   // interface ApplicationRelation.
+   RelationRange arRelationRange;  // The range of the relation. Range of the
+                                   // relation is not stored in the physical
+                                   // storage. The relation range is return at
+                                   // the method getRelationRange() of the
+                                   // interface ApplicationRelation.
+   RelationRange invRelationRange; // The inverse range of the relation. Range
+                                   // of the relation is not stored in the
+                                   // physical storage. The inverse relation
+                                   // range is return at the method
+                                   // getInverseRelationRange() of the
+                                   // interface ApplicationRelation.
+};
+
+/**
+* AID - Name pair.
+*/
+struct AIDName {
+   T_LONGLONG aid;    // The Id of the application element.
+   Name       aaName; // The attribute, or measured quantity name.
+};
+
+/**
+* Instance element Id. The unique description of an instance element.
+*/
+struct ElemId {
+   T_LONGLONG aid; // The Id of the application element.
+   T_LONGLONG iid; // The Id of the instance element.
+};
+
+/**
+* AID - Name - UnitId tuple.
+*/
+struct AIDNameUnitId {
+   AIDName    attr;   // The attribute  of the application element (aid,
+                      // name).
+   T_LONGLONG unitId; // The unit of the attribute or the column. The unitId
+                      // is the Id of instance element with the basetype
+                      // AoUnit.
+};
+
+/**
+* Order criteria.
+*/
+struct SelOrder {
+   AIDName   attr;      // Attribute specification.
+   T_BOOLEAN ascending; // ascending order, FALSE means descending.
+};
+
+/**
+* The access control list entry.
+*/
+struct ACL {
+   T_LONGLONG usergroupId; // The usergroup Id.
+   T_LONG     rights;      // The access rights of the requested object.
+};
+
+/**
+* An initial right.
+*/
+struct InitialRight {
+   T_LONG     rights;      // The initial access rights of the requested
+                           // object.
+   T_LONGLONG usergroupId; // The usergroup Id of the Initial right list.
+   T_LONGLONG refAid;      // The referencing application element.
+};
+
+/**
+* itÂ’s quite the same sequence as in the QueryStructure of GetInstances
+* with one exception. It has one new attribute called function, which is
+* of the type AggrFunc. Thereby  it is possible to define aggregate
+* functions on attribute level, without the need to parse the attribute
+* name for a known aggregate function name. The default value of that
+* attribute function is NONE, it symbolizes that no aggregate function
+* should be applied on that attribute.If an aggregate function is used,
+* it is also required to define a GroupSequence.It is also defined that a
+* ‘*’ as attribute name, delivers all attributes of an element.
+*/
+struct SelAIDNameUnitId {
+   AIDName    attr;      // The attribute  of the application element (aid,
+                         // name).
+   T_LONGLONG unitId;    // The unit of the attribute ot the column. The
+                         // unitId is the Id of instance element with the
+                         // basetype AoUnit.
+   AggrFunc   aggregate; // The aggregate function.
+};
+
+/**
+* Basically, joins can only be realized between application elements that
+* are linked via a reference defined in the model.From the definition of
+* attributes or application elements, the references for the joins are
+* determined. It is also taken into account that the application elements
+* involved are not linked directly. However, there must be an unambiguous
+* path between the application elements. The path may also include n:m
+* relations. The unambiguousness of relations between two application
+* elements no longer exists if more than one reference has been defined
+* between the application elements. In this case, these references must
+* have names and must be indicated explicitly in the request.For this
+* purpose, the request structure provides a sequence of relation
+* definitions (JoinDefSequence). The sequence in which the application
+* elements are addressed in the request also determines the sequence in
+* which the references between application elements are searched. Thus,
+* for every new application element, the server begins with the first
+* application element addressed in the request and tries to find a
+* relation from there. If no reference to the first application element
+* can be found, the search continues with the application element that
+* comes next in the request. Furthermore, the explicit relation
+* definitions (JoinDefSequence) enable an OUTER join, i.e. the result
+* also includes those records for which the join could not be
+* established.
+*/
+struct JoinDef {
+   T_LONGLONG fromAID;
+   T_LONGLONG toAID;
+   Name       refName;
+   JoinType   joiningType;
+};
+
+/**
+* The application relation with the instances to create the relation with
+* new instances.
+*/
+struct ApplicationRelationInstanceElementSeq {
+   ApplicationRelation     applRel;   // The application relation.
+   InstanceElementSequence instances; // The list with instances. The
+                                      // application element of the instances
+                                      // in the list must match one of the
+                                      // application elements of the
+                                      // application relation. All instances
+                                      // of the list must have the same
+                                      // application element.
+};
+
+/**
+* The structure with the attribute and the name of the enumeration.
+*/
+struct EnumerationAttributeStructure {
+   T_LONGLONG aid;      // The application element Id.
+   T_STRING   aaName;   // The name of the attribute
+   T_STRING   enumName; // The name of the enumeration
+};
+
+/**
+* The structure with the items of the enumeration.
+*/
+struct EnumerationItemStructure {
+   T_LONG   index;    // The index of the enuemration item.
+   T_STRING itemName; // The name of the item.
+};
+
+// Sequence definitions (S_xxx).
+typedef sequence<EnumerationAttributeStructure> EnumerationAttributeStructureSequence;
+typedef sequence<EnumerationItemStructure> EnumerationItemStructureSequence;
+typedef sequence<T_COMPLEX> S_COMPLEX;
+typedef sequence<T_DCOMPLEX> S_DCOMPLEX;
+typedef sequence<T_LONGLONG> S_LONGLONG;
+typedef sequence<S_LONGLONG> SS_LONGLONG;
+typedef sequence<S_COMPLEX> SS_COMPLEX;
+typedef sequence<S_DCOMPLEX> SS_DCOMPLEX;
+typedef sequence<T_ExternalReference> S_ExternalReference;
+typedef sequence<S_ExternalReference> SS_ExternalReference;
+typedef sequence<ApplAttr> ApplAttrSequence;
+typedef sequence<ApplRel> ApplRelSequence;
+typedef sequence<AIDName> AIDNameSequence;
+typedef sequence<AIDNameUnitId> AIDNameUnitIdSequence;
+typedef sequence<ElemId> ElemIdSequence;
+typedef sequence<SelOrder> SelOrderSequence;
+typedef sequence<ACL> ACLSequence;
+typedef sequence<InitialRight> InitialRightSequence;
+typedef sequence<SelAIDNameUnitId> SelAIDNameUnitIdSequence;
+typedef sequence<JoinDef> JoinDefSequence;
+typedef sequence<ApplicationRelationInstanceElementSeq> ApplicationRelationInstanceElementSeqSequence;
+
+/**
+* The application element definition. The same information is available
+* at the interface ApplicationElement.
+*/
+struct ApplElem {
+   T_LONGLONG       aid;        // The application element id. The id is given
+                                // also with the method getId() at the
+                                // interface ApplicationElement.     At the
+                                // RPC API this information was stored in the
+                                // field aiAId of the structure ApplInfSeq and
+                                // the request AOP_GetApplInf.
+   Name             beName;     // The base element name, all elements have a
+                                // basic element. The same name is returned by
+                                // the methods getType() of the BaseElement
+                                // interface. The base element is given with
+                                // the method getBaseElement() at the
+                                // interface ApplicationElement.     At the
+                                // RPC API this information was not delivered
+                                // but the corresponding Id of the base
+                                // element was stored in the field aiBId of
+                                // the structure ApplInfSeq and the request
+                                // AOP_GetApplInf.
+   Name             aeName;     // The application element name. The name is
+                                // given also with the method getName() at the
+                                // interface ApplicationElement.     At the
+                                // RPC API this information was stored in the
+                                // field aiName of the structure ApplInfSeq
+                                // and the request AOP_GetApplInf.
+   ApplAttrSequence attributes; // The attributes of application element. The
+                                // attributes are given with the method
+                                // getAttributes() of the interface
+                                // ApplicationElement. There are no relations
+                                // given in the this sequence.
+};
+
+/**
+* The structure with the enumeration and there items.
+*/
+struct EnumerationStructure {
+   T_STRING                         enumName; // The name of the enueration.
+   EnumerationItemStructureSequence items;    // The items of the enumeration.
+};
+
+/**
+* The union definition for all datatypes.
+*/
+union TS_Union switch (DataType) {
+   case DT_STRING:                      T_STRING                       stringVal;
+   case DT_SHORT:                       T_SHORT                        shortVal;
+   case DT_FLOAT:                       T_FLOAT                        floatVal;
+   case DT_BYTE:                        T_BYTE                         byteVal;
+   case DT_BOOLEAN:                     T_BOOLEAN                      booleanVal;
+   case DT_LONG:                        T_LONG                         longVal;
+   case DT_DOUBLE:                      T_DOUBLE                       doubleVal;
+   case DT_LONGLONG:                    T_LONGLONG                     longlongVal;
+   case DT_COMPLEX:                     T_COMPLEX                      complexVal;
+   case DT_DCOMPLEX:                    T_DCOMPLEX                     dcomplexVal;
+   case DT_DATE:                        T_DATE                         dateVal;
+   case DT_BYTESTR:                     T_BYTESTR                      bytestrVal;
+   case DT_BLOB:                        T_BLOB                         blobVal;
+   case DS_STRING:                      S_STRING                       stringSeq;
+   case DS_SHORT:                       S_SHORT                        shortSeq;
+   case DS_FLOAT:                       S_FLOAT                        floatSeq;
+   case DS_BYTE:                        S_BYTE                         byteSeq;
+   case DS_BOOLEAN:                     S_BOOLEAN                      booleanSeq;
+   case DS_LONG:                        S_LONG                         longSeq;
+   case DS_DOUBLE:                      S_DOUBLE                       doubleSeq;
+   case DS_LONGLONG:                    S_LONGLONG                     longlongSeq;
+   case DS_COMPLEX:                     S_COMPLEX                      complexSeq;
+   case DS_DCOMPLEX:                    S_DCOMPLEX                     dcomplexSeq;
+   case DS_DATE:                        S_DATE                         dateSeq;
+   case DS_BYTESTR:                     S_BYTESTR                      bytestrSeq;
+   case DT_EXTERNALREFERENCE:           T_ExternalReference            extRefVal;
+   case DS_EXTERNALREFERENCE:           S_ExternalReference            extRefSeq;
+   case DT_ENUM:                        T_LONG                         enumVal;
+   case DS_ENUM:                        S_LONG                         enumSeq;
+};
+
+/**
+* Define a union with sequences of a certain type. Using this union
+* instead of sequence <TS_Union> gives much better performance.
+*/
+union TS_UnionSeq switch (DataType) {
+   case DT_STRING:                      S_STRING                       stringVal;
+   case DT_SHORT:                       S_SHORT                        shortVal;
+   case DT_FLOAT:                       S_FLOAT                        floatVal;
+   case DT_BYTE:                        S_BYTE                         byteVal;
+   case DT_BOOLEAN:                     S_BOOLEAN                      booleanVal;
+   case DT_LONG:                        S_LONG                         longVal;
+   case DT_DOUBLE:                      S_DOUBLE                       doubleVal;
+   case DT_LONGLONG:                    S_LONGLONG                     longlongVal;
+   case DT_COMPLEX:                     S_COMPLEX                      complexVal;
+   case DT_DCOMPLEX:                    S_DCOMPLEX                     dcomplexVal;
+   case DT_DATE:                        S_DATE                         dateVal;
+   case DT_BYTESTR:                     S_BYTESTR                      bytestrVal;
+   case DT_BLOB:                        S_BLOB                         blobVal;
+   case DS_STRING:                      SS_STRING                      stringSeq;
+   case DS_SHORT:                       SS_SHORT                       shortSeq;
+   case DS_FLOAT:                       SS_FLOAT                       floatSeq;
+   case DS_BYTE:                        SS_BYTE                        byteSeq;
+   case DS_BOOLEAN:                     SS_BOOLEAN                     booleanSeq;
+   case DS_LONG:                        SS_LONG                        longSeq;
+   case DS_DOUBLE:                      SS_DOUBLE                      doubleSeq;
+   case DS_LONGLONG:                    SS_LONGLONG                    longlongSeq;
+   case DS_COMPLEX:                     SS_COMPLEX                     complexSeq;
+   case DS_DCOMPLEX:                    SS_DCOMPLEX                    dcomplexSeq;
+   case DS_DATE:                        SS_DATE                        dateSeq;
+   case DS_BYTESTR:                     SS_BYTESTR                     bytestrSeq;
+   case DT_EXTERNALREFERENCE:           S_ExternalReference            extRefVal;
+   case DS_EXTERNALREFERENCE:           SS_ExternalReference           extRefSeq;
+   case DT_ENUM:                        S_LONG                         enumVal;
+   case DS_ENUM:                        SS_LONG                        enumSeq;
+};
+
+// Sequence definitions (S_xxx).
+typedef sequence<EnumerationStructure> EnumerationStructureSequence;
+typedef sequence<ApplElem> ApplElemSequence;
+
+/**
+* The ASAM ODS value structure.  There is one flag for each value. If the
+* union (u) contains a sequence, the flag is valid for all values in that
+* sequence.
+* 
+* Meaning of flags:
+*    AO_VF_VALID(0x01)      The value is valid.
+*    AO_VF_VISIBLE(0x02)    The value has to be
+*                           visualized.
+*    AO_VF_UNMODIFIED(0x04) The value has not been
+*                           modified.
+*    AO_VF_DEFINED(0x08)    The value is defined. If
+*                           the value in a value matrix
+*                           is not available this bit
+*                           is not set.
+*   The normal value of the flag is 15.
+*/
+struct TS_Value {
+   TS_Union u;    // The value union for values of all known datatypes.
+   T_SHORT  flag; // The value flags.
+};
+
+/**
+* A structure with sequences of a certain type. Using this union instead
+* of sequence <TS_Value> gives much better performance.
+*/
+struct TS_ValueSeq {
+   TS_UnionSeq u;    // The value union for values of all known datatypes.
+   S_SHORT     flag; // See TS_Value flag.
+};
+
+/**
+* Application structure values. All values of the entire application
+* structure are stored in this structure and loaded to the Client on
+* request. 
+* 
+* At the RPC API this information delivered by the request AOP_GetApplInf
+* and AOP_GetAttr for each application element.
+*/
+struct ApplicationStructureValue {
+   ApplElemSequence applElems; // The list of application elements.
+   ApplRelSequence  applRels;  // The list of relations in the application
+                               // structure. The list of ApplRel's contains
+                               // distinct entries for relations and their
+                               // inverses. The field invName contains the
+                               // partner relation.  Both relation, the normal
+                               // and the inverse relation are given in the
+                               // sequence.
+};
+
+/**
+* The ASAM ODS name-value-unit tuple structure with a sequence of values.
+*/
+struct NameValueSeqUnit {
+   Name        valName; // Column name or measured quantity name.
+   TS_ValueSeq value;   // Column value (vector).
+   T_STRING    unit;    // Column unit as string.
+};
+
+/**
+* AID - Name - Value - UnitId quartet.
+*/
+struct AIDNameValueUnitId {
+   AIDName    attr;   // The attribute  of the application element (aid,
+                      // name).
+   T_LONGLONG unitId; // The unit of the attribute ot the column. The unitId
+                      // is the Id of instance element with the basetype
+                      // AoUnit.
+   TS_Value   values; // The attribute values with value flags.
+};
+
+/**
+* AID - Name - Value - UnitId quartet. Multiple values for on attribute.
+*/
+struct AIDNameValueSeqUnitId {
+   AIDName     attr;   // The attribute  of the application element (aid,
+                       // name).
+   T_LONGLONG  unitId; // The unit of the attribute ot the column. The unitId
+                       // is the Id of instance element with the basetype
+                       // AoUnit.
+   TS_ValueSeq values; // The column values with value flags.
+};
+
+/**
+* The ASAM ODS name-value-unitId tuple structure with a sequence of
+* values.
+*/
+struct NameValueSeqUnitId {
+   Name        valName; // Column name or measured quantity name.
+   TS_ValueSeq value;   // Column value (vector).
+   T_LONGLONG  unitId;  // Column unit as Id.
+};
+
+/**
+*  Structure for name value query or attribute search conditions.
+*/
+struct SelValue {
+   AIDNameValueUnitId attr;  // The attribute specification with unit of the
+                             // value.
+   SelOpcode          oper;  // The compare operator between the attribute and
+                             // value.
+   TS_Value           value; // Value for the condition.
+};
+
+/**
+* The ASAM ODS name-value-unitid tuple structure. This structure is
+* identical with the NameValueUnit, except the unit is given as an Id
+* insead of a string.
+*/
+struct NameValueUnitId {
+   Name       valName; // Attribute name or measured quantity name.
+   TS_Value   value;   // Attribute value or column value (vector).
+   T_LONGLONG unitId;  // Id of attribute or column unit.
+};
+
+/**
+* The attribute selection structure.
+*/
+struct SelValueExt {
+   AIDNameUnitId attr;  // The attribute specification with unit Id.
+   SelOpcode     oper;  // The compare operator between the attribute and
+                        // value.
+   TS_Value      value; // Value for the condition.
+};
+
+/**
+* Defines the sequence of selection attributes with their logical
+* operators. The Idea is to have the logical operators and the selection
+* values in one sequence. Therefore no implicit rules are necessary how
+* logical operators have to be interpreted to the corresponding selection
+* value.
+*/
+union SelItem switch (SelType) {
+   case SEL_VALUE_TYPE:                 SelValueExt                    value;
+   case SEL_OPERATOR_TYPE:              SelOperator                    operator;
+};
+
+// Sequence definitions (S_xxx).
+typedef sequence<NameValueSeqUnit> NameValueSeqUnitSequence;
+typedef sequence<AIDNameValueSeqUnitId> AIDNameValueSeqUnitIdSequence;
+typedef sequence<SelValue> SelValueSequence;
+typedef sequence<NameValueSeqUnitId> NameValueSeqUnitIdSequence;
+typedef sequence<SelItem> SelItemSequence;
+
+/**
+* The ASAM ODS name-value pair structure.
+*/
+struct NameValue {
+   Name     valName; // Attribute name or measured quantity name.
+   TS_Value value;   // Attribute value or column value (vector).
+};
+
+/**
+* The ASAM ODS name-value-unit tuple structure. This structure is
+* identical with the NameValueUnitId, except the unit is given as a
+* string insead of an Id.
+*/
+struct NameValueUnit {
+   Name     valName; // Attribute name or measured quantity name.
+   TS_Value value;   // Attribute value or column value (vector).
+   T_STRING unit;    // Attribute or column unit as string.
+};
+
+/**
+* The results for one attribute. The result set for all attributes are
+* given in the sequence of the result set.
+*/
+struct AttrResultSet {
+   NameValueSeqUnitId      attrValues; // The attribute result set of one
+                                       // element. All values have the same
+                                       // attribute (AIDName) and the same
+                                       // unit (UnitId). Only the first part
+                                       // of the possible attribute values are
+                                       // available in this result set. The
+                                       // size of the part depends on the
+                                       // parameter 'how_many' of the method
+                                       // 'getInstances' of the interface
+                                       // 'ApplElemAccess'.
+   NameValueUnitIdIterator rest;       // The rest of the results. The
+                                       // iterator provides access to the
+                                       // conseccutive
+                                       // NameValueSeqUnitId-packages of the
+                                       // result set.
+};
+
+/**
+* The query structure.
+* 
+* How to build a query.
+* 
+* A query is a search condition for instances. The instances are
+* specified by the values of the attributes. The search condition
+* represents an attribute value condition. This means the attribute value
+* specifies the selection of the instance or instance attribute. An
+* attribute is specified by the application element and the name of the
+* attribute (AIDName). The conditions are defined in the enumeration
+* SelOPCode. The values are given in the TS_Value or TS_Union structure.
+* If we like an Unit indepedent condition we needed to define the Unit at
+* the attribute, use AIDNameUnitId instead of AIDName, the server has to
+* convert the value to the proper attribute value. The attribute search
+* condition can be combined by operations defined in the enumeration
+* SelOperator. A query can be built with a sequence SelValue and
+* SelOperator.
+* 
+* How to read/write the query:
+* 
+* e.g.  SelValue1 AND SelValue2
+*   
+*          selValueSeq    = SelValue1, SelValue2
+*          selOPeratorSeq = AND  
+* 
+* e.g.  (SelValue1 AND SelValue2) OR SelValue3 
+*    
+*          selValueSeq    = SelValue1, SelValue2, SelValue3
+*          selOPeratorSeq = OPEN, AND, CLOSE, OR
+*    
+* e.g.  NOT(SelValue1 AND SelValue2) OR SelValue3 
+*    
+*          selValueSeq    = SelValue1, SelValue2, SelValue3
+*          selOPeratorSeq = NOT, OPEN, AND, CLOSE, OR
+*    
+*  e.g.  NOT(SelValue1) AND SelValue2 OR SelValue3 
+*    
+*          selValueSeq    = SelValue1, SelValue2, SelValue3
+*          selOPeratorSeq = NOT, AND, OR
+* 
+* There is no selection about the N:M relations.
+*  
+* There are no aggregate functions (MAX, MIN, COUNT etc.) defined so we
+* need no "group by" and "having" Clause. All the parts defined in the
+* "having"-clause can be defined in the select part.
+*/
+struct QueryStructure {
+   AIDNameUnitIdSequence anuSeq;  // The sequence of attributes to be
+                                  // reported. A pattern is accepted for the
+                                  // attribute name.    At the RPC API this
+                                  // information was stored in the fields
+                                  // applId and nuSeq of the structure
+                                  // GetValReq and the request AOP_GetVal. At
+                                  // the RPC API only one application element
+                                  // could be selected.
+   SelValueSequence      condSeq; // The query condition sequence.     At the
+                                  // RPC API this information was stored in
+                                  // the field nsSeq of the structure
+                                  // GetValReq and the request AOP_GetVal.
+   SelOperatorSequence   operSeq; // The query condition operator sequence.   
+                                  //  At the RPC API was the operator always
+                                  // 'AND'.
+   ElemId                relInst; // The related instance. (aid == 0 && iid ==
+                                  // 0) means no related instance specified.  
+                                  //         At the RPC API this information
+                                  // was stored in the field elemId of the
+                                  // structure GetValReq and the request
+                                  // AOP_GetVal.
+   Name                  relName; // Name of the relation.     At the RPC API
+                                  // this information was stored in the field
+                                  // refName of the structure GetValReq and
+                                  // the request AOP_GetVal.
+   SelOrderSequence      orderBy; // The order by sequence. The order of the
+                                  // result set.     At the RPC API it was not
+                                  // possiable to set the order.
+};
+
+/**
+* Restult set of one application element.
+*/
+struct ElemResultSetExt {
+   T_LONGLONG                 aid;    // The application element Id.
+   NameValueSeqUnitIdSequence values; // The attribute values of the instances
+                                      // of the given application element.
+};
+
+/**
+* The extended query structure.
+*/
+struct QueryStructureExt {
+   SelAIDNameUnitIdSequence anuSeq;  // The sequence of attributes to be
+                                     // reported. A pattern is accepted for
+                                     // the attribute name.    At the RPC API
+                                     // this information was stored in the
+                                     // fields applId and nuSeq of the
+                                     // structure GetValReq and the request
+                                     // AOP_GetVal. At the RPC API only one
+                                     // application element could be selected.
+   SelItemSequence          condSeq; // The query condition sequence.     At
+                                     // the RPC API this information was
+                                     // stored in the field nsSeq of the
+                                     // structure GetValReq and the request
+                                     // AOP_GetVal.
+   JoinDefSequence          joinSeq; // Defined the join between the
+                                     // application elements.
+   SelOrderSequence         orderBy; // The order by sequence. The order of
+                                     // the result set.     At the RPC API
+                                     // interface it was not possiable to set
+                                     // the order.
+   AIDNameSequence          groupBy; // Defines the grouping attributes for a
+                                     // request, necessary if aggregate
+                                     // functions are defined in the
+                                     // SelAIDNameUnitIdSequence.
+};
+
+// Sequence definitions (S_xxx).
+typedef sequence<NameValue> NameValueSequence;
+typedef sequence<NameValueUnit> NameValueUnitSequence;
+typedef sequence<AttrResultSet> AttrResultSetSequence;
+typedef sequence<ElemResultSetExt> ElemResultSetExtSequence;
+
+/**
+* The result set for one element. The result set for all elements are
+* given in the sequence of the result set.
+*/
+struct ElemResultSet {
+   T_LONGLONG            aid;        // The Id of the application element.
+   AttrResultSetSequence attrValues; // The selected attributes of the
+                                     // element. The number of values in each
+                                     // AttrResultSet are identical, the
+                                     // attributes of one element has always
+                                     // the position in the AttrResultSet.
+};
+
+/**
+* The Result set of the extended query. The iterator is for instance
+* oriented access.
+*/
+struct ResultSetExt {
+   ElemResultSetExtSequence    firstElems; // The sequence of the first
+                                           // how_many result elements.
+   ElemResultSetExtSeqIterator restElems;  // the iterator, which allows to
+                                           // iterate above the result values,
+                                           // the attributes of one instance
+                                           // each iteration.
+};
+
+// Sequence definitions (S_xxx).
+typedef sequence<ElemResultSet> ElemResultSetSequence;
+typedef sequence<ResultSetExt> ResultSetExtSequence;
+
+/**
+* The ASAM ODS query result types.
+*/
+interface ResultType {
+   const T_SHORT INSTELEM_ITERATOR_AS_RESULT = 0; // Iterator of instance elements as result of the query (the default).
+   const T_SHORT TABLE_ITERATOR_AS_RESULT = 1;    // Iterator for table access as result type of the query.
+   const T_SHORT TABLE_AS_RESULT = 2;             // Table as result type of the query.
+};
+
+/**
+* The lock mode of the server. The lock mode tells the way the server
+* will lock the objects as soon a modification of the server will be
+* done.
+*/
+interface LockMode {
+   const T_SHORT LOCK_INSTANCEELEMENT = 0;    // Lock the instance element. (Default LockMode)
+   const T_SHORT LOCK_APPLICATIONELEMENT = 1; // Lock the application element, all instances of the application element are locked.
+   const T_SHORT LOCK_CHILDREN = 2;           // Lock the children of the locked object. This mode can be combined with one of the upper two modi.
+};
+
+/**
+* The bits of the security rights.
+*/
+interface SecurityRights {
+   const T_LONG SEC_READ = 1;   // Read access is allowed.
+   const T_LONG SEC_UPDATE = 2; // Update access to an existing object is allowed.
+   const T_LONG SEC_INSERT = 4; // Creating new instances is allowed.
+   const T_LONG SEC_DELETE = 8; // Delete of the object is allowed.
+   const T_LONG SEC_GRANT = 16;  // Access rights may be passed on.
+};
+
+/**
+* The security level of an application element.
+*/
+interface SecurityLevel {
+   const T_LONG NO_SECURITY = 0;        // No security defined.
+   const T_LONG ELEMENT_SECURITY = 1;   // Security scaled for the application element.
+   const T_LONG INSTANCE_SECURITY = 2;  // Security scaled for instance elements.
+   const T_LONG ATTRIBUTE_SECURITY = 4; // Security scaled for appliation attributes.
+};
+
+/**
+* The ASAM ODS query constants.
+*/
+interface QueryConstants {
+   const T_LONG MaxDurationDEFAULT = 0;     // Default value of max duration parameter of the query  (no limitations).
+   const T_STRING MaxDuration = "MaxDuration";            // The ASAM ODS max duration parameter of the query.
+   const T_STRING QueryResultType = "QueryResultType";        // The ASAM ODS query result type parameter.
+   const T_LONG QueryResultTypeDEFAULT = ResultType::INSTELEM_ITERATOR_AS_RESULT; // Default value of the ASAM ODS query result type parameter.
+};
+
+/**
+* The ASAM ODS exception structure.
+*/
+exception AoException {
+   ErrorCode    errCode;
+   SeverityFlag sevFlag;
+   T_LONG       minorCode;
+   T_STRING     reason;
+};
+
+/**
+* The ASAM factory interface.
+*/
+interface AoFactory {
+
+   /** (2001)
+   * Get the description of the ASAM ODS factory. If the description is
+   * not available an empty string is returned and no exception is
+   * thrown. The server loads the description from the base attribute
+   * "description" of the instance of AoEnvironment.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The description of the ASAM ODS factory.
+   */
+   T_STRING getDescription()
+      raises (AoException);
+
+   /** (2002)
+   * Get the interface version of the ASAM ODS factory. The interface
+   * version is for each ODS version a fixed string. The string is the
+   * version of the interface implemented at the server. 
+   * 
+   * The format of the string is:
+   * V<Major Version Nr>.<Minor Version Nr>.<Revision Nr>
+   *   - Major Version Nr (numeric: [0-9]+)
+   *   - Minor Version Nr (numeric: [0-9]+)
+   *   - Revision Nr (numeric: [0-9]+)
+   * Example of the version specification is 'V5.1.0'.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The interface version of the ASAM ODS factory.
+   */
+   T_STRING getInterfaceVersion()
+      raises (AoException);
+
+   /** (2003)
+   * Get the name of the ASAM ODS factory. If the name is not available
+   * an empty string is returned and no exception is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The name of the ASAM ODS factory.
+   */
+   T_STRING getName()
+      raises (AoException);
+
+   /** (2004)
+   * Get the type of the ASAM ODS factory. If the type is not available
+   * an empty string is returned and no exception is thrown. The server
+   * loads the type from the base attribute "Application_model_type" of
+   * the instance of AoEnvironment.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The type of the ASAM ODS factory.
+   */
+   T_STRING getType()
+      raises (AoException);
+
+   /** (2005)
+   * Establish a new session to an ASAM ODS server. The server normally
+   * checks the activity of the session and will close the session after
+   * a time period of inactivity.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECT_FAILED
+   *    AO_CONNECT_REFUSED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_OPEN_MODE_NOT_SUPPORTED
+   *    AO_SESSION_LIMIT_REACHED
+   *
+   * @param  auth  A string that may contain authentication information.
+   *               The following values are currently supported:
+   *                  USER
+   *                  PASSWORD
+   *                  CREATE_COSESSION_ALLOWED
+   *                  FOR_USER
+   *                The values may be specified in any order and have to
+   *               be separated by comma.
+   *               The variable CREATE_COSESSION_ALLOWED
+   *                       Value (DT_STRING) TRUE or FALSE
+   *                       Default for CREATE_COSESSION_ALLOWED =
+   *               FALSE.
+   *                      The variable CREATE_COSESSION_ALLOWED is a
+   *               read-only variable in the session.
+   *               The variable FOR_USER is the name of the user for
+   *               which this session shall be created. If this value is
+   *               given, USER must be a superuser. Otherwise the
+   *               exception AO_CONNECT_REFUSED will be thrown.
+   *               Example:
+   *               "USER=hans, PASSWORD=secret, CREATE_COSESSION_ALLOWED
+   *               = TRUE"
+   *
+   * @return  The new created ASAM ODS session.
+   */
+   AoSession newSession(
+      in T_STRING auth)
+      raises (AoException);
+
+   /** (2006)
+   * Establish a new session to an ASAM ODS server. The server normally
+   * checks the activity of the session and will close the session after
+   * a time period of inactivity. The authentication is a list of
+   * NameValue which is an argument of the method.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECT_FAILED
+   *    AO_CONNECT_REFUSED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_OPEN_MODE_NOT_SUPPORTED
+   *    AO_SESSION_LIMIT_REACHED
+   *
+   * @param  auth  A list of NameValue with the parameters for the
+   *               authentication, the parameter is stored in the Name of
+   *               the NameValue and the value of the aprameter is stored
+   *               in the Value. Each entry in the list represent exact
+   *               one parameter. With this argument the values of the
+   *               parameters can contain also comma because these are
+   *               not used as separater.
+   *
+   * @return  The new created ASAM ODS session.
+   */
+   AoSession newSessionNameValue(
+      in NameValueSequence auth)
+      raises (AoException);
+
+}; // Interface AoFactory.
+
+/**
+* The ASAM ODS session interface.
+*/
+interface AoSession {
+
+   /** (3001)
+   * Abort (rollback) a transaction. The changes made in the transaction
+   * are lost.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   */
+   void abortTransaction()
+      raises (AoException);
+
+   /** (3002)
+   * Close session to an ASAM ODS server. Active transactions are
+   * committed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void close()
+      raises (AoException);
+
+   /** (3003)
+   * Commit a transaction. The changes made in the transaction become
+   * permanent.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   */
+   void commitTransaction()
+      raises (AoException);
+
+   /** (3004)
+   * Get the application model from the current session by returning an
+   * object with the interface ApplicationStructure. The complete
+   * information on the application model is available through that
+   * interface.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application structure.
+   */
+   ApplicationStructure getApplicationStructure()
+      raises (AoException);
+
+   /** (3005)
+   * Get the application model as values from the current session.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application structure as value.
+   */
+   ApplicationStructureValue getApplicationStructureValue()
+      raises (AoException);
+
+   /** (3006)
+   * Get the ASAM ODS base model from the current session by returning an
+   * object with the interface BaseStructure. The complete information on
+   * the base model is available through that interface; it includes all
+   * possible base elements with all possible base attributes as
+   * specified by ASAM ODS.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The base structure.
+   */
+   BaseStructure getBaseStructure()
+      raises (AoException);
+
+   /** (3007)
+   * Get context variables from the session. A pattern string can be
+   * specified to select groups of variables.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  varPattern  The name or the search pattern for the context
+   *                     variable(s).
+   *
+   * @return  A list of context variables.
+   */
+   NameValueIterator getContext(
+      in Pattern varPattern)
+      raises (AoException);
+
+   /** (3008)
+   * Get a context variable by its name from the session.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  varName  The name of the requested context variable.
+   *
+   * @return  The requested context variable.
+   */
+   NameValue getContextByName(
+      in Name varName)
+      raises (AoException);
+
+   /** (3009)
+   * List the names of context variables from the session. A pattern
+   * string can be specified to select groups of variables.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NOT_FOUND
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  varPattern  The name or the search pattern for the context
+   *                     variable(s).
+   *
+   * @return  A list of context variable names.
+   */
+   NameIterator listContext(
+      in Pattern varPattern)
+      raises (AoException);
+
+   /** (3010)
+   * Remove context variables from the session. A pattern string can be
+   * specified to remove groups of variables.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NOT_FOUND
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  varPattern  The name or the search pattern for the context
+   *                     variable(s) to be removed.
+   */
+   void removeContext(
+      in Pattern varPattern)
+      raises (AoException);
+
+   /** (3011)
+   * Set/modify a known context variable or add a new context variable to
+   * the session.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  contextVariable  The context variable.
+   */
+   void setContext(
+      in NameValue contextVariable)
+      raises (AoException);
+
+   /** (3012)
+   * Set/modify a known context variable or add a new context variable to
+   * the session. This is a convenience method for the frequently used
+   * string variable type. It uses setContext  internally.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  varName  The name of the context variable.
+   *
+   * @param  value  The value of the context variable.
+   */
+   void setContextString(
+      in Name varName,
+      in T_STRING value)
+      raises (AoException);
+
+   /** (3013)
+   * Start a transaction on the physical storage system (e.g. database
+   * system). Only when a transaction is started it is allowed to create
+   * or modify instances or measurement data. The changes get permanent
+   * with a commit of the transaction or will be lost with an abort of
+   * the transaction. If the session is closed the transaction will be
+   * committed automatically. If a transaction is already active an
+   * exception is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_ALREADY_ACTIVE
+   */
+   void startTransaction()
+      raises (AoException);
+
+   /** (3014)
+   * Make the changes permanent.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   */
+   void flush()
+      raises (AoException);
+
+   /** (3015)
+   * Every new created instance will set its initial rights to <acl> .
+   * This method overrides the default-methods for applying initial
+   * rights. The initial rights are only valid for the current session.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  irlEntries  The current initial rights.
+   *
+   * @param  set  Set (1) or remove (0) the current initial rights. The
+   *              previous initial rights get lost. If the parameter set
+   *              is 0 (remove) the parameter irlEntries will be ignored.
+   */
+   void setCurrentInitialRights(
+      in InitialRightSequence irlEntries,
+      in T_BOOLEAN set)
+      raises (AoException);
+
+   /** (3016)
+   * Get the current lock mode. The lock mode tells the server which
+   * objects to lock for upcoming changes. Application elements, instance
+   * elements or children of elements can be locked.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The current lock mode. The lock mode constants are defined
+   *          in the interface LockMode. The interface definition
+   *          language IDL does not allow to set the values of
+   *          enumerations thus the constant definitions had to be done
+   *          in an interface.
+   */
+   T_SHORT getLockMode()
+      raises (AoException);
+
+   /** (3017)
+   * Set the new lock mode. The lock mode tells the server which objects
+   * to lock for upcoming changes. Application elements, instance
+   * elements or children of elements can be locked.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  lockMode  The new lock mode. The lock mode constants are
+   *                   defined in the interface LockMode. The interface
+   *                   definition language IDL does not allow to set the
+   *                   values of enumerations thus the constant
+   *                   definitions had to be done in an interface.
+   */
+   void setLockMode(
+      in T_SHORT lockMode)
+      raises (AoException);
+
+   /** (3018)
+   * Get the application element access object from the current session.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application element access object.
+   */
+   ApplElemAccess getApplElemAccess()
+      raises (AoException);
+
+   /** (3019)
+   * Change the password for user defined by <username> to <newPassword>.
+   * A normal user must supply his current password <oldPassword>. The
+   * super user can change the password without supplying the current
+   * password <oldPassword>. If no username is given the password of the
+   * user of the current session will be changed. The password is
+   * normally encrypted in the attribute of the user instance element.
+   * Creating a new user can be done by creating a new instance,
+   * afterwards the password must be set by the super user.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_WRONG_PASSWORD
+   *
+   * @param  username  The name of the user for which the password will
+   *                   be changed. If no username is given the password
+   *                   of the current user will be changed. If the
+   *                   username differs from the current user the current
+   *                   user must be a super user.
+   *
+   * @param  oldPassword  The current password of the user. A normal user
+   *                      must supply his current password. The super
+   *                      user can change the password without supplying
+   *                      the current password.
+   *
+   * @param  newPassword  The new password of the user.
+   */
+   void setPassword(
+      in T_STRING username,
+      in T_STRING oldPassword,
+      in T_STRING newPassword)
+      raises (AoException);
+
+   /** (3020)
+   * Get the description of the ASAM ODS session. The description of the
+   * session is identical with description of the ASAM ODS factory. If
+   * the description is not available an empty string is returned and no
+   * exception is thrown. The server loads the description from the base
+   * attribute "description" of the instance of AoEnvironment.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_CONNECTION_LOST
+   *
+   * @return  The description of the ASAM ODS session.
+   */
+   T_STRING getDescription()
+      raises (AoException);
+
+   /** (3021)
+   * Get the name of the ASAM ODS session. The name of the session is
+   * identical with the name of the ASAM ODS factory. If the name is not
+   * available an empty string is returned and no exception is thrown.
+   * The server loads the name from the base attribute "name" of the
+   * instance of AoEnvironment.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_CONNECTION_LOST
+   *
+   * @return  The name of the ASAM ODS session.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (3022)
+   * Get the type of the ASAM ODS session. The type of the session is
+   * identical with the type of the ASAM ODS factory. If the type is not
+   * available an empty string is returned and no exception is thrown.
+   * The server loads the type from the base attribute
+   * "Application_model_type" of the instance of AoEnvironment.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_CONNECTION_LOST
+   *
+   * @return  The type of the ASAM ODS session.
+   */
+   T_STRING getType()
+      raises (AoException);
+
+   /** (3023)
+   * Create a QueryEvaluator object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The new created query evaluator object
+   */
+   QueryEvaluator createQueryEvaluator()
+      raises (AoException);
+
+   /** (3024)
+   * Create a new object with the Interface Blob on the server. This
+   * object can be used to create an attribute value of the data type
+   * DT_BLOB.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The reference of the blob object which is generated at the
+   *          server.
+   */
+   Blob createBlob()
+      raises (AoException);
+
+   /** (3025)
+   * Create a co session. The co session session is the same session as
+   * the original session was at login time.
+   * The co session has no relation to the original session except that
+   * the same authentication is used.
+   * A client application with components can give all components his own
+   * session to the ASAM ODS Server. So the component can close the
+   * session when it is ready, the component can start his own
+   * transaction without any conflict with other components. 
+   * Only when the variable CREATE_COSESSION_ALLOWED=TRUE is given in the
+   * 'auth' parameter of the method newSession at the interface AoFactory
+   * an new session will be created otherwise the exception
+   * AO_ACCESS_DENIED is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_ACCESS_DENIED
+   *
+   * @return  The co session.
+   */
+   AoSession createCoSession()
+      raises (AoException);
+
+   /** (3026)
+   * Returns the instance element of the user logged in, this is the
+   * instance element from the application element derived from AoUser,
+   * with the name given in s given in the 'auth' parameter of the method
+   * newSession at the interface AoFactory (variable USER). 
+   * 
+   * When the client settings of the user are stored in the ASAM ODS
+   * application model, this methods helps the client  to get his
+   * settings.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The instance element of the logged in user.
+   */
+   InstanceElement getUser()
+      raises (AoException);
+
+   /** (3027)
+   * Get the list with the attributes of all elements and the enumeration
+   * name which has an enumeration.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @return  The list with attribute and there enumeration.
+   */
+   EnumerationAttributeStructureSequence getEnumerationAttributes()
+      raises (AoException);
+
+   /** (3028)
+   * Get all enumerations used in the application model. The enumerations
+   * and all items of the enumerations are returned to the client.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The enumeration with there Items.
+   */
+   EnumerationStructureSequence getEnumerationStructure()
+      raises (AoException);
+
+   /** (3029)
+   * Returns the Id of the session, the ODS server will give each session
+   * an unique Id. The ODS server returns this Id to the client.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *
+   * @return  The Id of the session.
+   */
+   T_LONG getId()
+      raises (AoException);
+
+}; // Interface AoSession.
+
+/**
+* The ASAM ODS application attribute interface.
+*/
+interface ApplicationAttribute {
+
+   /** (4001)
+   * Get the base attribute of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The base attribute of the application attribute. A 'null'
+   *          is returned if the application attribute has no base
+   *          attribute.
+   */
+   BaseAttribute getBaseAttribute()
+      raises (AoException);
+
+   /** (4002)
+   * Get the data type of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The data type of the application attribute.
+   */
+   DataType getDataType()
+      raises (AoException);
+
+   /** (4003)
+   * Get the maximum allowed length of the value of the application
+   * attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The maximum allowed length of the application attribute.
+   */
+   T_LONG getLength()
+      raises (AoException);
+
+   /** (4004)
+   * Get the name of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the application attribute.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (4005)
+   * Get the unit Id of the application attribute. The unit Id is only
+   * valid for the current server.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The unit Id of the application attribute.
+   */
+   T_LONGLONG getUnit()
+      raises (AoException);
+
+   /** (4006)
+   * Get the obligatory flag of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The obligatory flag of the application attribute.
+   */
+   T_BOOLEAN isObligatory()
+      raises (AoException);
+
+   /** (4007)
+   * Get the unique flag of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The unique flag of the application attribute.
+   */
+   T_BOOLEAN isUnique()
+      raises (AoException);
+
+   /** (4008)
+   * Set the base attribute of the application attribute. This allows the
+   * client to declare the application attribute (new or existing)
+   * additional to a base attribute. The application attribute will
+   * become the derived attribute of the given base attribute.
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The base attribute must be unique within the application element
+   * otherwise the exception AO_DUPLICATE_BASE_ATTRIBUTE is thrown.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exceptions:
+   *    AO_INVALID_DATATYPE
+   *    AO_MISSING_VALUE
+   *    AO_NOT_UNIQUE.
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the following problems:
+   * 
+   * AO_INVALID_DATATYPE: The data type of the base attribute is not the
+   * same as the data type of the instantiated attributes.
+   * 
+   * AO_MISSING_VALUE: The obligatory flag of the base attribute is set
+   * but there are one or more empty values in the instances.
+   * 
+   * AO_NOT_UNIQUE: The unique flag of the base attribute is set but the
+   * values of the instances are not unique.
+   * 
+   * The length, the name and the unit of the application attribute are
+   * not affected by this call.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_DATATYPE
+   *    AO_MISSING_VALUE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NOT_UNIQUE
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baseAttr  The base attribute.
+   */
+   void setBaseAttribute(
+      in BaseAttribute baseAttr)
+      raises (AoException);
+
+   /** (4009)
+   * Set the data type of the application attribute. 
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * It is not allowed to set the data type of application attributes
+   * that represent base attributes. An attempt to set the data type of
+   * such an application attribute will result in the exception
+   * AO_IS_BASE_ATTRIBUTE.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exception:
+   *    AO_INVALID_DATATYPE
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the following problem:
+   * 
+   * AO_INVALID_DATATYPE: The data type of the base attribute is not the
+   * same as the data type of the instantiated attributes.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_DATATYPE
+   *    AO_IS_BASE_ATTRIBUTE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaDataType  The data type.
+   */
+   void setDataType(
+      in DataType aaDataType)
+      raises (AoException);
+
+   /** (4010)
+   * Set the obligatory flag of the application attribute.
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * It is not allowed to set the obligatory flag of application
+   * attributes
+   * that represent base attributes. An attempt to set the obligatory
+   * flag of such an application attribute will result in the exception
+   * AO_IS_BASE_ATTRIBUTE.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exception:
+   *    AO_MISSING_VALUE
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the following problem:
+   * 
+   * AO_MISSING_VALUE: The obligatory flag of the base attribute is set
+   * but there are one or more empty values in the instances.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_IS_BASE_ATTRIBUTE
+   *    AO_MISSING_VALUE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaIsObligatory  The obligatory flag.
+   */
+   void setIsObligatory(
+      in T_BOOLEAN aaIsObligatory)
+      raises (AoException);
+
+   /** (4011)
+   * Set the unique flag of the application attribute. 
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The server will check if the values of the instance attributes are
+   * unique. If this flag is set and the values of an attribute are not
+   * unique when using the method setValue an exception is thrown. If
+   * instances of the application element already exist that contain
+   * non-unique values and the flag shall be set this method throws an
+   * exception.
+   * 
+   * It is not allowed to set the unique flag of application attributes
+   * that represent base attributes. An attempt to set the unique flag of
+   * such an application attribute will result in the exception
+   * AO_IS_BASE_ATTRIBUTE.
+   * 
+   * If the unique flag is set to TRUE the obligatory flag is also set to
+   * TRUE. The previous values of both flag do not matter in this case.
+   * Setting the unique flag to FALSE does not affect the obligatory
+   * flag.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exception:
+   *    AO_MISSING_VALUE
+   *    AO_NOT_UNIQUE
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the following problem:
+   * 
+   * AO_MISSING_VALUE: The obligatory flag of the base attribute is set
+   * but there are one or more empty values in the instances.
+   * 
+   * AO_NOT_UNIQUE: The unique flag of the base attribute is set but the
+   * values of the instances are not unique.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_IS_BASE_ATTRIBUTE
+   *    AO_MISSING_VALUE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NOT_UNIQUE
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaIsUnique  The unique flag.
+   */
+   void setIsUnique(
+      in T_BOOLEAN aaIsUnique)
+      raises (AoException);
+
+   /** (4012)
+   * Set the maximum allowed length of the application attribute. The
+   * maximum value  accepted by the ASAM ODS server for this length
+   * information depends on the underlying physical storage. For the
+   * physical storage specified in chapter 3 the maximum allowed length
+   * will be stored in the AFLEN value in SVCATTR, and it is restricted
+   * by the maximum length of string type database fields. If a length is
+   * specified that exceeds the capabilities of the underlying physical
+   * storage the server will throw the exception AO_INVALID_LENGTH. 
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction. 
+   * 
+   * This method is useful for ODS database design tools. Negative length
+   * values are not allowed.
+   * 
+   * This method provides only a hint to a database server in the design
+   * phase which size the data entries may have. The length is only
+   * relevant for is ignored for all attribute values with the data type
+   * other datatypes than DT_STRING, DS_STRING, DT_DATE, DS_DATE, all
+   * components of DT_EXTERNALREFERENCE and of DS_EXTERNALREFERENCE, and
+   * the header portion of DT_BLOB.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exception:
+   *    AO_HAS_INSTANCES
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the exception AO_HAS_INSTANCES
+   * if the instances of the application attribute are not empty.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_INSTANCES
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_LENGTH
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaLength  The maximum attribute length.
+   */
+   void setLength(
+      in T_LONG aaLength)
+      raises (AoException);
+
+   /** (4013)
+   * Set the name of an application attribute. 
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The name must be unique.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * The name of an application attribute must not exceed the maximum
+   * name length of the underlying physical storage. Current server
+   * implementations typically restrict it to 30 characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_NAME
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaName  The application attribute name.
+   */
+   void setName(
+      in Name aaName)
+      raises (AoException);
+
+   /** (4014)
+   * Set the unit Id of an application attribute. 
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The unit Id is only valid for the current server. If instances of
+   * the application attribute exist, the respective values are
+   * automatically converted to the new unit. If there is no known
+   * conversion an exception is thrown.
+   * 
+   * The automatic conversion can be avoided if the unit is set to zero.
+   * After that the transaction must be committed. In the next step the
+   * new unit may be set in another transaction.
+   * 
+   * The automatic conversion is done only for the following data
+   * types:
+   *    DT_BYTE
+   *    DT_COMPLEX
+   *    DT_DCOMPLEX
+   *    DT_DOUBLE
+   *    DT_FLOAT
+   *    DT_LONG
+   *    DT_LONGLONG
+   *    DT_SHORT
+   * as well as for the corresponding sequence data types. For complex
+   * data types the real and imaginary part are converted separately.
+   * 
+   * If the unit of an attribute is set the unit is constant. If the
+   * value of the attribute has another unit the value is recalculated to
+   * the unit of the application attribute. If there is no unit at the
+   * application attribute the unit at the attribute value is stored and
+   * reported on request at the instance.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   * 
+   * If this method is called before the first commit it will not throw
+   * the following exceptions:
+   *    AO_INCOMPATIBLE_UNITS
+   *    AO_MATH_ERROR
+   * 
+   * After the first commit, there may be instances of the application
+   * attribute. These instances may cause the following problems:
+   * 
+   * AO_INCOMPATIBLE_UNITS: No conversion rules is known to convert the
+   * unit.
+   * 
+   * AO_MATH_ERROR: Converting the values to the new unit results in data
+   * overflow or underflow or a division by zero is detected.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INCOMPATIBLE_UNITS
+   *    AO_MATH_ERROR
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_UNKNOWN_UNIT
+   *
+   * @param  aaUnit  The unit Id.
+   */
+   void setUnit(
+      in T_LONGLONG aaUnit)
+      raises (AoException);
+
+   /** (4015)
+   * The given user group the rights should be set for. <rights> defines
+   * the rights to set or to clear. If the parameter <set> is set to
+   * 'set', the rights in <rights> are set all others are cleared. If the
+   * parameter <set> is set to 'add', the rights in <rights> are added to
+   * the existing rights. If the parameter <set> is set to 'remove', the
+   * rights in <rights> are removed from the existing rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  usergroup  The user group for which the rights will be
+   *                    modified.
+   *
+   * @param  rights  The new right for the user group. The rights
+   *                 constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setRights(
+      in InstanceElement usergroup,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (4016)
+   * Retrieve access control list information of the given object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The access control list entries of the given application
+   *          element.
+   */
+   ACLSequence getRights()
+      raises (AoException);
+
+   /** (4017)
+   * Return the application element to which the attribute belongs.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application element of the attribute.
+   */
+   ApplicationElement getApplicationElement()
+      raises (AoException);
+
+   /** (4018)
+   * Get the auto generate flag of the application attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The auto generate flag of the application attribute.
+   */
+   T_BOOLEAN isAutogenerated()
+      raises (AoException);
+
+   /** (4019)
+   * Set the auto generate flag of the application attribute.
+   * 
+   * It is allowed to modify the application attribute outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * For performance and flexibility reasons this set-method should be
+   * used before the new application attribute is committed the first
+   * time.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_IS_BASE_ATTRIBUTE
+   *    AO_MISSING_VALUE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  isAutogenerated  The auto generate flag.
+   */
+   void setIsAutogenerated(
+      in T_BOOLEAN isAutogenerated)
+      raises (AoException);
+
+   /** (4020)
+   * Get the definition of the enumeration.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_DATATYPE
+   *
+   * @return  The ASAM ODS enumeration.
+   */
+   EnumerationDefinition getEnumerationDefinition()
+      raises (AoException);
+
+   /** (4021)
+   * Set the definition of the enumeration. This method modifies the
+   * application model, only the super user can use this method.
+   * 
+   * The AoException AO_INVALID_DATATYPE is thrown when the data type of
+   * the attribute is not DT_ENUM.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *    AO_INVALID_DATATYPE
+   *
+   * @param  enumDef  The new enumeration definition.
+   */
+   void setEnumerationDefinition(
+      in EnumerationDefinition enumDef)
+      raises (AoException);
+
+   /** (4022)
+   * Has the attribute an unit. If this flag is set, all the attributes
+   * of the instances derived from this attribute will has an unit.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The flag if the attribute has an unit.
+   */
+   T_BOOLEAN hasUnit()
+      raises (AoException);
+
+   /** (4023)
+   * Set whether the attribute becomes an unit or not. A call to the
+   * method setUnit() will automatically set the withUnit(TRUE).
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  withUnit  The flag if the attribute becomes an unit.
+   */
+   void withUnit(
+      in T_BOOLEAN withUnit)
+      raises (AoException);
+
+   /** (4024)
+   * Deprecated, not used any more since ASAM ODS 5.2. 
+   * Has the attribute a value flag. If this flag is set, all the
+   * attributes of the instances derived from this attribute will has a
+   * value flag. If this flag is not set the flag in the TS_Value
+   * structure can be ignored.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The flag if the attribute has a value flag.
+   */
+   T_BOOLEAN hasValueFlag()
+      raises (AoException);
+
+   /** (4025)
+   * Deprecated, not used any more since ASAM ODS 5.2. 
+   * Set whether the attribute becomes a value flag or not. If this flag
+   * isn't set the flag of the TS_Value will be ignored by the server.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  withValueFlag  The flag if the attribute becomes a value
+   *                        flag.
+   */
+   void withValueFlag(
+      in T_BOOLEAN withValueFlag)
+      raises (AoException);
+
+}; // Interface ApplicationAttribute.
+
+/**
+* The ASAM ODS application element interface.
+*/
+interface ApplicationElement {
+
+   /** (5001)
+   * Create a new application attribute on the server. 
+   * 
+   * It is allowed to modify the application element outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The properties of the new application attribute may be changed via
+   * the set-methods of the ApplicationAttribute interface.
+   * 
+   * For performance reasons it is recommended to set all required
+   * properties of an application attribute before it is committed the
+   * first time. This avoids database cross-checks for each attribute.
+   * 
+   * The default properties of a new application attribute are:
+   *    BaseAttribute   NULL
+   *    DataType        DT_UNKNOWN
+   *    IsObligatory    0
+   *    IsUnique        0
+   *    Length          0
+   *    Name            "AUTOGEN"
+   *    Unit            NULL
+   * 
+   * If there are already instances of the application element the values
+   * of the existing instances of the new attribute are set to
+   * undefined.
+   * 
+   * The exception AO_DUPLICATE_NAME name occurs if there is already
+   * another application attribute with the name "AUTOGEN".
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_NAME
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @return  The new application attribute.
+   */
+   ApplicationAttribute createAttribute()
+      raises (AoException);
+
+   /** (5002)
+   * Create an instance of the application element. 
+   * 
+   * It is allowed to create an instance outside a transaction but it is
+   * recommended to activate a transaction.
+   * 
+   * The instance gets permanent when the  transaction is committed.  All
+   * attributes connected to the application element are automatically
+   * created and connected to the instance. The values of the attributes
+   * can be set by the method setValue of the interface InstanceElement.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  ieName  The instance name.
+   *
+   * @return  The new instance.
+   */
+   InstanceElement createInstance(
+      in Name ieName)
+      raises (AoException);
+
+   /** (5003)
+   * Get a list of all related application elements connected to this
+   * application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The related application elements.
+   */
+   ApplicationElementSequence getAllRelatedElements()
+      raises (AoException);
+
+   /** (5004)
+   * Get a list of all application relations connected to this
+   * application element. The inverse relation of relations connected to
+   * other application elements pointing to the given application
+   * elements are not returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application relations of the application element.
+   */
+   ApplicationRelationSequence getAllRelations()
+      raises (AoException);
+
+   /** (5005)
+   * Get the application attribute of an application element which is
+   * inherited from the base attribute with the given name. The base name
+   * is case insensitive and may not contain wildcard characters. 
+   * 
+   * Note: The base model is case blind,  e.g. Id, ID and id is all the
+   * same base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baName  The base attribute name.
+   *
+   * @return  The application attribute.
+   */
+   ApplicationAttribute getAttributeByBaseName(
+      in Name baName)
+      raises (AoException);
+
+   /** (5006)
+   * Get the application attribute of an application element which has
+   * the given name. The name is case sensitive and may not contain
+   * wildcard characters.
+   * 
+   * Note: The application model is case sensitive, e.g. Id and ID are
+   * different application attributes, don't use this misleading
+   * attribute name.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaName  The application attribute name.
+   *
+   * @return  The application attribute.
+   */
+   ApplicationAttribute getAttributeByName(
+      in Name aaName)
+      raises (AoException);
+
+   /** (5007)
+   * Get a list of the application attributes of an application element.
+   * The reference attributes are not returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaPattern  The name or the search pattern for the
+   *                    application attribute name.
+   *
+   * @return  The application attributes.
+   */
+   ApplicationAttributeSequence getAttributes(
+      in Pattern aaPattern)
+      raises (AoException);
+
+   /** (5008)
+   * Get the base element of an application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The base element.
+   */
+   BaseElement getBaseElement()
+      raises (AoException);
+
+   /** (5009)
+   * Get the Id of an application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The Id of the application element.
+   */
+   T_LONGLONG getId()
+      raises (AoException);
+
+   /** (5010)
+   * Get the instance element specified by the given Id. If the Id of the
+   * instance is not unique an exception is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieId  The instance element Id.
+   *
+   * @return  The instance element.
+   */
+   InstanceElement getInstanceById(
+      in T_LONGLONG ieId)
+      raises (AoException);
+
+   /** (5011)
+   * Get the instance element specified by the given name. If the name of
+   * the instance is not unique an exception is thrown.
+   * 
+   * This is a convenience method for instance elements with unique
+   * names. If there are duplicate names for instance use the method
+   * getInstances instead and specify the requested name as pattern
+   * parameter.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_NAME
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieName  The instance element name.
+   *
+   * @return  The instance element.
+   */
+   InstanceElement getInstanceByName(
+      in Name ieName)
+      raises (AoException);
+
+   /** (5012)
+   * Get the instances whose names match the pattern. The pattern is case
+   * sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  iePattern  The name or the search pattern for the instance
+   *                    element name.
+   *
+   * @return  The instance elements.
+   */
+   InstanceElementIterator getInstances(
+      in Pattern iePattern)
+      raises (AoException);
+
+   /** (5013)
+   * Get the name of an application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the application element.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (5014)
+   * Get related application elements connected via the specified
+   * relationship.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeRelationship  The requested relationship.
+   *
+   * @return  The related application elements.
+   */
+   ApplicationElementSequence getRelatedElementsByRelationship(
+      in Relationship aeRelationship)
+      raises (AoException);
+
+   /** (5015)
+   * Get application relations of the requested type connected from this
+   * application element. The inverse relations are not returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION_TYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeRelationType  The requested relation type.
+   *
+   * @return  The application relations.
+   */
+   ApplicationRelationSequence getRelationsByType(
+      in RelationType aeRelationType)
+      raises (AoException);
+
+   /** (5016)
+   * Get the names of all related application elements.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The names of the related application elements.
+   */
+   NameSequence listAllRelatedElements()
+      raises (AoException);
+
+   /** (5017)
+   * Get the application attribute names of the application element.
+   * There are no attribute names returned in the result list that
+   * contain a reference to another application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaPattern  The name or the search pattern for the
+   *                    application attribute name.
+   *
+   * @return  The names of the application attributes.
+   */
+   NameSequence listAttributes(
+      in Pattern aaPattern)
+      raises (AoException);
+
+   /** (5018)
+   * Get the names of the instances whose names match the pattern. The
+   * pattern is case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aaPattern  The name or the search pattern for the
+   *                    application attribute name.
+   *
+   * @return  The names of the instances.
+   */
+   NameIterator listInstances(
+      in Pattern aaPattern)
+      raises (AoException);
+
+   /** (5019)
+   * Get the names of related application elements connected via the
+   * specified relationship.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeRelationship  The requested relationship.
+   *
+   * @return  The names of the related application elements.
+   */
+   NameSequence listRelatedElementsByRelationship(
+      in Relationship aeRelationship)
+      raises (AoException);
+
+   /** (5020)
+   * Remove an application attribute from an application element. If
+   * there are instances of the application element the attribute of the
+   * existing instances change from application to instance attributes.
+   * 
+   * 
+   * It is allowed to modify the application element outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applAttr  The application attribute to remove.
+   */
+   void removeAttribute(
+      in ApplicationAttribute applAttr)
+      raises (AoException);
+
+   /** (5021)
+   * Remove an instance from the application element. 
+   * 
+   * It is allowed to remove an instance outside a transaction but it is
+   * recommended to activate a transaction.
+   * 
+   * The instance is removed from the server when the transaction is
+   * committed. If the recursive flag is set all children of the instance
+   * are also deleted. Removing instances is allowed only if there are no
+   * references(relations) to this instance. If the recursive flag is set
+   * a reference to one of the children is not allowed and will cause an
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_REFERENCES
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  ieId  The instance Id.
+   *
+   * @param  recursive  The recursive flag.
+   */
+   void removeInstance(
+      in T_LONGLONG ieId,
+      in T_BOOLEAN recursive)
+      raises (AoException);
+
+   /** (5022)
+   * Set the base element of the application element. 
+   * 
+   * It is allowed to modify the application element outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The assignment to the current base element is overwritten. If there
+   * are instances of the application element or references to the
+   * application element an exception is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_INSTANCES
+   *    AO_HAS_REFERENCES
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  baseElem  The base element.
+   */
+   void setBaseElement(
+      in BaseElement baseElem)
+      raises (AoException);
+
+   /** (5023)
+   * Set the name of the application element.
+   *  
+   * It is allowed to modify the application element outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The name of the application element must be unique.
+   * 
+   * The name of an application element must not exceed the maximum name
+   * length of the underlying physical storage. Current server
+   * implementations restrict it to 30 characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_NAME
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  aeName  The application element name.
+   */
+   void setName(
+      in Name aeName)
+      raises (AoException);
+
+   /** (5024)
+   * The given user group the rights should be set for. <rights> defines
+   * the rights to set or to clear. If the parameter <set> is set to
+   * 'set', the rights in <rights> are set all others are cleared. If the
+   * parameter <set> is set to 'add', the rights in <rights> are added to
+   * the existing rights. If the parameter <set> is set to 'remove', the
+   * rights in <rights> are removed from the existing rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  usergroup  The user group for which the rights will be
+   *                    modified.
+   *
+   * @param  rights  The new right for the user group. The rights
+   *                 constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setRights(
+      in InstanceElement usergroup,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (5025)
+   * Retrieve access control list information of the given object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The access control list entries of the given application
+   *          element.
+   */
+   ACLSequence getRights()
+      raises (AoException);
+
+   /** (5026)
+   * Retrieve access control list information for the initial rights of
+   * the given object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The access control list entries with the initial rights of
+   *          the given application element.
+   */
+   InitialRightSequence getInitialRights()
+      raises (AoException);
+
+   /** (5027)
+   * The given user group the initial rights should be set for. <rights>
+   * defines the rights to set or to clear. If the parameter <set> is set
+   * to 'set', the rights in <rights> are set all others are cleared. If
+   * the parameter <set> is set to 'add', the rights in <rights> are
+   * added to the existing rights. If the parameter <set> is set to
+   * 'remove', the rights in <rights> are removed from the existing
+   * rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  usergroup  The user group for which the initial rights will
+   *                    be modified.
+   *
+   * @param  rights  The new initial rights for the user group. The
+   *                 rights constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  refAid  The Id of referencing application element for which
+   *                 the initial rights will be used. If no refAid is set
+   *                 the initial rights will be used for each new
+   *                 instance element independent of the application
+   *                 element.
+   *
+   * @param  set  What to do with the new initial rights.
+   */
+   void setInitialRights(
+      in InstanceElement usergroup,
+      in T_LONG rights,
+      in T_LONGLONG refAid,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (5028)
+   * Set for the given application element, which relation will be used
+   * to determine the initial rights for the new created instances.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applRel  The application relation which will be used to
+   *                  determine the initial rights. The relation range of
+   *                  the application relation must be [1:1] otherwise
+   *                  the server can not find an unique instance element
+   *                  to retrieve the initial rights.
+   *
+   * @param  set  Set or remove the relation for the initial rights. If
+   *              this parameter is true the relation will be set
+   *              otherwise removed.
+   */
+   void setInitialRightRelation(
+      in ApplicationRelation applRel,
+      in T_BOOLEAN set)
+      raises (AoException);
+
+   /** (5029)
+   * Get all relations which are used to retrieve the instances to create
+   * the initial rights of the new created instance element. If there are
+   * more then one application relation the initial rights of each
+   * related instance are 'ored' to the list of the initial rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The sequence with the application relations which will be
+   *          used to create the initial rights of the new created
+   *          instance element.
+   */
+   ApplicationRelationSequence getInitialRightRelations()
+      raises (AoException);
+
+   /** (5030)
+   * Get the security level of the application element. The security
+   * level tells if there is a security check for both application
+   * element and instance elements or only for the application
+   * attributes, the instance elements or none at all.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The current security level. The security level constants
+   *          are defined in the interface SecurityLevel. The interface
+   *          definition language IDL does not allow to set the values of
+   *          enumerations thus the constant definitions had to be done
+   *          in an interface.
+   */
+   T_LONG getSecurityLevel()
+      raises (AoException);
+
+   /** (5031)
+   * Set the security level for the given application element. If the
+   * security level is added the client is responsible for the access
+   * control list entries of the existing objects.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  secLevel  The new security level. The security level
+   *                   constants are defined in the interface
+   *                   SecurityLevel. The interface definition language
+   *                   IDL does not allow to set the values of
+   *                   enumerations thus the constant definitions had to
+   *                   be done in an interface.
+   *
+   * @param  set  What to do with the new security level.
+   */
+   void setSecurityLevel(
+      in T_LONG secLevel,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (5032)
+   * Get the application model to which the application element belongs
+   * by returning an object with the interface ApplicationStructure. The
+   * application model provided is the same as that provided from the
+   * method getApplicationStructure of the Interface AoSession. This
+   * method guarantees that the client software is able to return to the
+   * session in case the session object is not available.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application structure to which the application element
+   *          belongs.
+   */
+   ApplicationStructure getApplicationStructure()
+      raises (AoException);
+
+   /** (5033)
+   * Create a list with instances. The attribute are given with the name
+   * of the sequence. The values of the attributes are given in the value
+   * sequence. The index in the different value sequences match for one
+   * instance element. The index in the instance element sequence of the
+   * related instances match for the instance with the same index in the
+   * value sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_INVALID_REQUEST
+   *
+   * @param  attributes  The attributes of the new created instances.
+   *
+   * @param  relatedInstances  The list with related instances for
+   *                           different application relations.
+   *
+   * @return  The list with the new created instances.
+   */
+   InstanceElementSequence createInstances(
+      in NameValueSeqUnitSequence attributes,
+      in ApplicationRelationInstanceElementSeqSequence relatedInstances)
+      raises (AoException);
+
+   /** (5034)
+   * Return the basic application relations derived from the base
+   * relation with the given relation name.
+   * Take care at most elements only one application relation can be
+   * derived from a base relation, there are some well defined
+   * exceptions, so the method can return more then one application
+   * relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baseRelName  The name of the base relation.
+   *
+   * @return  The application relation sequence, if no relation is found
+   *          an empty sequence is returned.
+   */
+   ApplicationRelationSequence getRelationsByBaseName(
+      in Name baseRelName)
+      raises (AoException);
+
+}; // Interface ApplicationElement.
+
+/**
+* The ASAM ODS application relation interface.
+* 
+* A relation is the connection between two ASAM ODS elements; it may be
+* navigated in both
+* directions. The get- and set- methods are defined from the first
+* element, the getInverse- and
+* setInverse- methods work from the second element.
+*/
+interface ApplicationRelation {
+
+   /** (6001)
+   * Get the base relation of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The base relation of the application relation. A 'null' is
+   *          returned if the application relation has no base relation.
+   */
+   BaseRelation getBaseRelation()
+      raises (AoException);
+
+   /** (6002)
+   * Get the first application element of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The first application element of the application relation.
+   */
+   ApplicationElement getElem1()
+      raises (AoException);
+
+   /** (6003)
+   * Get the second application element of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The second application element of the application relation.
+   */
+   ApplicationElement getElem2()
+      raises (AoException);
+
+   /** (6004)
+   * Get the inverse relation range of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The inverse relation range of the application relation.
+   */
+   RelationRange getInverseRelationRange()
+      raises (AoException);
+
+   /** (6005)
+   * Get the inverse relationship of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The inverse relationship of the application relation.
+   */
+   Relationship getInverseRelationship()
+      raises (AoException);
+
+   /** (6006)
+   * Get the name of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the application relation.
+   */
+   Name getRelationName()
+      raises (AoException);
+
+   /** (6007)
+   * Get the relation range of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relation range of the application relation.
+   */
+   RelationRange getRelationRange()
+      raises (AoException);
+
+   /** (6008)
+   * Get the relationship of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relationship of the application relation.
+   */
+   Relationship getRelationship()
+      raises (AoException);
+
+   /** (6009)
+   * Get the relation type of the application relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relation type of the application relation.
+   */
+   RelationType getRelationType()
+      raises (AoException);
+
+   /** (6010)
+   * Set the base relation of the application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The relation type and relation range is copied from the base
+   * relation. The previous values get lost.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  baseRel  The base relation.
+   */
+   void setBaseRelation(
+      in BaseRelation baseRel)
+      raises (AoException);
+
+   /** (6011)
+   * Set the first application element of the application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ELEMENT
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applElem  The application element.
+   */
+   void setElem1(
+      in ApplicationElement applElem)
+      raises (AoException);
+
+   /** (6012)
+   * Set the second application element of the application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ELEMENT
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applElem  The application element.
+   */
+   void setElem2(
+      in ApplicationElement applElem)
+      raises (AoException);
+
+   /** (6013)
+   * Set the relation range of an application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * It is only allowed to set the relation type if no base relation is
+   * defined.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_RELATION
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION_RANGE
+   *    AO_IS_BASE_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  arRelationRange  The inverse relation range.
+   */
+   void setInverseRelationRange(
+      in RelationRange arRelationRange)
+      raises (AoException);
+
+   /** (6014)
+   * Set the name of an application relation.
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The name of an application attribute must not exceed the maximum
+   * name length of the underlying physical storage. Current server
+   * typically implementations restrict it to 30 characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  arName  The application relation name.
+   */
+   void setRelationName(
+      in Name arName)
+      raises (AoException);
+
+   /** (6015)
+   * Set the relation range of an application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * It is only allowed to set the relation type if no base relation is
+   * defined.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_RELATION
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION_RANGE
+   *    AO_IS_BASE_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  arRelationRange  The relation range.
+   */
+   void setRelationRange(
+      in RelationRange arRelationRange)
+      raises (AoException);
+
+   /** (6016)
+   * Set the relation type of an application relation. 
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The relationship is automatically set when the relation type is set.
+   * It is only allowed to set the relation type if no base relation is
+   * defined.
+   * 
+   * It is only allowed to modify a relation type when no base relation
+   * is given, otherwise the exception AO_HAS_BASE_RELATION is thrown.
+   * 
+   * It is not allowed to set the relation type FATHER_CHILD, these
+   * relation type is reserved for the base model. The two relation types
+   * which can be set are  INFO or INHERITANCE. 
+   * 
+   * The relationship is set automatic when the relation type is set, the
+   * maximum of the relation range determines the relationship between
+   * the elements of the relation.
+   * 
+   * R.Type      | max R.Range | max inv. R.Range | Relationship         
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INFO        | 1           | 1                | exception,
+   * AO_INVALID_RELATION_TYPE 
+   * ------------+-------------+------------------+-------------         
+   *        
+   * INFO        | 1           | MANY             | INFO_TO              
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INFO        | MANY        | 1                | INFO_FROM            
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INFO        | MANY        | MANY             | INFO                 
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INHERITANCE | 1           | 1                | exception,
+   * AO_INVALID_RELATION_TYPE 
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INHERITANCE | 1           | MANY             | SUPERTYPE            
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INHERITANCE | MANY        | 1                | SUBTYPE              
+   *               
+   * ------------+-------------+------------------+-------------         
+   *              
+   * INHERITANCE | MANY        | MANY             | exception,
+   * AO_INVALID_RELATION_TYPE
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_BASE_RELATION
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION_TYPE
+   *    AO_IS_BASE_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  arRelationType  The relation type.
+   */
+   void setRelationType(
+      in RelationType arRelationType)
+      raises (AoException);
+
+   /** (6017)
+   * Get the inverse name of the application relation. The inverse name
+   * of an application relation is the name of the relation seen from the
+   * other application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The inverse name of the application relation.
+   */
+   Name getInverseRelationName()
+      raises (AoException);
+
+   /** (6018)
+   * Set the name of an application relation.
+   * 
+   * It is allowed to modify the application relation outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  arInvName  The inverse application relation name.
+   */
+   void setInverseRelationName(
+      in Name arInvName)
+      raises (AoException);
+
+}; // Interface ApplicationRelation.
+
+/**
+* The ASAM ODS application structure interface.
+*/
+interface ApplicationStructure {
+
+   /** (7001)
+   * Check the application model for ASAM ODS conformity. The first error
+   * found is reported by an exception. The following checks are
+   * performed:
+   * 
+   *  - Each application element must be derived from a valid base
+   * element.
+   *  - An application attribute is derived from one base attribute. It
+   * is not allowed to derive more the one application attribute from the
+   * same base attribute. It is allowed that application attributes are
+   * not derived from any base attribute.
+   *  - All application elements must have at least the mandatory
+   * attributes.
+   *  - Each application elements must be identified by a unique Asam
+   * path. No "floating" application elements are allowed.
+   *  - All relations required by the base model must be present.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_BASE_ATTRIBUTE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION
+   *    AO_MISSING_ATTRIBUTE
+   *    AO_MISSING_RELATION
+   *    AO_MISSING_APPLICATION_ELEMENT
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_PATH_TO_ELEMENT
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void check()
+      raises (AoException);
+
+   /** (7002)
+   * Create a new application element in the application model. 
+   * 
+   * It is allowed to modify the application model outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   * The information whether or not the new application element is a top
+   * level element is taken from the specified base element. The Id of
+   * the application element is set automatically. The mandatory base
+   * attributes are created automatically. Optional attributes have to be
+   * created by the calling program. The application attribute interface
+   * methods may be used to modify the attributes.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  baseElem  The base element from which the application
+   *                   element is derived.
+   *
+   * @return  The new application element.
+   */
+   ApplicationElement createElement(
+      in BaseElement baseElem)
+      raises (AoException);
+
+   /** (7003)
+   * Create a new relation. 
+   * 
+   * It is allowed to modify the application model outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   * The relation is part of the application model. The application
+   * relation interface methods may be used to modify the relation.
+   * 
+   * The default properties of a new application relation are:
+   *    BaseRelation   NULL
+   *    Element1       NULL
+   *    Element2       NULL
+   *    Range          -2, -2
+   *    Name           NULL
+   *    Type           INFO
+   * When element 1 or element 2 is set before the name of the relation
+   * is specified, the name of the application relation is set to
+   * "AUTOGEN".
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @return  The new application relation.
+   */
+   ApplicationRelation createRelation()
+      raises (AoException);
+
+   /** (7004)
+   * Get the application element with the requested Id.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeId  The Id of the requested application element.
+   *
+   * @return  The requested application element.
+   */
+   ApplicationElement getElementById(
+      in T_LONGLONG aeId)
+      raises (AoException);
+
+   /** (7005)
+   * Get the application element with the requested name.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeName  The name of the requested application element.
+   *
+   * @return  The requested application element.
+   */
+   ApplicationElement getElementByName(
+      in Name aeName)
+      raises (AoException);
+
+   /** (7006)
+   * Get the application elements whose names match the pattern. The
+   * pattern is case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aePattern  The name or the search pattern for the requested
+   *                    application elements.
+   *
+   * @return  The requested application elements.
+   */
+   ApplicationElementSequence getElements(
+      in Pattern aePattern)
+      raises (AoException);
+
+   /** (7007)
+   * Get the names of application elements that are derived from the
+   * specified base element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BASETYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeType  The requested base element type. The base element
+   *                 type can be a pattern.
+   *
+   * @return  The requested application element names.
+   */
+   ApplicationElementSequence getElementsByBaseType(
+      in BaseType aeType)
+      raises (AoException);
+
+   /** (7008)
+   * Get the instance element specified by the ASAM path.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ASAM_PATH
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  asamPath  The ASAM path of the requested instance element.
+   *
+   * @return  The requested instance element.
+   */
+   InstanceElement getInstanceByAsamPath(
+      in Name asamPath)
+      raises (AoException);
+
+   /** (7009)
+   * Returns the relations between two application elements.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  applElem1  The first application element.
+   *
+   * @param  applElem2  The second application element.
+   *
+   * @return  The relations between the specified application elements.
+   */
+   ApplicationRelationSequence getRelations(
+      in ApplicationElement applElem1,
+      in ApplicationElement applElem2)
+      raises (AoException);
+
+   /** (7010)
+   * Get the top level application elements which are inherited from the
+   * base element that matches the base type. If the given base type is
+   * no top level base element an exception is thrown. A top level
+   * application element is an application element without a father.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BASETYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeType  The requested base type. The base element type can
+   *                 be a pattern.
+   *
+   * @return  The top level application elements.
+   */
+   ApplicationElementSequence getTopLevelElements(
+      in BaseType aeType)
+      raises (AoException);
+
+   /** (7011)
+   * Get the names of the application elements that  match the pattern.
+   * The pattern is case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aePattern  The name or the search pattern for the requested
+   *                    base elements.
+   *
+   * @return  The names of the application elements.
+   */
+   NameSequence listElements(
+      in Pattern aePattern)
+      raises (AoException);
+
+   /** (7012)
+   * Get the names of application elements that are  derived from the
+   * given base type.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BASETYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeType  The requested base type. The base element type can
+   *                 be a pattern.
+   *
+   * @return  The names of the application elements.
+   */
+   NameSequence listElementsByBaseType(
+      in BaseType aeType)
+      raises (AoException);
+
+   /** (7013)
+   * Get the names of the top level application elements that are derived
+   * from the given base type. If the given base type is not a top level
+   * base element an exception is thrown. A top level application element
+   * is an application element without a father.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BASETYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aeType  The requested base type.
+   *
+   * @return  The names of the application elements.
+   */
+   NameSequence listTopLevelElements(
+      in BaseType aeType)
+      raises (AoException);
+
+   /** (7014)
+   * Remove an application element from the application model. 
+   * 
+   * It is allowed to modify the application model outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   *   - Only allowed:
+   *       - if the application element is empty
+   *         (has no instances).
+   *       - no relations with other application elements.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_INSTANCES
+   *    AO_HAS_REFERENCES
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applElem  The application element to be removed.
+   */
+   void removeElement(
+      in ApplicationElement applElem)
+      raises (AoException);
+
+   /** (7015)
+   * This method removes an application relation from the model. 
+   * 
+   * It is allowed to modify the application model outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   * The elements of the relation are still part of the application
+   * model. If there are instances of the relation they are also removed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_HAS_INSTANCES
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  applRel  The application relation to be removed.
+   */
+   void removeRelation(
+      in ApplicationRelation applRel)
+      raises (AoException);
+
+   /** (7016)
+   * Get the instance elements specified by the element id.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ASAM_PATH
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieIds  The sequence with the element id.
+   *
+   * @return  The requested instance element sequence.
+   */
+   InstanceElementSequence getInstancesById(
+      in ElemIdSequence ieIds)
+      raises (AoException);
+
+   /** (7017)
+   * Get the current client session in which the application model is
+   * created.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The current client session.
+   */
+   AoSession getSession()
+      raises (AoException);
+
+   /** (7018)
+   * Create a new enumeration definition. This method modifies the
+   * application model and is only allowed for the super user.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *
+   * @param  enumName  Name of the enumeration
+   *
+   * @return  The new created enumeration
+   */
+   EnumerationDefinition createEnumerationDefinition(
+      in T_STRING enumName)
+      raises (AoException);
+
+   /** (7019)
+   * Remove the enumeration definition. The server checks if the
+   * enumeration is still in use by one of the attributes. This method
+   * modifies the application model and is only allowed for the super
+   * user.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *
+   * @param  enumName  Name of the enumeration to remove.
+   */
+   void removeEnumerationDefinition(
+      in T_STRING enumName)
+      raises (AoException);
+
+   /** (7020)
+   * Get the list of all enumeration names.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  List with all enumeration names.
+   */
+   NameSequence listEnumerations()
+      raises (AoException);
+
+   /** (7021)
+   * Get the specified enumeration definition.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  enumName  Name of the requested enumeration.
+   *
+   * @return  The enumeration definition.
+   */
+   EnumerationDefinition getEnumerationDefinition(
+      in T_STRING enumName)
+      raises (AoException);
+
+   /** (7022)
+   * Create the relation between a list of instances. The number of
+   * instances in both list must be identical. The application element of
+   * the instances in each list must be identical. The application
+   * elements must match the application elements of the application
+   * relation. The index in the list of the instances defines related
+   * instances.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_INVALID_REQUEST
+   *
+   * @param  applRel  The application relation.
+   *
+   * @param  elemList1  The list with the instances of one application
+   *                    element for which the relation will be created.
+   *
+   * @param  elemList2  The list with the related instances.
+   */
+   void createInstanceRelations(
+      in ApplicationRelation applRel,
+      in InstanceElementSequence elemList1,
+      in InstanceElementSequence elemList2)
+      raises (AoException);
+
+}; // Interface ApplicationStructure.
+
+/**
+* The ASAM ODS base attribute interface.
+*/
+interface BaseAttribute {
+
+   /** (8001)
+   * Get the data type of the base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The data type of the base attribute.
+   */
+   DataType getDataType()
+      raises (AoException);
+
+   /** (8002)
+   * Get the name of the base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the base attribute.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (8003)
+   * Get the obligatory flag of the base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The obligatory flag of the base attribute.
+   */
+   T_BOOLEAN isObligatory()
+      raises (AoException);
+
+   /** (8004)
+   * Get the unique flag of the base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The unique flag of the base attribute.
+   */
+   T_BOOLEAN isUnique()
+      raises (AoException);
+
+   /** (8005)
+   * Return the base element to which the attribute belongs..
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The base element of the attribute.
+   */
+   BaseElement getBaseElement()
+      raises (AoException);
+
+   /** (8006)
+   * Get the definition of the enumeration of the base attribute.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_DATATYPE
+   *
+   * @return  The ASAM ODS enumeration.
+   */
+   EnumerationDefinition getEnumerationDefinition()
+      raises (AoException);
+
+}; // Interface BaseAttribute.
+
+/**
+* The ASAM ODS base element interface.
+*/
+interface BaseElement {
+
+   /** (9001)
+   * Get all known relations of the base element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  All known relations of the base element.
+   */
+   BaseRelationSequence getAllRelations()
+      raises (AoException);
+
+   /** (9002)
+   * Get attributes of the base element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baPattern  The name or the search pattern for the requested
+   *                    base attributes.
+   *
+   * @return  The requested attributes of the base element.
+   */
+   BaseAttributeSequence getAttributes(
+      in Pattern baPattern)
+      raises (AoException);
+
+   /** (9003)
+   * Get the related elements of a base element defined by the
+   * relationship.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  brRelationship  The requested relationship.
+   *
+   * @return  The related elements of a base element.
+   */
+   BaseElementSequence getRelatedElementsByRelationship(
+      in Relationship brRelationship)
+      raises (AoException);
+
+   /** (9004)
+   * Get the base element's relations of the requested relation type.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION_TYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  brRelationType  The requested relation type.
+   *
+   * @return  The base element's relations of the requested type.
+   */
+   BaseRelationSequence getRelationsByType(
+      in RelationType brRelationType)
+      raises (AoException);
+
+   /** (9005)
+   * Get the type of the base element. The type of the base element is
+   * identical with the name of the base element. The type of the base
+   * element is a string.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The type of the base element.
+   */
+   BaseType getType()
+      raises (AoException);
+
+   /** (9006)
+   * Get whether or not the base element is a top level element. Top
+   * level elements are elements without a father.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Boolean whether or not the base element is a top level
+   *          element.
+   */
+   T_BOOLEAN isTopLevel()
+      raises (AoException);
+
+   /** (9007)
+   * Get attribute names of the base element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baPattern  The name or the search pattern for the requested
+   *                    base attribute names.
+   *
+   * @return  The requested attribute names of the base element.
+   */
+   NameSequence listAttributes(
+      in Pattern baPattern)
+      raises (AoException);
+
+   /** (9008)
+   * Get the related element names of the base element defined by the
+   * relationship.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  brRelationship  The requested relationship.
+   *
+   * @return  The related element names of the base element.
+   */
+   BaseTypeSequence listRelatedElementsByRelationship(
+      in Relationship brRelationship)
+      raises (AoException);
+
+}; // Interface BaseElement.
+
+/**
+* The ASAM ODS base relation interface.
+*/
+interface BaseRelation {
+
+   /** (10001)
+   * Get the first base element of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The first base element of the base relation.
+   */
+   BaseElement getElem1()
+      raises (AoException);
+
+   /** (10002)
+   * Get the second base element of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The second base element of the base relation.
+   */
+   BaseElement getElem2()
+      raises (AoException);
+
+   /** (10003)
+   * Get the inverse relation range of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The inverse relation range of the base relation.
+   */
+   RelationRange getInverseRelationRange()
+      raises (AoException);
+
+   /** (10004)
+   * Get the inverse relationship of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The inverse relationship of the base relation.
+   */
+   Relationship getInverseRelationship()
+      raises (AoException);
+
+   /** (10005)
+   * Get the relation name of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relation name of the base relation.
+   */
+   Name getRelationName()
+      raises (AoException);
+
+   /** (10006)
+   * Get the relation range of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relation range of the base relation.
+   */
+   RelationRange getRelationRange()
+      raises (AoException);
+
+   /** (10007)
+   * Get the relationship of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relationship of the base relation.
+   */
+   Relationship getRelationship()
+      raises (AoException);
+
+   /** (10008)
+   * Get the relation type of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The relation type of the base relation.
+   */
+   RelationType getRelationType()
+      raises (AoException);
+
+   /** (10009)
+   * Return the inverse name of the base relation.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the inverse relation.
+   */
+   Name getInverseRelationName()
+      raises (AoException);
+
+}; // Interface BaseRelation.
+
+/**
+* The ASAM ODS base structure interface.
+*/
+interface BaseStructure {
+
+   /** (11001)
+   * Get the base element that matches the requested type. The type of a
+   * base element is identical with the name of the base element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BASETYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  beType  The name of the requested base element.
+   *
+   * @return  The requested base element.
+   */
+   BaseElement getElementByType(
+      in BaseType beType)
+      raises (AoException);
+
+   /** (11002)
+   * Get the base elements that match the pattern. The pattern is case
+   * sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  bePattern  The name or the search pattern for the requested
+   *                    base elements.
+   *
+   * @return  The requested base elements.
+   */
+   BaseElementSequence getElements(
+      in Pattern bePattern)
+      raises (AoException);
+
+   /** (11003)
+   * Get the base relation between two base elements. The base relation
+   * is given from the first element (parameter elem1) to the second
+   * element (parameter elem2), the inverse relation is not given.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @param  elem1  The base element from which the relation starts.
+   *
+   * @param  elem2  The base element to which the relation points.
+   *
+   * @return  The base relation between the two base elements.
+   */
+   BaseRelation getRelation(
+      in BaseElement elem1,
+      in BaseElement elem2)
+      raises (AoException);
+
+   /** (11004)
+   * Get the top level base elements that match the pattern. The pattern
+   * is case sensitive and may contain wildcard characters. A top level
+   * base element is a base element without a father.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  bePattern  The name or the search pattern for the requested
+   *                    top level base elements.
+   *
+   * @return  The requested top level base elements.
+   */
+   BaseElementSequence getTopLevelElements(
+      in Pattern bePattern)
+      raises (AoException);
+
+   /** (11005)
+   * Get the version of the base model. The version of the base model is
+   * the version of the ASAM ODS base model.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The version of the ASAM ODS base model.
+   */
+   T_STRING getVersion()
+      raises (AoException);
+
+   /** (11006)
+   * Get the base element names that match the pattern. The pattern is
+   * case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  bePattern  The name or the search pattern for the requested
+   *                    base element names.
+   *
+   * @return  The requested base element names.
+   */
+   BaseTypeSequence listElements(
+      in Pattern bePattern)
+      raises (AoException);
+
+   /** (11007)
+   * Get the top level base element names that match the pattern. The
+   * pattern is case sensitive and may contain wildcard characters. A top
+   * level base element is a base element without a father.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  bePattern  The name or the search pattern for the requested
+   *                    top level base element names.
+   *
+   * @return  The requested top level base element names.
+   */
+   BaseTypeSequence listTopLevelElements(
+      in Pattern bePattern)
+      raises (AoException);
+
+   /** (11008)
+   * Get the base relations between two base elements. The base relation
+   * is given from the first element (parameter elem1) to the second
+   * element (parameter elem2), the inverse relation is not given.
+   * When there are no base relation between the two elements the server
+   * will throw the exception AO_NOT_FOUND
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @param  elem1  The base element from which the relation starts.
+   *
+   * @param  elem2  The base element to which the relation points.
+   *
+   * @return  The list with base relations between the two elements.
+   */
+   BaseRelationSequence getRelations(
+      in BaseElement elem1,
+      in BaseElement elem2)
+      raises (AoException);
+
+}; // Interface BaseStructure.
+
+/**
+* The ASAM ODS blob interface.
+*/
+interface Blob {
+
+   /** (12001)
+   * Append a byte sequence to the binary large object. 
+   * 
+   * It is allowed to modify the binary large object outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  value  The byte sequence.
+   */
+   void append(
+      in S_BYTE value)
+      raises (AoException);
+
+   /** (12002)
+   * Compares the content of the binary large object. The headers are not
+   * compared.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aBlob  The blob to compare.
+   *
+   * @return  A flag whether or not the compared blobs are equal.
+   */
+   T_BOOLEAN compare(
+      in T_BLOB aBlob)
+      raises (AoException);
+
+   /** (12003)
+   * Get a part of the binary large object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  offset  The starting position of the data in the blob.
+   *
+   * @param  length  The number of bytes requested from the blob.
+   *
+   * @return  The request part of the blob data.
+   */
+   S_BYTE get(
+      in T_LONG offset,
+      in T_LONG length)
+      raises (AoException);
+
+   /** (12004)
+   * Get the header of the binary large object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The blob header.
+   */
+   T_STRING getHeader()
+      raises (AoException);
+
+   /** (12005)
+   * Get the length of the binary large object without loading it.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The blob length.
+   */
+   T_LONG getLength()
+      raises (AoException);
+
+   /** (12006)
+   * Clear the binary large object and set the new data. 
+   * 
+   * It is allowed to modify the binary large object outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  value  The new blob data.
+   */
+   void set(
+      in S_BYTE value)
+      raises (AoException);
+
+   /** (12007)
+   * Set the header of a binary large object. 
+   * 
+   * It is allowed to modify the binary large object outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  header  The blob header.
+   */
+   void setHeader(
+      in T_STRING header)
+      raises (AoException);
+
+   /** (12008)
+   * Destroy the object on the server. The destructor of the client, so
+   * the server knows this object is not used anymore by the client.
+   * Access to this object after the destroy method will lead to an
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+}; // Interface Blob.
+
+/**
+* The ASAM ODS column interface. It is not inherited from
+* InstanceElement. Via the method getColumn of the interface SubMatrix
+* the column is accessed. The column is only used for read access. With
+* the creation of instances at the application element of type
+* AoLocalColumn and the relation to the instances of the application
+* element of type AoSubMatrix a local column can be created. The column
+* name is used for the SMatLink and the column is used to store a formula
+* for the calculation of the values of the column. There is no definition
+* of the formula language at the moment.
+*/
+interface Column {
+
+   /** (13001)
+   * Get the formula of the column.
+   * 
+   * There is no formula defined in ASAM ODS, so there is nothing to
+   * return.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The formula of the column.
+   */
+   T_STRING getFormula()
+      raises (AoException);
+
+   /** (13002)
+   * Get the name of the column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the column.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (13003)
+   * Get the source measurement quantity.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The source measurement quantity.
+   */
+   InstanceElement getSourceMQ()
+      raises (AoException);
+
+   /** (13004)
+   * Get the unit of the column.
+   * 
+   * The method returns the unit of the values according the current
+   * setting. Initially within a session this is the unit as given in the
+   * storage. After setUnit() is called, the unit as specified by
+   * setUnit() will be
+   * returned for the particular column. Thus the unit returned will be
+   * retrieved by the ODS server according to following strategy:
+   * 1) if a unit has already been set for the paricular column by
+   * setUnit(..) prior; that unit is returned, else
+   * 2) if the related measurement quantity has a unit (i.e. it has a
+   * relation derived from the base relation 'unit' referencing an
+   * instance of base type AoUnit), that unit's name is returned, else
+   * 3) if the related measurement quantity has a relation to a quantity
+   * (i.e. its relation derived from the base relation 'quantity' is
+   * referencing an instance of base type AoQuantity), and this quantity
+   * has
+   * a default unit (i.e. it has a relation derived from the base
+   * relation 'default_unit' referencing an instance of base type
+   * AoUnit), that unit's name is returned, else
+   * 4) an empty string is returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The unit of the column.
+   */
+   T_STRING getUnit()
+      raises (AoException);
+
+   /** (13005)
+   * Set the formula of the column. 
+   * 
+   * It is allowed to modify the column outside a transaction but it is
+   * recommended to activate a transaction.
+   * 
+   * There is no formula in ASAM ODS so don't try to set the formula.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  formula  The formula.
+   */
+   void setFormula(
+      in T_STRING formula)
+      raises (AoException);
+
+   /** (13006)
+   * Set the unit of the column. This is only a temporary unit for
+   * getting the values of a column. This unit is not stored in the
+   * storage. 
+   * When an empty string is given the unit is returned to the original
+   * setting.
+   * When the value matrix where the column belongs to is in the STORAGE
+   * mode this method have no influence on the values returned from the
+   * value matrix.
+   * To change the unit permanent in the storage the relation at the
+   * measurement quantity must be changed by the client.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  unit  The physical unit.
+   */
+   void setUnit(
+      in T_STRING unit)
+      raises (AoException);
+
+   /** (13007)
+   * Is the column an independent column
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The independent flag of the column.
+   */
+   T_BOOLEAN isIndependent()
+      raises (AoException);
+
+   /** (13008)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Is the column an scaling column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Tells if the column is a scaling column.
+   */
+   T_BOOLEAN isScaling()
+      raises (AoException);
+
+   /** (13009)
+   * Set the column as an independent column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  independent  The new value of the independent flag.
+   */
+   void setIndependent(
+      in T_BOOLEAN independent)
+      raises (AoException);
+
+   /** (13010)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Set the column to a scaling column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  scaling  The new value of the scaling flag.
+   */
+   void setScaling(
+      in T_BOOLEAN scaling)
+      raises (AoException);
+
+   /** (13011)
+   * Get the data type of the column.
+   * The data type of the measurement quantity is always returned,
+   * independent of the mode of the values matrix where the column
+   * belongs to neither the sequence representation of the column.
+   * 
+   * This method always returns the data type of the measurement quantity
+   * to which this local column belongs, independent of 
+   * - the value matrix mode of the value matrices this local column
+   * belongs to
+   * - the sequence representation of this local column
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The data type of the column.
+   */
+   DataType getDataType()
+      raises (AoException);
+
+   /** (13012)
+   * Destroy the object on the server. The destructor of the client so
+   * the server knows this object is not used anymore by the client.
+   * Access to this object after the destroy method will lead to an
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (13013)
+   * Get the sequence representation of the column. 
+   * 
+   * When the value matrix to which the column belongs is in CALCULATED
+   * mode the sequence_representation is always explicit.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The sequence representation of the column. This is the
+   *          integer value according the enumeration seq_rep_enum of the
+   *          base model.
+   */
+   T_LONG getSequenceRepresentation()
+      raises (AoException);
+
+   /** (13014)
+   * Set the sequence representation of a new column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_PARAMETER
+   *    AO_TRANSACTION_NOT_ACTVIE
+   *
+   * @param  sequenceRepresentation  The sequence representation.  This
+   *                                 is the integer value according the
+   *                                 enumeration seq_rep_enum of the base
+   *                                 model.
+   */
+   void setSequenceRepresentation(
+      in T_LONG sequenceRepresentation)
+      raises (AoException);
+
+   /** (13015)
+   * Get the generation parameters of the Column. 
+   * 
+   * If no generation parameters exist an empty sequence is returned, its
+   * type is double, its length is 0.
+   * When the value matrix to which the column belongs is in CALCULATED
+   * mode an empty sequence is returned, its type is double, its length
+   * is 0.
+   * 
+   * The data type of the generation parameter for the implicit columns
+   * is the data type given at the measurement quantity. The data type of
+   * the generation parameters for raw data is always T_DOUBLE.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The generation parameters.
+   */
+   TS_Union getGenerationParameters()
+      raises (AoException);
+
+   /** (13016)
+   * Set the generation parameters.
+   * 
+   * The data type of the generation parameter for the implicit columns
+   * must be the data type given at the measurement quantity. The data
+   * type of the generation parameters for raw data must be always
+   * T_DOUBLE.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_PARAMETER
+   *    AO_TRANSACTION_NOT_ACTVIE
+   *
+   * @param  generationParameters  The generation parameters.
+   */
+   void setGenerationParameters(
+      in TS_Union generationParameters)
+      raises (AoException);
+
+   /** (13017)
+   * Get the data type of the raw values.
+   * 
+   * When the column has no raw values the data type of the measurement
+   * quantity is returned. 
+   * When the value matrix to which the column belongs is in CALCULATED
+   * mode the data type of the measurement quantity returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The data type of the raw values.
+   */
+   DataType getRawDataType()
+      raises (AoException);
+
+}; // Interface Column.
+
+/**
+* The ASAM ODS instance element interface. It is allowed to modify the
+* instances outside a transaction but recommended to activate a
+* transaction before the instances are modified. The modifications to
+* instances get permanent when the transaction is committed.
+*/
+interface InstanceElement {
+
+   /** (14001)
+   * Add an instance attribute to the instance. The instance attribute is
+   * built as a Name/Value/Unit tuple on the client. This method has to
+   * copy the data from the client to the server. The name of the
+   * attribute must be unique. 
+   * 
+   * It is allowed to add an instance attribute outside a transaction but
+   * it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  instAttr  The instance attribute to be added.
+   */
+   void addInstanceAttribute(
+      in NameValueUnit instAttr)
+      raises (AoException);
+
+   /** (14002)
+   * Create a relation between the current and the given instance. Check
+   * if the application elements of the relation matches the application
+   * elements of the instances. 
+   * 
+   * It is allowed to modify the instance element outside a transaction
+   * but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  relation  The application relation.
+   *
+   * @param  instElem  The instance element.
+   */
+   void createRelation(
+      in ApplicationRelation relation,
+      in InstanceElement instElem)
+      raises (AoException);
+
+   /** (14003)
+   * Get the application element of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The application element from which the instance element is
+   *          derived.
+   */
+   ApplicationElement getApplicationElement()
+      raises (AoException);
+
+   /** (14004)
+   * Get the ASAM-Path of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The ASAM path to the instance element.
+   */
+   Name getAsamPath()
+      raises (AoException);
+
+   /** (14005)
+   * Get the Id of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The Id of the instance element.
+   */
+   T_LONGLONG getId()
+      raises (AoException);
+
+   /** (14006)
+   * Get the name of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The name of the instance element.
+   */
+   Name getName()
+      raises (AoException);
+
+   /** (14007)
+   * Get the related instances. The application relation and the name of
+   * the related  instances specify the listed instances. The pattern is
+   * case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  applRel  The application relation.
+   *
+   * @param  iePattern  The name or the search pattern for the related
+   *                    instance names.
+   *
+   * @return  The related instances.
+   */
+   InstanceElementIterator getRelatedInstances(
+      in ApplicationRelation applRel,
+      in Pattern iePattern)
+      raises (AoException);
+
+   /** (14008)
+   * Get the list of related instances. The relationship and the name of
+   * the related instances specify the listed instances. The pattern is
+   * case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieRelationship  The requested relationship.
+   *
+   * @param  iePattern  The name or the search pattern for the related
+   *                    instance names.
+   *
+   * @return  The related instances.
+   */
+   InstanceElementIterator getRelatedInstancesByRelationship(
+      in Relationship ieRelationship,
+      in Pattern iePattern)
+      raises (AoException);
+
+   /** (14009)
+   * Get the attribute value (name, value and unit) of the given
+   * attribute of the instance element. This method will not return the
+   * value of relation attributes, use the method getRelatedInstances.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  attrName  The name of the requested attribute.
+   *
+   * @return  The attribute value.
+   */
+   NameValueUnit getValue(
+      in Name attrName)
+      raises (AoException);
+
+   /** (14010)
+   * Get the attribute value (value and unit) of the attribute inherited
+   * from the given base attribute of the instance element. The base name
+   * is case insensitive and may not contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  baseAttrName  The base name of the requested attribute.
+   *
+   * @return  The attribute value.
+   */
+   NameValueUnit getValueByBaseName(
+      in Name baseAttrName)
+      raises (AoException);
+
+   /** (14011)
+   * Get the attribute names from the instance element. The  attributes
+   * reserved for a relation are not listed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ATTRIBUTE_TYPE
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  iaPattern  The name or the search pattern for the attribute
+   *                    names.
+   *
+   * @param  aType  The requested attribute type.
+   *
+   * @return  The names of the attributes.
+   */
+   NameSequence listAttributes(
+      in Pattern iaPattern,
+      in AttrType aType)
+      raises (AoException);
+
+   /** (14012)
+   * Get the names of the related instances. The application relation and
+   * the name of the related instances specifies the listed names. The
+   * pattern is case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieRelation  The application relation.
+   *
+   * @param  iePattern  The name or the search pattern for the related
+   *                    instance names.
+   *
+   * @return  The names of the related instances.
+   */
+   NameIterator listRelatedInstances(
+      in ApplicationRelation ieRelation,
+      in Pattern iePattern)
+      raises (AoException);
+
+   /** (14013)
+   * Get the names of the related instances. The relationship and the
+   * name of the related instances specify the listed names. The pattern
+   * is case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATIONSHIP
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ieRelationship  The requested relationship.
+   *
+   * @param  iePattern  The name or the search pattern for the related
+   *                    instance names.
+   *
+   * @return  The names of the related instances.
+   */
+   NameIterator listRelatedInstancesByRelationship(
+      in Relationship ieRelationship,
+      in Pattern iePattern)
+      raises (AoException);
+
+   /** (14014)
+   * Remove an instance attribute.
+   * 
+   * It is allowed to remove the instance attribute outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   * The application attributes can't be removed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  attrName  The name of the attribute to be removed.
+   */
+   void removeInstanceAttribute(
+      in Name attrName)
+      raises (AoException);
+
+   /** (14015)
+   * Remove the relation between the current instance and the given
+   * instance. It is necessary to specify the instance element in case of
+   * n:m relations if not all relations shall be deleted. 
+   * 
+   * It is allowed to modify the instance element outside a transaction
+   * but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_RELATION
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  applRel  The relation to be removed.
+   *
+   * @param  instElem_nm  The instance element for specific delete from
+   *                      n:m relations.
+   */
+   void removeRelation(
+      in ApplicationRelation applRel,
+      in InstanceElement instElem_nm)
+      raises (AoException);
+
+   /** (14016)
+   * Rename the instance attribute. The application attributes can't be
+   * renamed. 
+   * 
+   * It is allowed to rename the instance attribute outside a transaction
+   * but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_NAME
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  oldName  The old instance attribute name.
+   *
+   * @param  newName  The new instance attribute name.
+   */
+   void renameInstanceAttribute(
+      in Name oldName,
+      in Name newName)
+      raises (AoException);
+
+   /** (14017)
+   * Set the name of an instance element. 
+   * 
+   * It is allowed to modify the name of the instance element outside a
+   * transaction but it is recommended to activate a transaction.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  iaName  The instance attribute name.
+   */
+   void setName(
+      in Name iaName)
+      raises (AoException);
+
+   /** (14018)
+   * Set the value of an application attribute or of an existing instance
+   * attribute, but is doesn't create a new instance attribute; for this
+   * purpose use the method addInstancesAttribute of this interface.
+   * 
+   * It is allowed to modify the attribute value outside a transaction
+   * but it is recommended to activate a transaction.
+   * 
+   * The name of the attribute is specified by the name of the
+   * NameValueUnit tuple. If the application attribute flag unique is
+   * set, the uniqueness of the new value is checked.
+   * 
+   * This method can not be used to set the value of a relation
+   * attribute, use the method createRelation of this interface .
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_VALUE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  value  The value to be set in the instance element.
+   */
+   void setValue(
+      in NameValueUnit value)
+      raises (AoException);
+
+   /** (14019)
+   * Cast an instance element to a measurement. There are some
+   * object-oriented languages which do not allow this cast.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_BASETYPE
+   *
+   * @return  The instance of type measurement.
+   */
+   Measurement upcastMeasurement()
+      raises (AoException);
+
+   /** (14020)
+   * Cast an instance element to a submatrix. There are some
+   * object-oriented languages which do not allow this cast.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_BASETYPE
+   *
+   * @return  The instance of type submatrix.
+   */
+   SubMatrix upcastSubMatrix()
+      raises (AoException);
+
+   /** (14021)
+   * Get the attribute value (name, value and unit) of the given
+   * attribute of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_INCOMPATIBLE_UNITS
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  attr  The name of the requested attribute and the unit of
+   *               the attribute value.
+   *
+   * @return  The attribute value, value converted to the requested unit.
+   */
+   NameValueUnit getValueInUnit(
+      in NameUnit attr)
+      raises (AoException);
+
+   /** (14022)
+   * Set a sequences of values of an application attributes but no
+   * instances attributes.
+   * 
+   * It is allowed to modify the values of the attributes outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The name of the attribute is specified by the name of the
+   * NameValueUnit tuple. If the application attribute flag unique is
+   * set, the uniqueness of the new value is checked.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_DUPLICATE_VALUE
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  values  The sequence of the values to be set at the instance
+   *                 element.
+   */
+   void setValueSeq(
+      in NameValueUnitSequence values)
+      raises (AoException);
+
+   /** (14023)
+   * The given user group the rights should be set for. <rights> defines
+   * the rights to set or to clear. If the parameter <set> is set to
+   * 'set', the rights in <rights> are set all others are cleared. If the
+   * parameter <set> is set to 'add', the rights in <rights> are added to
+   * the existing rights. If the parameter <set> is set to 'remove', the
+   * rights in <rights> are removed from the existing rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  usergroup  The user group for which the rights will be
+   *                    modified.
+   *
+   * @param  rights  The new right for the user group. The rights
+   *                 constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setRights(
+      in InstanceElement usergroup,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (14024)
+   * Retrieve access control list information of the given object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The access control list entries of the given application
+   *          element.
+   */
+   ACLSequence getRights()
+      raises (AoException);
+
+   /** (14025)
+   * Retrieve access control list information for the initial rights of
+   * the given object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The access control list entries with the initial rights of
+   *          the given application element.
+   */
+   InitialRightSequence getInitialRights()
+      raises (AoException);
+
+   /** (14026)
+   * The given user group the initial rights should be set for. <rights>
+   * defines the rights to set or to clear. If the parameter <set> is set
+   * to 'set', the rights in <rights> are set all others are cleared. If
+   * the parameter <set> is set to 'add', the rights in <rights> are
+   * added to the existing rights. If the parameter <set> is set to
+   * 'remove', the rights in <rights> are removed from the existing
+   * rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  usergroup  The user group for which the initial rights will
+   *                    be modified.
+   *
+   * @param  rights  The new initial rights for the user group. The
+   *                 rights constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions have to be done in the
+   *                 interface.
+   *
+   * @param  refAid  The Id of referencing application element for which
+   *                 the initial rights will be used. If no refAid is set
+   *                 the initial rights will be used for each new
+   *                 instance element independent of the application
+   *                 element.
+   *
+   * @param  set  What to do with the new initial rights.
+   */
+   void setInitialRights(
+      in InstanceElement usergroup,
+      in T_LONG rights,
+      in T_LONGLONG refAid,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (14027)
+   * Provides an easy-to-use and effective copy mechanism for instance
+   * elements inside the server. The new instance elements gets a copy of
+   * all attribute values and informational relations that are available
+   * in the original instance element. The new instance element has the
+   * same parent as the original instance element but it does not have
+   * references to any children of the original instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  newName  The name of the new instance element. If a new
+   *                  version shall be created this parameter may be NULL
+   *                  to use the same name for the copy. In this case a
+   *                  new version must be provided.
+   *
+   * @param  newVersion  The version of the new instance element. This
+   *                     parameter may be NULL if a new name is provided.
+   *
+   * @return  The reference to the copied instance element.
+   */
+   InstanceElement shallowCopy(
+      in T_STRING newName,
+      in T_STRING newVersion)
+      raises (AoException);
+
+   /** (14028)
+   * Provides an easy-to-use and effective copy mechanism for instance
+   * element hierarchies inside the server (e.g. copy a project with all
+   * tests or copy a test with all measurements). The deep copy follows
+   * only the child references but not the informational references.
+   * Example: Copying elements of type AoMeasurement does not include
+   * copying the referenced elements of type AoMeasurementQuantity. The
+   * copied instance elements of type AoMeasurement will reference the
+   * same measurement quantities as the original. An application that
+   * wants to copy the measurement quantity also must do this (including
+   * setting the proper references) by itself e.g. with another call to
+   * shallowCopy; deepCopy is not necessary in this case because
+   * AoMeasurementQuantity has no children.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  newName  The name of the new instance element. If a new
+   *                  version shall be created this parameter may be NULL
+   *                  to use the same name for the copy. In this case a
+   *                  new version must be provided.
+   *
+   * @param  newVersion  The version of the new instance element. This
+   *                     parameter may be NULL if a new name is provided.
+   *
+   * @return  The reference to the copied instance element hierarchy.
+   */
+   InstanceElement deepCopy(
+      in T_STRING newName,
+      in T_STRING newVersion)
+      raises (AoException);
+
+   /** (14029)
+   * Get the sequence of the values of the application or instance
+   * attributes, specified by their names.  The name sequence can use a
+   * pattern (*) for all attributes of the instance element. This means
+   * that application as well as   instance attributes will be delivered.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  attrNames  The names of the attributes to be reported.
+   *
+   * @return  The sequence of the attribute values.
+   */
+   NameValueUnitSequence getValueSeq(
+      in NameSequence attrNames)
+      raises (AoException);
+
+   /** (14030)
+   * Destroy the object on the server. The destructor of the client so
+   * the server knows this object is not used anymore by the client.
+   * Access to this object after the destroy method will lead to an
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (14031)
+   * Compare two instance elements. The Id's of the application elements
+   * and the Id's of the instance elements are compared. The Id's of the
+   * application elements will be compare first.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  compIeObj  The instance element to compare with.
+   *
+   * @return  The difference of the Id's. Meaning:
+   *          diff < 0 ElemId of instance is smaller then instance to
+   *          compare with.
+   *          diff == 0 ElemId is identical.
+   *          diff > 0 ElemId of instance is greater then instance to
+   *          compare with.
+   */
+   T_LONGLONG compare(
+      in InstanceElement compIeObj)
+      raises (AoException);
+
+   /** (14032)
+   * Create a list with instances which are related to the actual
+   * instance element. The attribute are given with the name of the
+   * sequence. The values of the attributes are given in the value
+   * sequence. The index in the different value sequences match for one
+   * instance element. The index in the instance element sequence of the
+   * related instances match for the instance with the same index in the
+   * value sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_INVALID_REQUEST
+   *
+   * @param  applRel  The application relation for witch the related
+   *                  instances will be created.
+   *
+   * @param  attributes  The attributes of the new created instances.
+   *
+   * @param  relatedInstances  The list with related instances for
+   *                           different application relations.
+   *
+   * @return  The list with the new created instances.
+   */
+   InstanceElementSequence createRelatedInstances(
+      in ApplicationRelation applRel,
+      in NameValueSeqUnitSequence attributes,
+      in ApplicationRelationInstanceElementSeqSequence relatedInstances)
+      raises (AoException);
+
+   /** (14033)
+   * Upcast the InstanceElement object to the corresponding ODSFile
+   * interface for an instance. 
+   * 
+   * This method may only be invoked for instances of an application
+   * element derived from
+   * the base element AoFile and returns an ODSFile interface.
+   * 
+   * An exception with the error code AO_INVALID_BASETYPE is thrown when
+   * the instance is not an instance of an application element derived
+   * from the base element AoFile.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_INVALID_BASETYPE
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The ODSFile interface to access the desired file.
+   */
+   ODSFile upcastODSFile()
+      raises (AoException);
+
+}; // Interface InstanceElement.
+
+/**
+* The ASAM ODS instance element iterator interface.
+*/
+interface InstanceElementIterator {
+
+   /** (15001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (15002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (15003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n instance elements from the instance sequence.
+   */
+   InstanceElementSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (15004)
+   * Get the next element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next instance element from the instance sequence.
+   */
+   InstanceElement nextOne()
+      raises (AoException);
+
+   /** (15005)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface InstanceElementIterator.
+
+/**
+* The ASAM ODS measurement interface.The interface Measurement extends
+* the interface InstanceElement. Thus alll methods of the interface
+* InstanceElement do also work here.
+*/
+interface Measurement : InstanceElement {
+
+   /** (16001)
+   * Create a submatrix link. The submatrix link is only valid in the
+   * current session. When the session is closed the submatrix link will
+   * be destroyed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The new submatrix link.
+   */
+   SMatLink createSMatLink()
+      raises (AoException);
+
+   /** (16002)
+   * Get the list of the submatrix links .
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The available submatrix links.
+   */
+   SMatLinkSequence getSMatLinks()
+      raises (AoException);
+
+   /** (16003)
+   * Get the value matrix of a measurement. 
+   * By calling this method, the value matrix mode of the returned value
+   * matrix will be taken from the context variable 'VALUEMATRIX_MODE'.
+   * For more information especially on different modes of the value
+   * matrix, see description at the method getValueMatrixInMode() of this
+   * interface.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_VALUEMATRIX_STRUCTURE
+   *
+   * @return  The value matrix.
+   */
+   ValueMatrix getValueMatrix()
+      raises (AoException);
+
+   /** (16004)
+   * Remove a submatrix link.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  smLink  The sub matrix link to be removed.
+   */
+   void removeSMatLink(
+      in SMatLink smLink)
+      raises (AoException);
+
+   /** (16005)
+   * Get the value matrix of a measurement in the requested mode.
+   * 
+   * The server checks the independent column, if there is more than one
+   * submatrix at the measurement there must be exactly one independent
+   * column with the same measurement quantity in each submatrix,
+   * otherwise the exception AO_INVALID_VALUEMATRIX_STRUCTURE is
+   * thrown.
+   * 
+   * The server throws the exception AO_INVALID_VALUEMATRIX_STRUCTURE
+   * when it is unable to create the value matrix due to the data of the
+   * measurement
+   * - if there are no independent column
+   * - if there are different independent columns
+   * - if there are sub matrices with more than one independent column.
+   * 
+   * The server orders the values according to the values of the
+   * independent localcolumn. (in ascending order) It is up to the server
+   * what value is returned when a measurement quantity has two different
+   * values at the same independent point. The gaps are marked with Flags
+   * in TS_ValueSeq (flagvalue = 0).
+   * 
+   * In the CALCULATED mode the server returns the calculated values for
+   * implicit and raw values. The server returns at each measurement
+   * point the explicit value as the value for the implicit channels. The
+   * raw values are calculated to the explicit values.
+   * 
+   * In the STORAGE mode the server handles the values of the localcolumn
+   * as they are in the storage. Write is only allowed when the value
+   * matrix is in the STROAGE mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_VALUEMATRIX_STRUCTURE
+   *
+   * @param  vmMode  The requested mode of the value matrix.
+   *
+   * @return  The value matrix.
+   */
+   ValueMatrix getValueMatrixInMode(
+      in ValueMatrixMode vmMode)
+      raises (AoException);
+
+}; // Interface Measurement.
+
+/**
+* The ASAM ODS name iterator interface.
+*/
+interface NameIterator {
+
+   /** (17001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (17002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (17003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n names from the name sequence.
+   */
+   NameSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (17004)
+   * Get the next element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next name from the name sequence.
+   */
+   Name nextOne()
+      raises (AoException);
+
+   /** (17005)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface NameIterator.
+
+/**
+* The ASAM ODS name-value iterator interface.
+*/
+interface NameValueIterator {
+
+   /** (18001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (18002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (18003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n name-value pairs from the name-value pair
+   *          sequence.
+   */
+   NameValueSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (18004)
+   * Get the next element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next name-value pair from the name-value pair sequence.
+   */
+   NameValue nextOne()
+      raises (AoException);
+
+   /** (18005)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface NameValueIterator.
+
+/**
+* The ASAM ODS name-value-unit iterator interface. This interface is
+* identical with the NameValueUnitIdIterator, except the unit is given as
+* a string insead of an Id.
+*/
+interface NameValueUnitIterator {
+
+   /** (19001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (19002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (19003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n name-value-unit tuples from the name-value-unit
+   *          tuple sequence.
+   */
+   NameValueUnitSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (19004)
+   * Get the next element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next name-value-unit tuple from the name-value-unit
+   *          tuple sequence.
+   */
+   NameValueUnit nextOne()
+      raises (AoException);
+
+   /** (19005)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface NameValueUnitIterator.
+
+/**
+* The ASAM ODS submatrix link interface.
+*/
+interface SMatLink {
+
+   /** (20001)
+   * Get the link or build type.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The link type.
+   */
+   BuildUpFunction getLinkType()
+      raises (AoException);
+
+   /** (20002)
+   * Get the ordinal or sequence number
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The sequence number.
+   */
+   T_LONG getOrdinalNumber()
+      raises (AoException);
+
+   /** (20003)
+   * Get the first submatrix of the link.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The first submatrix of the link.
+   */
+   SubMatrix getSMat1()
+      raises (AoException);
+
+   /** (20004)
+   * Get the bind columns of the first submatrix used in the link (e.g.
+   * Time).
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The columns of the first submatrix.
+   */
+   ColumnSequence getSMat1Columns()
+      raises (AoException);
+
+   /** (20005)
+   * Get the second submatrix of the link.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The second submatrix of the link.
+   */
+   SubMatrix getSMat2()
+      raises (AoException);
+
+   /** (20006)
+   * Get the bind columns of the second submatrix used in the link (e.g.
+   * Time).
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The columns of the second submatrix.
+   */
+   ColumnSequence getSMat2Columns()
+      raises (AoException);
+
+   /** (20007)
+   * Set the build or link type.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_BUILDUP_FUNCTION
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  linkType  The requested build-up function.
+   */
+   void setLinkType(
+      in BuildUpFunction linkType)
+      raises (AoException);
+
+   /** (20008)
+   * Set the ordinal or sequence number.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_ORDINALNUMBER
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  ordinalNumber  The sequence number.
+   */
+   void setOrdinalNumber(
+      in T_LONG ordinalNumber)
+      raises (AoException);
+
+   /** (20009)
+   * Set the first submatrix of the link.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_SUBMATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  subMat1  The first sub matrix of the sub matrix link.
+   */
+   void setSMat1(
+      in SubMatrix subMat1)
+      raises (AoException);
+
+   /** (20010)
+   * Set the bind columns of the first submatrix used in the link (e.g.
+   * Time).
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COLUMN
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  columns  The column sequence of the sub matrix.
+   */
+   void setSMat1Columns(
+      in ColumnSequence columns)
+      raises (AoException);
+
+   /** (20011)
+   * Set the second submatrix of the link.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_INVALID_SUBMATRIX
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  subMat2  The second sub matrix of the sub matrix link.
+   */
+   void setSMat2(
+      in SubMatrix subMat2)
+      raises (AoException);
+
+   /** (20012)
+   * Set the bind columns of the second submatrix used in the link (e.g.
+   * Time). If there is more than one column bound the column sequence
+   * must be identical with the column sequence of the first submatrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_INVALID_COLUMN
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  columns  The column sequence of the sub matrix.
+   */
+   void setSMat2Columns(
+      in ColumnSequence columns)
+      raises (AoException);
+
+}; // Interface SMatLink.
+
+/**
+* The ASAM ODS submatrix interface. The instances of the submatrix can be
+* accessed via the method getRelatedInstances of the interface
+* Measurement. The interface SubMatrix extends the interface
+* InstanceElement. Thus alll methods of the interface InstanceElement do
+* also work here.
+*/
+interface SubMatrix : InstanceElement {
+
+   /** (21001)
+   * Get the columns of the submatrix. The column is not inherited from
+   * the InstanceElement interface. This is the only way to get a column.
+   * The columns are used in the SMatLink interface to build the value
+   * matrix. The pattern is case sensitive and may contain wildcard
+   * characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the column
+   *                     names.
+   *
+   * @return  The columns of the submatrix.
+   */
+   ColumnSequence getColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (21002)
+   * Get a value matrix of the submatrix.
+   * By calling this method, the value matrix mode of the returned value
+   * matrix will be taken from the context variable 'VALUEMATRIX_MODE'.
+   * For more information especially on different modes of the value
+   * matrix, see description at the method getValueMatrixInMode() of this
+   * interface.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_SMATLINK
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The value matrix.
+   */
+   ValueMatrix getValueMatrix()
+      raises (AoException);
+
+   /** (21003)
+   * Get the names of the columns of the submatrix. The name sequence is
+   * identical with the names of the related instances. The pattern is
+   * case sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the column
+   *                     names.
+   *
+   * @return  The column names of the submatrix.
+   */
+   NameSequence listColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (21004)
+   * Get the value matrix of a submatrix in the requested mode.
+   * 
+   * The server doesn't check any independent columns. The columns are
+   * only the local columns from this submatrix. The flags in the
+   * TS_ValueSeq are the flags of the localcolumn. If no flags are given
+   * there are no flags available, the client have to check the
+   * global_flag.
+   * 
+   * In the CALCULATED mode the server returns the calculated values for
+   * implicit and raw values. The server returns at each measurement
+   * point the explicit value as the value for the implicit channels. The
+   * raw values are calculated to the explicit values.
+   * 
+   * In the STORAGE mode the server handles the values of the localcolumn
+   * as they are in the storage. Write is only allowed when the value
+   * matrix is in the STROAGE mode. The values are exactly from this
+   * submatrix. The raw / implicit values are returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  vmMode  The requested mode of the value matrix.
+   *
+   * @return  The value matrix.
+   */
+   ValueMatrix getValueMatrixInMode(
+      in ValueMatrixMode vmMode)
+      raises (AoException);
+
+}; // Interface SubMatrix.
+
+/**
+* The ASAM ODS value matrix interface. Value matrix is an interface used
+* by Measurement and SubMatrix to handle vectors of values.
+*/
+interface ValueMatrix {
+
+   /** (22001)
+   * Get the columns of the value matrix no matter whether the column is
+   * dependent or independent. The pattern is case sensitive and may
+   * contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the column
+   *                     names.
+   *
+   * @return  The columns of the value matrix, no matter whether the
+   *          column is dependent, independent or scaling
+   */
+   ColumnSequence getColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22002)
+   * Get the column count of the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of columns of the value matrix.
+   */
+   T_LONG getColumnCount()
+      raises (AoException);
+
+   /** (22003)
+   * Get the independent columns of the value matrix. The independent
+   * columns are the columns used to build the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the
+   *                     independent column name.
+   *
+   * @return  The independent column of the value matrix.
+   */
+   ColumnSequence getIndependentColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22004)
+   * Get the row count of the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of rows of the value matrix.
+   */
+   T_LONG getRowCount()
+      raises (AoException);
+
+   /** (22005)
+   * Get a measurement point of the value matrix. The parameter meaPoint
+   * specifies the row of the matrix. The iterator allows to access all
+   * elements in the row.
+   * 
+   * The server behavior depends on the mode of the value matrix.
+   * Value matrix mode 'CALCULATED':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will first calculate the physical values from raw values and
+   * generation parameters, before it returns them to the requesting
+   * client.
+   * Value matrix mode 'STORAGE':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will return the raw values of the local column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  meaPoint  The measurement point.
+   *
+   * @return  The requested measurement point.
+   */
+   NameValueUnitIterator getValueMeaPoint(
+      in T_LONG meaPoint)
+      raises (AoException);
+
+   /** (22006)
+   * Get the values or a part of values of the column from the value
+   * matrix. The parameter column specifies from which column the values
+   * will be returned. The startPoint and count specify the part of the
+   * vector. A startPoint = 0 and count = rowCount will return the entire
+   * vector. When startPoint >= rowCount an exception is thrown. If
+   * startPoint + count > rowCount only the remaining values of the
+   * vector are returned and no exception is thrown. Use the getName and
+   * getUnit method of the interface column for the name and the unit of
+   * the column. The name and the value are not stored at each element of
+   * the vector. The return type TS_ValueSeq is not a sequence of
+   * TS_Value but a special structure.
+   * 
+   * The server behavior depends on the mode of the value matrix.
+   * Value matrix mode 'CALCULATED':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will first calculate the physical values from raw values and
+   * generation parameters, before it returns them to the requesting
+   * client.
+   * Value matrix mode 'STORAGE':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will return the raw values of the local column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COLUMN
+   *    AO_INVLAID_COUNT
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  col  The column to retrieve the values from.
+   *
+   * @param  startPoint  The starting point in the column.
+   *
+   * @param  count  The number of points to be retrieved.
+   *
+   * @return  The requested column values of the value matrix.
+   */
+   TS_ValueSeq getValueVector(
+      in Column col,
+      in T_LONG startPoint,
+      in T_LONG count)
+      raises (AoException);
+
+   /** (22007)
+   * Get the names of the columns of the value matrix no matter whether
+   * the column is dependent or independent. The pattern is case
+   * sensitive and may contain wildcard characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the column
+   *                     names.
+   *
+   * @return  The column names of the value matrix, no matter whether the
+   *          column is dependent, independent or scaled by another one.
+   */
+   NameSequence listColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22008)
+   * Get the names of the independent columns of the value matrix. The
+   * independent columns are the columns used to build the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the
+   *                     independent column name.
+   *
+   * @return  The names of the independent columns of the value matrix.
+   */
+   NameSequence listIndependentColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22009)
+   * Remove the values of the columns at a given measurement point.
+   * Remove the number of points of the given column. If the count is 0
+   * all points until the end of the column are removed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COUNT
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  columnNames  The columns from which the measurement points
+   *                      are to be removed.
+   *
+   * @param  meaPoint  The measurement point to be removed.
+   *
+   * @param  count  The number of points to be removed from each column.
+   */
+   void removeValueMeaPoint(
+      in NameSequence columnNames,
+      in T_LONG meaPoint,
+      in T_LONG count)
+      raises (AoException);
+
+   /** (22010)
+   * Remove the values from a value vector. Beginning at startPoint the
+   * number of values specified in count are removed. If count is 0 all
+   * values from  the startPoint until the end of the vector are removed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COLUMN
+   *    AO_INVALID_COUNT
+   *    AO_NOT_FOUND
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  col  The column from which the values are to be removed.
+   *
+   * @param  startPoint  The starting point for the value removal.
+   *
+   * @param  count  The number of points to be removed from the column.
+   */
+   void removeValueVector(
+      in Column col,
+      in T_LONG startPoint,
+      in T_LONG count)
+      raises (AoException);
+
+   /** (22011)
+   * Create or modify a measurement point of a value matrix. 
+   * The sequence of name values specifies the names of the column with
+   * the new values. 
+   * The meaning of the parameter setType is:
+   * 
+   *    INSERT   Insert the values at meaPoint, the current values at
+   * meaPoint    are moved to the end of  the new inserted values.
+   * 
+   *    APPEND   The value of meaPoint is ignored, the values are
+   * appended at the end of the current values.
+   * 
+   *    UPDATE   Update or modify the values at meaPoint, the current
+   * values are overwritten. If meaPoint is bigger than the number of
+   * values in the          vector, the measurement point is
+   * automatically appended.
+   * 
+   * The names of the columns have to exist.
+   * 
+   * When a client creates a ValueMatrix based on AoMeasurement this
+   * methods behaves as follows:
+   * The server checks the sub matrices and creates all necessary
+   * instances of AoSubmatrix, AoLocalColumn and AoMeasurementQuantity. 
+   * The values of the name attribute of AoSubmatrix must be generated by
+   * the server. The value will be equal to the value of the attribute ID
+   * (converted to DT_STRING). Missing instances of AoMeasurementQuantity
+   * will be created by the server, too. 
+   * 
+   * The mandatory attributes will get the following default values:
+   * Name supplied by client 
+   * Datatype copied from AoQuantity.default_datatype
+   * Typesize copied from AoQuantity.default_typesize
+   * Interpolation no interpolation
+   * Rank copied from AoQuantity.default_rank
+   * Dimension copied from AoQuantity.default_dimension
+   * 
+   * The server takes the value of the channel (supplied by client) and
+   * looks up the corresponding instance in AoQuantity using the
+   * attribute default_meq_name.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_IS_MEASUREMENT_MATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  set  The set type.
+   *
+   * @param  meaPoint  The measurement point.
+   *
+   * @param  value  The values to be inserted.
+   */
+   void setValueMeaPoint(
+      in SetType set,
+      in T_LONG meaPoint,
+      in NameValueSequence value)
+      raises (AoException);
+
+   /** (22012)
+   * Create or modify a value vector in a value matrix. 
+   * 
+   * It is allowed to modify the values of the value matrix outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The data is made permanent on transaction commit. Until the
+   * transaction is committed or until the access to the measurement
+   * point of the value matrix, it is allowed to have different number of
+   * values in the different value vectors.
+   * 
+   * The meaning of the parameter setType is:
+   * 
+   *    INSERT   Insert the values from startPoint, the current available
+   * values from startPoint are moved to the end of the new inserted
+   * values.
+   * 
+   *    APPEND   The value of startPoint is ignored,  the values are
+   * appended at the end of the current values.
+   * 
+   *    UPDATE   Update or modify the values from startPoint, the current
+   * values are overwritten. If the number of values in the parameter
+   * values is too big    the values are automatically appended.
+   * 
+   * When a client creates a ValueMatrix based on AoMeasurement this
+   * methods 
+   * behaves as follows:
+   * The server checks the sub matrices and creates all necessary
+   * instances of AoSubmatrix, AoLocalColumn and AoMeasurementQuantity. 
+   * The values of the name attribute of AoSubmatrix must be generated by
+   * the server. The value will be equal to the value of the attribute ID
+   * (converted to DT_STRING). Missing instances of AoMeasurementQuantity
+   * will be created by the server, 
+   * too. 
+   * 
+   * The mandatory attributes will get the following default values:
+   * Name supplied by client 
+   * Datatype copied from AoQuantity.default_datatype
+   * Typesize copied from AoQuantity.default_typesize
+   * Interpolation no interpolation
+   * Rank copied from AoQuantity.default_rank
+   * Dimension copied from AoQuantity.default_dimension
+   * 
+   * The server takes the value of the channel (supplied by client) and
+   * looks up the corresponding instance in AoQuantity using the
+   * attribute default_meq_name.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COLUMN
+   *    AO_INVALID_SET_TYPE
+   *    AO_IS_MEASUREMENT_MATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  col  The column whose values are to be set.
+   *
+   * @param  set  The set type.
+   *
+   * @param  startPoint  The starting point for the new values.
+   *
+   * @param  value  The values to be inserted.
+   */
+   void setValueVector(
+      in Column col,
+      in SetType set,
+      in T_LONG startPoint,
+      in TS_ValueSeq value)
+      raises (AoException);
+
+   /** (22013)
+   * Create or modify a number of value vectors in a value matrix. 
+   * 
+   * It is allowed to modify the values of the value matrix outside a
+   * transaction but it is recommended to activate a transaction.
+   * 
+   * The data is made permanent on transaction commit. Until the
+   * transaction is committed or until the access to the measurement
+   * point of the value matrix it is allowed to have different numbers of
+   * values in the different value vectors.
+   * 
+   * The names of the parameter values are the names of the columns. The
+   * values are the new values of the column. (setValueMeaPoint allows
+   * only one point, the TS_ValueSeq allows more then one point) There is
+   * a sequence of name value pairs (setValueVector allows only one
+   * column), so a block of values can be modified.
+   * 
+   * The meaning of the parameter setType is:
+   * 
+   *    INSERT   Insert the values from startPoint,  the current
+   * available values from  startPoint are moved to the end of  the new
+   * inserted values.
+   * 
+   *    APPEND   The value of startPoint is ignored, the values are
+   * appended at the end of the current values.
+   * 
+   *    UPDATE   Update or modify the values from startPoint, the current
+   * values are overwritten. If the number of values is greater than the
+   * number of values in the  vector, the measurement point is 
+   * automatically appended.
+   * 
+   *    REMOVE  Remove the number of values from each column, starting
+   * with startPoint. The name of the column is given as the name of the
+   * NameValueseqUnit, the  number of values to remove is given  in the
+   * number of the values in the   value.
+   * 
+   * When a client creates a ValueMatrix based on AoMeasurement this
+   * methods behaves as follows:
+   * The server checks the sub matrices and creates all necessary
+   * instances of AoSubmatrix, AoLocalColumn and AoMeasurementQuantity. 
+   * The values of the name attribute of AoSubmatrix must be generated by
+   * the server. The value will be equal to the value of the attribute ID
+   * (converted to DT_STRING). Missing instances of AoMeasurementQuantity
+   * will be created by the server, too. 
+   * 
+   * The mandatory attributes will get the following default values:
+   * Name supplied by client 
+   * Datatype copied from AoQuantity.default_datatype
+   * Typesize copied from AoQuantity.default_typesize
+   * Interpolation no interpolation
+   * Rank copied from AoQuantity.default_rank
+   * Dimension copied from AoQuantity.default_dimension
+   * 
+   * The server takes the value of the channel (supplied by client) and
+   * looks up the corresponding instance in AoQuantity using the
+   * attribute default_meq_name.
+   * 
+   * The ValueMatrix interface handles the values but not the raw values,
+   * to modify the raw values the instances of localcolumn must be
+   * created, the base attribute sequence_representation, raw_datatype
+   * and the generation_parameter must be created before the values are
+   * modified. The values must have the data type identical with the
+   * raw_datatype, any other data type will cause an AO_INVALID_DATATYPE
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_COLUMN
+   *    AO_INVALID_SET_TYPE
+   *    AO_INVALID_DATATYPE
+   *    AO_IS_MEASUREMENT_MATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  set  The set type.
+   *
+   * @param  startPoint  The measurement point.
+   *
+   * @param  value  The values to be inserted.
+   */
+   void setValue(
+      in SetType set,
+      in T_LONG startPoint,
+      in NameValueSeqUnitSequence value)
+      raises (AoException);
+
+   /** (22014)
+   * Add a column to the value matrix. It is only allowed to create a
+   * value vector if the value matrix is created from a submatrix. 
+   * 
+   * It is allowed to add a column outside a transaction but it is
+   * recommended to activate a transaction.
+   * 
+   * The data is made permanent on transaction commit. Until the
+   * transaction is committed or until the access to the measurement
+   * point of the value matrix it is allowed to have different number of
+   * values in the different value vectors. After the new column is
+   * added, it is possible to set the values of the column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_NAME
+   *    AO_INVALID_SET_TYPE
+   *    AO_IS_MEASUREMENT_MATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  newColumn  The name and unit of the column to add.
+   *
+   * @return  The new column.
+   */
+   Column addColumn(
+      in NameUnit newColumn)
+      raises (AoException);
+
+   /** (22015)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Get the names of the scaling columns of the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the scaling
+   *                     column name.
+   *
+   * @return  The names of the scaling columns of the value matrix.
+   */
+   NameSequence listScalingColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22016)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Get the scaling column of the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  colPattern  The name or the search pattern for the scaling
+   *                     column name.
+   *
+   * @return  The scaling columns of the value matrix.
+   */
+   ColumnSequence getScalingColumns(
+      in Pattern colPattern)
+      raises (AoException);
+
+   /** (22017)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * List the names of the columns, which are scaled by the given column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NO_SCALING_COLUMN
+   *
+   * @param  scalingColumn  The scaling column.
+   *
+   * @return  The names of the columns which are scaled by the given
+   *          input column.
+   */
+   NameSequence listColumnsScaledBy(
+      in Column scalingColumn)
+      raises (AoException);
+
+   /** (22018)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Get the columns which are scaled by the given column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NO_SCALING_COLUMN
+   *
+   * @param  scalingColumn  The scaling column.
+   *
+   * @return  The columns which are scaled by the given input column.
+   */
+   ColumnSequence getColumnsScaledBy(
+      in Column scalingColumn)
+      raises (AoException);
+
+   /** (22019)
+   * Deprecated, solved by NVH Application model.
+   * 
+   * Add a column to the value matrix. It is only allowed to create a
+   * value vector if the value matrix is created from a submatrix. The
+   * column will be scaled by the given scaling column.
+   * 
+   * It is allowed to add a column outside a transaction but it is
+   * recommended to activate a transaction.
+   * 
+   * The data is made permanent on transaction commit. Until the
+   * transaction is committed or until the access to the measurement
+   * point of the value matrix it is allowed to have different number of
+   * values in the different value vectors. After the new column is
+   * added, it is possible to set the values of the column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_INVALID_NAME
+   *    AO_INVALID_SET_TYPE
+   *    AO_IS_MEASUREMENT_MATRIX
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NO_SCALING_COLUMN
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  newColumn  The name and unit of the column to add.
+   *
+   * @param  scalingColumn  The scaling column.
+   *
+   * @return  The new column.
+   */
+   Column addColumnScaledBy(
+      in NameUnit newColumn,
+      in Column scalingColumn)
+      raises (AoException);
+
+   /** (22020)
+   * Destroy the object on the server. The destructor of the client, so
+   * the server knows this object is not used anymore by the client.
+   * Access to this object after the destroy method will lead to an
+   * exception.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (22021)
+   * Get the values of different columns of the value matrix.
+   * 
+   * The server behavior depends on the mode of the value matrix.
+   * Value matrix mode 'CALCULATED':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will first calculate the physical values from raw values and
+   * generation parameters, before it returns them to the requesting
+   * client.
+   * Value matrix mode 'STORAGE':
+   * In case 'sequence_representation' of the corresponding local column
+   * is one of the entries 'raw_linear', raw_polynomial',
+   * 'raw_linear_external', 'raw_polynomial_external',
+   * 'raw_linear_calibrated', or 'raw_linear_calibrated_external', the
+   * server will return the raw values of the local column.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  columns  The requested columns.
+   *
+   * @param  startPoint  The starting point in the column.
+   *
+   * @param  count  The number of points to be retrieved. 0 mean until
+   *                end of column.
+   *
+   * @return  The values of the different columns. The name of the return
+   *          structure corresponds with the name of the column. The unit
+   *          corresponds with the unit of the column. The order of the
+   *          results might not match the order in the requested
+   *          sequence.
+   */
+   NameValueSeqUnitSequence getValue(
+      in ColumnSequence columns,
+      in T_LONG startPoint,
+      in T_LONG count)
+      raises (AoException);
+
+   /** (22022)
+   * Get the current mode of the value matrix.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The mode of the value matrix
+   */
+   ValueMatrixMode getMode()
+      raises (AoException);
+
+}; // Interface ValueMatrix.
+
+/**
+* The ASAM ODS name-value-unitId iterator interface. This interface is
+* identical with the NameValueUnitIterator, except the unit is given as
+* an Id insead of a string.
+*/
+interface NameValueUnitIdIterator {
+
+   /** (23001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (23002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (23003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n name-value-unit tuples from the name-value-unit
+   *          tuple sequence.
+   */
+   NameValueSeqUnitId nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (23004)
+   * Get the next element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next name-value-unitId tuple from the name-value-unitId
+   *          tuple sequence.
+   */
+   NameValueUnitId nextOne()
+      raises (AoException);
+
+   /** (23005)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface NameValueUnitIdIterator.
+
+/**
+* The application element access.  The ApplElemAccess interface (RPC API
+* GetVal, PutVal, GetInstRef, ...) is responsible to retrieve instances
+* of application elements. Currently available query methods are:
+* - query with attribute and value
+* - query with attribute and values (not)in set
+* - sorted results
+* - grouped results including having condition
+*/
+interface ApplElemAccess {
+
+   /** (24001)
+   * Perform the Query.
+   * 
+   * The number of different application elements which are requested are
+   * exactly defined by the definition of the query given in the field
+   * anuSeq of the QueryStructure. The number of attributes for each
+   * application element is also given in the definition. The number of
+   * matching instances (their attributes) is not defined by the query
+   * and can be a large amount. Therefore only one iterator for the
+   * attribute values are defined.
+   * 
+   * The values of the localcolumn instances is part of the resultset
+   * when the following criteria all fit:
+   * 
+   * - Only when the attributes id, generation_parameters, values, flags
+   * are requested, as soon as any other attributes is requested the
+   * values are not reported.
+   * - The values of the localcolumn must all belong to exactly one
+   * instances of AoMeasurement
+   * - The server have a limitation of the memory, not the system memory
+   * limitation, as soon as the result set will break the limitation an
+   * exception will be thrown.
+   * 
+   * - No iterator for the rest is required.
+   * 
+   * In case an attribute of blob type is among the requested attributes,
+   * the content of the return structure will depend on the number of
+   * instances that are returned:
+   * - In case attributes of only one instance are returned (either
+   * because 'how_many' was set to 1 or there is only one instance
+   * available at the server), the return structure contains the blob
+   * itself.
+   * -In case attributes of more than one instance are returned, the
+   * return structure does not contain the blobs; instead it contains the
+   * headers of the respective blobs.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aoq  The query definition.
+   *
+   * @param  how_many  Maximum number of values in each result set. Valid
+   *                   arguments are: 
+   *                   how_many = 0 : report all found values,
+   *                   how_many > 0 : report a maximum number of values.
+   *
+   * @return  The result set with the requested attribute values.
+   */
+   ElemResultSetSequence getInstances(
+      in QueryStructure aoq,
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (24002)
+   * Get related instances (Id). This method returns a sequence of
+   * related instances. 
+   * 
+   * The relation name specifies the relation given in the
+   * ApplStructValue. The aid of the ElemId and the relName defines the
+   * unique relation and the target application element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  elem  Original instance. 
+   *               
+   *               At the RPC API this information was stored in the
+   *               field elemId of the structure GetInstRefReq and the
+   *               request AOP_GetInstRef.
+   *
+   * @param  relName  The relation name. 
+   *                  
+   *                  At the RPC API this information was stored in the
+   *                  field refName of the structure GetInstRefReq   and
+   *                  the request AOP_GetInstRef.
+   *
+   * @return  The list of the Id of the related instances.
+   */
+   S_LONGLONG getRelInst(
+      in ElemId elem,
+      in Name relName)
+      raises (AoException);
+
+   /** (24003)
+   * Set the instance reference.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  elem  The instance to add the related instances.
+   *               
+   *               At the RPC API this information was stored in the
+   *               field elemId1 of the structure SetInstRefReq  and the
+   *               request AOP_SetInstRef.
+   *
+   * @param  relName  The name of relation. 
+   *                  
+   *                  At the RPC API this information was stored in the
+   *                  field refName of the structure SetInstRefReq and
+   *                  the request AOP_SetInstRef.
+   *
+   * @param  instIds  Sequence of instance id's. 
+   *                  
+   *                  At the RPC API this information was stored in the
+   *                  field elemId2 of the structure SetInstRefReq and
+   *                  the request AOP_SetInstRef. It was not possible to
+   *                  set more then one relation.
+   *
+   * @param  type  The type of the modification, insert, update or
+   *               remove. 
+   *               
+   *               At the RPC API this information was stored in the
+   *               field on off of the structure SetInstRefReq and the
+   *               request AOP_SetInstRef.
+   */
+   void setRelInst(
+      in ElemId elem,
+      in Name relName,
+      in S_LONGLONG instIds,
+      in SetType type)
+      raises (AoException);
+
+   /** (24004)
+   * Create instance elements of an application element. 
+   * The application element is specified by the AID of input structure.
+   * 
+   * The attribute names are specified by the name of the input
+   * structure.
+   * The values of one instance element are specified in the valueseq of
+   * the input structure.
+   * You can create several instance elements in one call by filling the
+   * valueseq of the input structure.
+   * The same index in the valueseq corresponds to the attributes values
+   * of one instance element. This method returns a sequence of Id's, the
+   * order is related to the order of instance element specified in the
+   * input structure. In case of inheritance, the method supports only
+   * instances of same subtype per call. The returned Id's are the Id's
+   * of the related super type instances.
+   * 
+   * The client must supply all mandatory attributes and references
+   * within one single method call; otherwise the object cannot be made
+   * persistent by the server in the database without the risk of
+   * violating any database constraint.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  val  The sequence of attributes and their values. 
+   *              
+   *              At the RPC API this information was stored in the
+   *              fields elemId and nvSeq of the structure PutValReq and
+   *              the request AOP_PutValReq.
+   *
+   * @return  List with the Id's of the new created instances.
+   */
+   ElemIdSequence insertInstances(
+      in AIDNameValueSeqUnitIdSequence val)
+      raises (AoException);
+
+   /** (24005)
+   * Update one or more attributes of one or more instance elements. It's
+   * necessary that the input structure includes also the Id attribute,
+   * the Id attribute will be used to select the instance elements. In
+   * case of inherited application elements the super type Id has to be
+   * included. The values of one instance element are specified in the
+   * valueseq of the input structure. The same index in the valueseq
+   * corresponds to the attributes values of one instance element. 
+   * 
+   * The server will update the values of the localcolumn instances when
+   * the following criteria all fit:
+   * 
+   * - Only when the attributes id, generation_parameters, values, flags
+   * are given, as soon as any other attributes is given an exception is
+   * thrown.
+   * - The values of the localcolumn must all belong to exactly one
+   * instances of AoMeasurement
+   * - The server have a limitation of the memory, not the system memory
+   * limitation, as soon as the given values breaks the limitation an
+   * exception will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  val  The sequence of attributes and their values. At least
+   *              one of the attribute values sequence must be a sequence
+   *              with the Id. 
+   *              
+   *              At the RPC API this information was stored in the
+   *              fields elemId and nvSeq of the structure PutValReq and
+   *              the request AOP_PutValReq.
+   */
+   void updateInstances(
+      in AIDNameValueSeqUnitIdSequence val)
+      raises (AoException);
+
+   /** (24006)
+   * Delete instances from an application element. In case of inherited
+   * application elements the Id of the super type has to be specified.
+   * 
+   * This method can be used to delete several instances of the same
+   * application element, the method removeInstance of the interface
+   * ApplicationElement to remove one instance of an application element
+   * with the children of the instance element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The application element Id.
+   *
+   * @param  instIds  The sequence of instance Id's. 
+   *                  
+   *                  At the RPC API this information was stored in the
+   *                  fields elemId and nvSeq of the structure PutValReq
+   *                  and the request AOP_PutValReq.
+   */
+   void deleteInstances(
+      in T_LONGLONG aid,
+      in S_LONGLONG instIds)
+      raises (AoException);
+
+   /** (24007)
+   * Get the value matrix of a measurement or a submatrix. If the value
+   * matrix will be built up with special submatrix link, use the
+   * interface Measurement.
+   * By calling this method, the value matrix mode of the returned value
+   * matrix will be taken from the context variable 'VALUEMATRIX_MODE'.
+   * For more information especially on different modes of the value
+   * matrix, see description at the method getValueMatrixInMode() of the
+   * interfaces 'Measurement' and 'SubMatrix'.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_BASETYPE
+   *
+   * @param  elem  The element id. The aid has to be the application
+   *               element Id of the AoMeasurement or AoSubmatrix.
+   *
+   * @return  The value matrix
+   */
+   ValueMatrix getValueMatrix(
+      in ElemId elem)
+      raises (AoException);
+
+   /** (24008)
+   * Set the ACL information on some application element-attribute
+   * defined by <aid> and <attr_name>. The <usergroup_id> defines the
+   * user group the rights should be set for. <rights> defines the rights
+   * to set or to clear. If the parameter <set> is set to 'set', the
+   * rights in <rights> are set all others are cleared. If the parameter
+   * <set> is set to 'add', the rights in <rights> are added to the
+   * existing rights. If the parameter <set> is set to 'remove', the
+   * rights in <rights> are removed from the existing rights. Restriction
+   * for the model: only one application element of the type AoUserGroup
+   * is allowed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  attrName  The name of the attribute.
+   *
+   * @param  usergroupId  The user group to set the rights for.
+   *
+   * @param  rights  The new right for the user group.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setAttributeRights(
+      in T_LONGLONG aid,
+      in T_STRING attrName,
+      in T_LONGLONG usergroupId,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24009)
+   * Set the ACL information on some application element defined by
+   * <aid>. The <usergroup_id> defines the user group the rights should
+   * be set for. <rights> defines the rights to set or to clear. If the
+   * parameter <set> is set to 'set', the rights in <rights> are set all
+   * others are cleared. If the parameter <set> is set to 'add', the
+   * rights in <rights> are added to the existing rights. If the
+   * parameter <set> is set to 'remove', the rights in <rights> are
+   * removed from the existing rights.  Restriction for the model: only
+   * one application element of the type AoUserGroup is allowed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  usergroupId  The user group to set the rights for.
+   *
+   * @param  rights  The new rights for the user group. The rights
+   *                 constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setElementRights(
+      in T_LONGLONG aid,
+      in T_LONGLONG usergroupId,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24010)
+   * Set the ACL information on some instance defined by the application
+   * element id <aid> and a sequence of instance defined by the id <iid>.
+   * The <usergroup_id> defines the user group the rights should be set
+   * for. <rights> defines the rights to set or to clear. If the
+   * parameter <set> is set to 'set', the rights in <rights> are set all
+   * others are cleared. If the parameter <set> is set to 'add', the
+   * rights in <rights> are added to the existing rights. If the
+   * parameter <set> is set to 'remove', the rights in <rights> are
+   * removed from the existing rights.  Restriction for the model: only
+   * one application element of the type AoUserGroup is allowed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  instIds  The sequence of instance Id's.
+   *
+   * @param  usergroupId  The user group to set the rights for.
+   *
+   * @param  rights  The new right for the user group.
+   *
+   * @param  set  What to do with the new right.
+   */
+   void setInstanceRights(
+      in T_LONGLONG aid,
+      in S_LONGLONG instIds,
+      in T_LONGLONG usergroupId,
+      in T_LONG rights,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24011)
+   * Retrieve access control list information for the given application
+   * attribute <aid>/<attr_name>.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  attrName  The name of the attribute.
+   *
+   * @return  The access control list entries of the give application
+   *          attribute.
+   */
+   ACLSequence getAttributeRights(
+      in T_LONGLONG aid,
+      in T_STRING attrName)
+      raises (AoException);
+
+   /** (24012)
+   * Retrieve access control list information for the requested
+   * application element <aid>.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @return  The access control list entries of the given application
+   *          element.
+   */
+   ACLSequence getElementRights(
+      in T_LONGLONG aid)
+      raises (AoException);
+
+   /** (24013)
+   * Retrieve access control list information for the requested instance
+   * <aid>/<iid>.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  iid  The Id of the instance.
+   *
+   * @return  The access control list entries of the given instance.
+   */
+   ACLSequence getInstanceRights(
+      in T_LONGLONG aid,
+      in T_LONGLONG iid)
+      raises (AoException);
+
+   /** (24014)
+   * Set the access control list information for the initial rights on
+   * some application element defined by <aid>. The <usergroup_id>
+   * defines the user group the rights should be set for. <rights>
+   * defines the rights to set or to clear. If the parameter <set> is set
+   * to 'set', the rights in <rights> are set all others are cleared. If
+   * the parameter <set> is set to 'add', the rights in <rights> are
+   * added to the existing rights. If the parameter <set> is set to
+   * 'remove', the rights in <rights> are removed from the existing
+   * rights.  Restriction for the model: only one application element of
+   * the type AoUserGroup is allowed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  usergroupId  The user group to set the initial rights for.
+   *
+   * @param  rights  The new initial rights for the user group. The
+   *                 rights constants are defined in the interface
+   *                 SecurityRights. The interface definition language
+   *                 IDL does not allow to set the values of enumerations
+   *                 thus the constant definitions had to be done in an
+   *                 interface.
+   *
+   * @param  refAid  The Id of referencing application element for which
+   *                 the initial rights will be used. If no refAid is set
+   *                 the initial rights will be used for each new
+   *                 instance element independent of the application
+   *                 element.
+   *
+   * @param  set  What to do with the new initial rights.
+   */
+   void setElementInitialRights(
+      in T_LONGLONG aid,
+      in T_LONGLONG usergroupId,
+      in T_LONG rights,
+      in T_LONGLONG refAid,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24015)
+   * Set the access control list information for the initial rights on
+   * some instance defined by the application element id <aid> and a
+   * sequence of instance defined by the id <iid>. The <usergroup_id>
+   * defines the user group the rights should be set for. <rights>
+   * defines the rights to set or to clear. If the parameter <set> is set
+   * to 'set', the rights in <rights> are set all others are cleared. If
+   * the parameter <set> is set to 'add', the rights in <rights> are
+   * added to the existing rights. If the parameter <set> is set to
+   * 'remove', the rights in <rights> are removed from the existing
+   * rights.  Restriction for the model: only one application element of
+   * the type AoUserGroup is allowed.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  instIds  The sequence of instance Id's.
+   *
+   * @param  usergroupId  The user group to set the initial rights for.
+   *
+   * @param  rights  The new initial right for the user group.
+   *
+   * @param  refAid  The Id of referencing application element for which
+   *                 the initial rights will be used. If no refAid is set
+   *                 the initial rights will be used for each new
+   *                 instance element independent of the application
+   *                 element.
+   *
+   * @param  set  What to do with the new initial rights.
+   */
+   void setInstanceInitialRights(
+      in T_LONGLONG aid,
+      in S_LONGLONG instIds,
+      in T_LONGLONG usergroupId,
+      in T_LONG rights,
+      in T_LONGLONG refAid,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24016)
+   * Set the flag <set> in svcattr, if this reference will be used (or
+   * not) to retrieve the Initial Rights. If more than one reference is
+   * set to true, the union (or-function) of all rights are used.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *
+   * @param  aid  The application element Id.
+   *
+   * @param  refName  The name of the reference.
+   *
+   * @param  set  What to do with the given reference.
+   */
+   void setInitialRightReference(
+      in T_LONGLONG aid,
+      in T_STRING refName,
+      in RightsSet set)
+      raises (AoException);
+
+   /** (24017)
+   * Get all attribute names (references) which are used to retrieve the
+   * Initial Rights.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The application element Id.
+   *
+   * @return  The names of the references which will be used for the
+   *          initial rights determination.
+   */
+   NameSequence getInitialRightReference(
+      in T_LONGLONG aid)
+      raises (AoException);
+
+   /** (24018)
+   * Retrieve access control list information of the initial rights for
+   * the requested application element <aid>.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @return  The access control list entries of the given application
+   *          element for the initial rights.
+   */
+   InitialRightSequence getElementInitialRights(
+      in T_LONGLONG aid)
+      raises (AoException);
+
+   /** (24019)
+   * Retrieve access control list information of the initial rights for
+   * the requested instance <aid>/<iid>.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aid  The Id of the application element.
+   *
+   * @param  iid  The Id of the instance.
+   *
+   * @return  The access control list entries of the given instance for
+   *          the initial rights.
+   */
+   InitialRightSequence getInstanceInitialRights(
+      in T_LONGLONG aid,
+      in T_LONGLONG iid)
+      raises (AoException);
+
+   /** (24020)
+   * Perform the Query. This method can be used for a more powerful query
+   * compared to the method getInstances of this interface, with join
+   * definitions and aggregate functions.
+   * 
+   * The number of different application elements which are requested are
+   * exactly defined by the definition of the query given in the field
+   * anuSeq of the QueryStructureExt. The number of attributes for each
+   * application element is also given in the definition. The number of
+   * matching instances (their attributes) is not defined by the query
+   * and can be a large amount. Therefore only one iterator for the
+   * attribute values are defined.
+   * 
+   * The return is a sequence of the structure ResultSetExt . This
+   * sequence will always have the length of 1. This
+   * element in the structure have two fields 
+   *   - firstElems of type ElemResultSetExtSequence
+   *   - restElems of type ElemResultSetExtSeqIterator
+   * 
+   * firstElems
+   * The firstElems is a sequence of ElemResultSetExt, the length of the
+   * sequence corresponds with the number of different application
+   * elements requested in the anuSeq of the QueryStructrueExt. The
+   * structure ElemResultSetExt has the fields aid and values. The aid is
+   * the Id of the application element, the values, a sequence of the
+   * structure NameValueSeqUnitId are the values of the attributes. For
+   * each reported attribute an entry is given in the sequence, the name
+   * of the attribute is given in the field valName. The Id of the unit
+   * is given in the field unitId, this is the Id of the instance of the
+   * application element derived from the base element AoUnit. The values
+   * are given in the field value with the type TS_ValueSeq. Each value
+   * sequence has the same length, this length is maximum how_many the
+   * parameter of the method. If no values are found the length of the
+   * sequence is 0. The values with the same index in the different
+   * sequences of the entry in the NameValueSeqUnitIdSequence belongs to
+   * the same instance element. 
+   * 
+   * restElems
+   * The restElems is an iterator for the remaining sequence of
+   * ElemResultSetExt. This iterator allows to load the next N values
+   * from the ResultSet. The result of the element is the same way stored
+   * as at the field firstElems, the next N is the length of the sequence
+   * of the field value of the NameValueSeqUnitId. The method nextOne is
+   * wrong specified and should not be used, use instead the method nextN
+   * with n=1. The method getCount return the total number of found
+   * element, also the number already returned in firstElems. The method
+   * reset set the iterator the beginning of the ResultSet, this is the
+   * beginning of the firstElems.
+   * 
+   * The values of the localcolumn instances is part of the resultset
+   * when the following criteria all fit:
+   * 
+   * - Only when the attributes id, generation_parameters, values, flags
+   * are requested, as soon as any other attributes is requested the
+   * values are not reported.
+   * - The values of the localcolumn must all belong to exactly one
+   * instances of AoMeasurement
+   * - The server have a limitation of the memory, not the system memory
+   * limitation, as soon as the result set will break the limitation an
+   * exception will be thrown.
+   * - No iterator for the rest is required.
+   * 
+   * In case an attribute of blob type is among the requested attributes,
+   * the content of the return structure will depend on the number of
+   * instances that are returned:
+   * - In case attributes of only one instance are returned (either
+   * because 'how_many' was set to 1 or there is only one instance
+   * available at the server), the return structure contains the blob
+   * itself.
+   * - In case attributes of more than one instance are returned, the
+   * return structure does not contain the blobs; instead it contains the
+   * headers of the respective blobs.
+   * 
+   * The value of valName of query result values shall be the aaName in
+   * case AggrFunc='NONE' and shall be constructed for all other AggrFunc
+   * values as string concatenation of the AggrFunc value followed by a
+   * '(' character, followed by the name of attribute (aaName) followed
+   * by a ')' character.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  aoq  The query definition.
+   *
+   * @param  how_many  Maximum number of values in each result set. Valid
+   *                   arguments are: 
+   *                   how_many = 0 : report all found values,
+   *                   how_many > 0 : report a maximum number of values.
+   *
+   * @return  The result set with the requested attribute values.
+   */
+   ResultSetExtSequence getInstancesExt(
+      in QueryStructureExt aoq,
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (24021)
+   * Get the value matrix of a measurement or a submatrix. If the value
+   * matrix will be built up with special submatrix link, use the
+   * interface Measurement.
+   * The behavior of the ASAM ODS server depends on whether the
+   * referenced element is a submatrix or a measurement. For more
+   * information on the server behavior see description at the method
+   * getValueMatrixInMode() of the interfaces 'Measurement' and
+   * 'SubMatrix'.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_INVALID_BASETYPE
+   *    AO_INVALID_VALUEMATRIX_STRUCTURE
+   *
+   * @param  elem  The element id. The aid has to be the application
+   *               element Id of the AoMeasurement or AoSubmatrix.
+   *
+   * @param  vmMode  The requested mode of the value matrix.
+   *
+   * @return  The value matrix.
+   */
+   ValueMatrix getValueMatrixInMode(
+      in ElemId elem,
+      in ValueMatrixMode vmMode)
+      raises (AoException);
+
+   /** (24022)
+   * Get the ODSFile interface for an instance of an application element
+   * derived from AoFile.
+   * 
+   * This method returns an ODSFile interface.
+   * 
+   * One parameter controls the behavior of this method:
+   * The value of the parameter 'elem' (with its components 'aid' and
+   * 'iid') uniquely identifies
+   * an instance within the ODS storage. If no such instance exists, or
+   * if the instance is not
+   * an instance of an application element derived from AoFile, the
+   * exception
+   * AO_INVALID_BASETYPE is thrown.
+   * 
+   * Note that an ODS server may be set up to support the ODS security
+   * concepts and that in
+   * such case access to a file is only allowed if the access rights of
+   * the accessing user are
+   * sufficient. If the user does not have at least READ rights for the
+   * instance specified by
+   * 'elem' an exception AO_ACCESS_DENIED will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_INVALID_BASETYPE
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *
+   * @param  elem  The instance to which the file belongs, whose access
+   *               is intended.
+   *
+   * @return  The ODSFile interface to access the desired file.
+   */
+   ODSFile getODSFile(
+      in ElemId elem)
+      raises (AoException);
+
+}; // Interface ApplElemAccess.
+
+/**
+* The ASAM ODS query evaluator interface allows to perform queries in
+* synchronous mode and to create Query objects for asynchronous
+* execution.
+*/
+interface QueryEvaluator {
+
+   /** (25000)
+   * Evaluate a query in synchronous mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_QUERY_TYPE_INVALID
+   *    AO_QUERY_INVALID
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  queryStr  The query string.
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameters should be passed:
+   *                 
+   *                 Name: "MaxDuration"; 
+   *                 Type: T_LONG
+   *                 Comment: Can be used to restrict the processing
+   *                 time. The time is given in  milliseconds,
+   *                 Default value: 0 (no restriction)
+   *
+   * @return  The result of the query as an instance element iterator.
+   */
+   InstanceElementIterator getInstances(
+      in T_STRING queryStr,
+      in NameValueSequence params)
+      raises (AoException);
+
+   /** (25001)
+   * Evaluate a query in synchronous mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_QUERY_TYPE_INVALID
+   *    AO_QUERY_INVALID
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  queryStr  The query string.
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameters should be passed:
+   *                 
+   *                 Name: "MaxDuration"; 
+   *                 Type: T_LONG
+   *                 Comment: Can be used to restrict the processing
+   *                 time. The time is given in  milliseconds,
+   *                 Default value: 0 (no restriction)
+   *
+   * @return  The result of the query as a name value unit sequence
+   *          iterator. Each name value unit tuple is one cell of the
+   *          table. The name value unit sequence is one row of the
+   *          table.
+   */
+   NameValueUnitSequenceIterator getTableRows(
+      in T_STRING queryStr,
+      in NameValueSequence params)
+      raises (AoException);
+
+   /** (25002)
+   * Evaluate a query in synchronous mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_QUERY_TYPE_INVALID
+   *    AO_QUERY_INVALID
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  queryStr  The query string.
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameters should be passed:
+   *                 
+   *                 Name: "MaxDuration"; 
+   *                 Type: T_LONG
+   *                 Comment: Can be used to restrict the processing
+   *                 time. The time is given in  milliseconds,
+   *                 Default value: 0 (no restriction)
+   *
+   * @return  The result of the query as a name value sequence unit
+   *          sequence. Each name value sequence unit tuple is one column
+   *          of the table. The name value sequence unit sequence is  the
+   *          table. The result structure can be very huge.
+   */
+   NameValueSeqUnitSequence getTable(
+      in T_STRING queryStr,
+      in NameValueSequence params)
+      raises (AoException);
+
+   /** (25003)
+   * Create a query object to execute it in asynchronous mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_QUERY_TYPE_INVALID
+   *    AO_QUERY_INVALID
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  queryStr  The query string
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameters should be passed:
+   *                 
+   *                 Name: "QueryResultType"; 
+   *                 Type: ResultType.
+   *                 Comment: Specifies what kind of result is expected
+   *                 by the client.
+   *                 Default value: INSTELEM_ITERATOR_AS_RESULT
+   *                 
+   *                 Name: "MaxDuration"; 
+   *                 Type: T_LONG
+   *                 Comment: Can be used to restrict the processing
+   *                 time. The time is given in  milliseconds,
+   *                 Default value: 0 (no restriction)
+   *
+   * @return  The query object.
+   */
+   Query createQuery(
+      in T_STRING queryStr,
+      in NameValueSequence params)
+      raises (AoException);
+
+}; // Interface QueryEvaluator.
+
+/**
+* The ASAM ODS interface Query.
+*/
+interface Query {
+
+   /** (26000)
+   * Get the QueryEvaluator object which is responsible for this query.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The QueryEvaluator object which is responsible for this
+   *          query.
+   */
+   QueryEvaluator getQueryEvaluator()
+      raises (AoException);
+
+   /** (26001)
+   * Do the query pre-processing (optimization, etc.)  Call can be
+   * omitted by the client. In this case the functionality is executed on
+   * the call of executeQuery.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_INVALID_RESULTTYPE
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameters should be passed:
+   *                 
+   *                 Name: "QueryResultType"; 
+   *                 Type: ResultType.
+   *                 Comment: Specifies what kind of result is expected
+   *                 by the client, this parameter is required if the
+   *                 parameters isn't given at the method createQuery of
+   *                 the interface QueryEvaluator.
+   *                 Default value: INSTELEM_ITERATOR_AS_RESULT
+   */
+   void prepareQuery(
+      in NameValueSequence params)
+      raises (AoException);
+
+   /** (26002)
+   * Execute query in asynchronous mode.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_INVALID_RESULTTYPE
+   *
+   * @param  params  Sequence of parameter names and values. The
+   *                 following parameter should be passed:
+   *                 
+   *                 Name: "QueryResultType"; 
+   *                 Type: ResultType.
+   *                 Comment: Specifies what kind of result is expected
+   *                 by the client, this parameter is required if the
+   *                 parameters isn't given at the method prepareQuery or
+   *                 the method createQuery of the interface
+   *                 QueryEvaluator.
+   *                 Default value: INSTELEM_ITERATOR_AS_RESULT
+   *                 
+   *                 Name: "Synchronous";
+   *                 Type: T_BOOLEAN
+   *                 Comment: In case of "true" guarantees synchronous
+   *                 execution.
+   *                 Default value: "false"
+   */
+   void executeQuery(
+      in NameValueSequence params)
+      raises (AoException);
+
+   /** (26003)
+   * Return query status.
+   * 
+   * Returns INCOMPLETE if the query is still executing.
+   * 
+   * Returns COMPLETE if the query finished execution or if the query
+   * execution stopped because of an error or because the timeout was
+   * exceeded.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The status of the query.
+   */
+   QueryStatus getStatus()
+      raises (AoException);
+
+   /** (26004)
+   * Get the query result. This method should only be called after the
+   * query has been executed. It returns an iterator on the instances
+   * that were found by the query.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_QUERY_INCOMPLETE
+   *    AO_QUERY_INVALID_RESULTTYPE
+   *
+   * @return  The result of the query as an instance element iterator.
+   */
+   InstanceElementIterator getInstances()
+      raises (AoException);
+
+   /** (26005)
+   * Get the query result. This method should only be called after the
+   * query has been executed. It returns an iterator on the name value
+   * unit sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_QUERY_INCOMPLETE
+   *    AO_QUERY_INVALID_RESULTTYPE
+   *
+   * @return  The result of the query as a name value unit sequence
+   *          iterator. Each name value unit tuple is one cell of the
+   *          table. The name value unit sequence is one row of the
+   *          table.
+   */
+   NameValueUnitSequenceIterator getTableRows()
+      raises (AoException);
+
+   /** (26006)
+   * Get the query result. This method should only be called after the
+   * query has been executed. It returns the result as an structure.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_QUERY_PROCESSING_ERROR
+   *    AO_QUERY_TIMEOUT_EXCEEDED
+   *    AO_QUERY_INCOMPLETE
+   *    AO_QUERY_INVALID_RESULTTYPE
+   *
+   * @return  The result of the query as a name value sequence unit
+   *          sequence. Each name value sequence unit tuple is one column
+   *          of the table. The name value sequence unit sequence is  the
+   *          table. The result structure can be very huge.
+   */
+   NameValueSeqUnitSequence getTable()
+      raises (AoException);
+
+}; // Interface Query.
+
+/**
+* The name value unit sequence iterator. The table iterator as query
+* result.
+*/
+interface NameValueUnitSequenceIterator {
+
+   /** (27001)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (27002)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (27003)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n values of the name-value-unit  sequence. For
+   *          each NameValuUnit the next n values are stored in the value
+   *          sequence.
+   */
+   NameValueSeqUnitSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (27004)
+   * Get the next element from the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next name-value-unit tuple sequence from the
+   *          name-value-unit tuple.
+   */
+   NameValueSeqUnit nextOne()
+      raises (AoException);
+
+   /** (27005)
+   * Reset the pointer in the element iterator to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface NameValueUnitSequenceIterator.
+
+/**
+* The ASAM ODS enumeration interface.
+*/
+interface EnumerationDefinition {
+
+   /** (28000)
+   * List the possible names of the enumeration. The sort order of the
+   * list is the value of the item. The first item has the value zero.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  List with all possible names of the enumeration items.
+   */
+   NameSequence listItemNames()
+      raises (AoException);
+
+   /** (28001)
+   * Get the value of an item.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @param  itemName  The name of the item.
+   *
+   * @return  The number of the item.
+   */
+   T_LONG getItem(
+      in T_STRING itemName)
+      raises (AoException);
+
+   /** (28002)
+   * Get the name of an item.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @param  item  The value of the item.
+   *
+   * @return  The name of the item.
+   */
+   T_STRING getItemName(
+      in T_LONG item)
+      raises (AoException);
+
+   /** (28003)
+   * Add a new item to the enumeration. This method modifies the
+   * application model and is only allowed for the super user.
+   * 
+   * The name of an item must not exceed the maximum name length of the
+   * underlying physical storage. Current server implementations restrict
+   * it to 128 characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *    AO_DUPLICATE_NAME
+   *    AO_DUPLICATE_VALUE
+   *
+   * @param  itemName  The name of the new item.
+   */
+   void addItem(
+      in T_STRING itemName)
+      raises (AoException);
+
+   /** (28004)
+   * Rename the item of the enumeration. This method modifies the
+   * application model and is only allowed for the super user.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_NOT_FOUND
+   *
+   * @param  oldItemName  The existing name of the item.
+   *
+   * @param  newItemName  the new name of the item.
+   */
+   void renameItem(
+      in T_STRING oldItemName,
+      in T_STRING newItemName)
+      raises (AoException);
+
+   /** (28005)
+   * Get the name of the enumeration.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Name of the enumeration.
+   */
+   T_STRING getName()
+      raises (AoException);
+
+   /** (28006)
+   * Set the name of the enumeration. This method modifies the
+   * application model and is only allowed for the super user.
+   * 
+   * The name of an enumeration definition must not exceed the maximum
+   * name length of the underlying physical storage. Current server
+   * implementations restrict it to 30 characters.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_TRANSACTION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *
+   * @param  enumName  Name of the enumeration.
+   */
+   void setName(
+      in T_STRING enumName)
+      raises (AoException);
+
+   /** (28007)
+   * Get the index of the enumeration.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_BAD_PARAMETER
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The index of the enumeration.
+   */
+   T_LONG getIndex()
+      raises (AoException);
+
+}; // Interface EnumerationDefinition.
+
+/**
+* For iteration through the result elements, there is also a new iterator
+* necessary called ElemResultSetExtSeqIterator. ItÂ’s functionality is
+* still the same as all other iterators and needs therefore no further
+* explanation.
+* There is only one difference to the other iterations. The iteration is
+* done on the lowest level in that case on the TS_UnionSeq.
+*/
+interface ElemResultSetExtSeqIterator {
+
+   /** (29000)
+   * Destroy the iterator and free the associated memory.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void destroy()
+      raises (AoException);
+
+   /** (29001)
+   * Get the total number of elements accessible by the iterator.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The number of elements accessible by the iterator.
+   */
+   T_LONG getCount()
+      raises (AoException);
+
+   /** (29002)
+   * Get the next n elements from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @param  how_many  The number of requested elements.
+   *
+   * @return  The next n attribute values from the element result set
+   *          sequence.
+   */
+   ElemResultSetExtSequence nextN(
+      in T_LONG how_many)
+      raises (AoException);
+
+   /** (29003)
+   * Get the next  element from the sequence.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The next attribute values from the element result set
+   *          sequence.
+   */
+   ElemResultSetExt nextOne()
+      raises (AoException);
+
+   /** (29004)
+   * Reset the pointer in the element sequence to the first element.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void reset()
+      raises (AoException);
+
+}; // Interface ElemResultSetExtSeqIterator.
+
+/**
+* The interface ODSFile extends the interface InstanceElement. Thus all
+* methods of the interface InstanceElement do also work here. 
+* 
+* ODSFile allows to create a file that is under control of the ODS server
+* (a 'managed file'). ODSFile furthermore allows read, write, append or
+* remove operations to a managed file.
+* 
+* General information of the file can be retrieved from this interface as
+* well. Note, that no random access on a file is provided; only a
+* sequential read and a write by appending at the end is possible.
+* 
+* Replacing an existing file by a new one requires to first remove the
+* old one and then create the new one.
+*/
+interface ODSFile : InstanceElement {
+
+   /** (30000)
+   * Get the ODSWriteTransfer interface for the file, to allow appending
+   * further bytes to the file.
+   * 
+   * This method returns the ODSWriteTransfer interface for the file
+   * represented by this ODSFile object. That interface allows to write
+   * sequentially to the file, beginning at the end of the currently
+   * existing file.
+   * Before returning the interface ODSWriteTransfer, the physical file
+   * will be opened for subsequent write operations.
+   * 
+   * In case the current user has no UPDATE right for the instance (resp.
+   * for all of its attributes in case of attribute security) from which
+   * this ODSFile object was created, the exception AO_ACCESS_DENIED will
+   * be thrown.
+   * 
+   * In case the physical file referenced by this ODSFile object cannot
+   * be found, the exception AO_BAD_OPERATION will be thrown.
+   * 
+   * In case the physical file referenced by this ODSFile object is
+   * currently opened by an ODSReadTransfer or an ODSWriteTransfer
+   * object, the exception AO_FILE_LOCKED will be thrown.
+   * 
+   * In case the file cannot be opened for writing the exception
+   * AO_SYSTEM_PROBLEM will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_FILE_LOCKED
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @return  The ODSWriteTransfer interface to append to the file.
+   */
+   ODSWriteTransfer append()
+      raises (AoException);
+
+   /** (30001)
+   * Check whether the file may be opened for reading.
+   * 
+   * This method checks whether the file represented by this ODSFile
+   * object may be opened by the ODS server for reading access.
+   * 
+   * The method returns a boolean TRUE in case the file may be opened for
+   * reading, and a boolean FALSE in case it cannot be opened for reading
+   * or it is already opened for write access (i.e. an ODSWriteTransfer
+   * object for this file exists).
+   * 
+   * In case the physical file referenced by this ODSFile object cannot
+   * be found, false will be returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Information about whether the file can be opened for
+   *          reading
+   */
+   T_BOOLEAN canRead()
+      raises (AoException);
+
+   /** (30002)
+   * Check whether the file may be opened for writing.
+   * 
+   * This method checks whether the file represented by this ODSFile
+   * object may be opened by the ODS server for writing access.
+   * 
+   * The method returns a boolean TRUE in case the user has appropriate
+   * rights and the file can be opened for writing, and a boolean FALSE
+   * in case it is already opened for write access (i.e. an
+   * ODSWriteTransfer object for this file exists) or for read access
+   * (i.e. one or more ODSReadTransfer objects for this file exist).
+   * 
+   * In case ao_location is defined and the current user has no UPDATE
+   * right for the instance from which this ODSFile object was created, a
+   * boolean FALSE will be returned.
+   * 
+   * In case ao_location is undefined and the current user has no INSERT
+   * right for the instance from which this ODSFile object was created, a
+   * boolean FALSE will be returned.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Information about whether the file can be opened for
+   *          writing
+   */
+   T_BOOLEAN canWrite()
+      raises (AoException);
+
+   /** (30003)
+   * Create a new file at the ODS server and get the ODSWriteTransfer
+   * interface for that file, to allow storing bytes to the file.
+   * 
+   * This method returns the ODSWriteTransfer interface for the file
+   * represented by this ODSFile object. That interface allows to write
+   * sequentially to the (initially empty) file. 
+   * 
+   * Before returning the interface ODSWriteTransfer, the physical file
+   * will be created at the ODS server and opened for subsequent write
+   * operations. The file name will be decided by the ODS server and set
+   * as value of the attribute derived from the base attribute
+   * 'ao_location' of the instance from which this ODSFile object was
+   * created.
+   * 
+   * In case the current user has no INSERT right for the instance from
+   * which this ODSFile object was created, the exception
+   * AO_ACCESS_DENIED will be thrown.
+   * 
+   * If the attribute derived from 'ao_location' of the instance from
+   * which this ODSFile object was created already has a value, the
+   * instance potentially already references a file which was not yet
+   * removed, and the server will check whether that former file still
+   * exists. If so the exception AO_BAD_OPERATION will be thrown and no
+   * new file will be created.
+   * 
+   * In case the file cannot be opened for writing the exception
+   * AO_SYSTEM_PROBLEM will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_ACCESS_DENIED
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @return  The ODSWriteTransfer interface to a new file.
+   */
+   ODSWriteTransfer create()
+      raises (AoException);
+
+   /** (30004)
+   * Check whether the file physically exists at the ODS server.
+   * 
+   * This method checks whether the file represented by this ODSFile
+   * object truly exists at the expected location (e.g. on a specific
+   * drive/directory) within reach of  the ODS server.
+   * 
+   * The method returns a boolean TRUE in case the file exists, and a
+   * boolean FALSE in case it does not exist.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  Information about whether the file exists.
+   */
+   T_BOOLEAN exists()
+      raises (AoException);
+
+   /** (30005)
+   * Get the date of the file.
+   * This method returns the date of the file represented by this ODSFile
+   * object. The returned string follows the rules for ODS date and time
+   * specification strings.
+   * The date returned shall specify the timestamp of the latest change
+   * of the file. It is the information the operating system of the ODS
+   * server provides; if there is no date available from the operating
+   * system with exactly this meaning, the ODS server shall return the
+   * closest information available.
+   * In case the physical file referenced by this ODSFile object cannot
+   * be found, the exception AO_SYSTEM_PROBLEM will be thrown.
+   * In case the physical file referenced by this ODSFile object is
+   * currently opened by an ODSWriteTransfer object of another session,
+   * the exception AO_FILE_LOCKED will be thrown.
+   * In case there is no file defined by the attribute derived from
+   * 'ao_location', the exception AO_BAD_OPERATION will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *    AO_FILE_LOCKED
+   *
+   * @return  The date of last change of the file represented by this
+   *          ODSFile object.
+   */
+   T_DATE getDate()
+      raises (AoException);
+
+   /** (30006)
+   * Get the size of the file.
+   * This method returns the size of the file represented by this ODSFile
+   * object. 
+   * The returned value shall specify the exact file size in bytes. It is
+   * the information the operating system of the ODS server provides.
+   * In case the physical file referenced by this ODSFile object cannot
+   * be found, the exception AO_SYSTEM_PROBLEM will be thrown.
+   * In case there is no file defined by the attribute derived from
+   * 'ao_location', the exception AO_BAD_OPERATION will be thrown.
+   * In case the physical file referenced by this ODSFile object is
+   * currently opened by an ODSWriteTransfer object of another session,
+   * the exception AO_FILE_LOCKED will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_FILE_LOCKED
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @return  The size in bytes of the file represented by this ODSFile
+   *          object.
+   */
+   T_LONGLONG getSize()
+      raises (AoException);
+
+   /** (30007)
+   * Remove a file from the ODS server.
+   * This method removes the file represented by this ODSFile object from
+   * the ODS server if the user has appropriate rights. The attribute
+   * derived from the base attribute 'ao_location' of the instance from
+   * which this ODSFile object was created will become undefined and
+   * ao_size will be set to 0.
+   * In case the current user has no DELETE right for the instance from
+   * which this ODSFile object was created, the exception
+   * AO_ACCESS_DENIED will be thrown.
+   * In case the file is currently opened for write access (i.e. an
+   * ODSWriteTransfer object for this file exists) or for read access
+   * (i.e. one or more ODSReadTransfer objects for this file exist) an
+   * exception AO_FILE_LOCKED will be thrown.
+   * In case the physical file referenced by this ODSFile object does not
+   * exist, the method will return without any further file action; it
+   * will set the attribute derived from the base attribute 'ao_location'
+   * to undefined and 'ao_size' to 0; it will not throw an exception to
+   * signal the non-existence of the file.
+   * In case the file cannot be physically deleted from its location, the
+   * exception AO_SYSTEM_PROBLEM will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_FILE_LOCKED
+   *    AO_ACCESS_DENIED
+   *    AO_SYSTEM_PROBLEM
+   */
+   void remove()
+      raises (AoException);
+
+   /** (30008)
+   * Get the ODSReadTransfer interface for the file.
+   * This method returns the ODSReadTransfer interface for the file
+   * represented by this ODSFile object. That interface allows to read
+   * sequentially from the file, either starting at the very beginning or
+   * at a user-specified byte location within the file.
+   * Before returning the interface ODSReadTransfer, the physical file
+   * will be opened for reading.
+   * In case the physical file referenced by this ODSFile object is
+   * currently opened by an ODSWriteTransfer object, the exception
+   * AO_FILE_LOCKED will be thrown.
+   * In case there is no file defined by the attribute derived from
+   * 'ao_location', the exception AO_BAD_OPERATION will be thrown.
+   * In case the attribute derived from 'ao_location' is defined but the
+   * physical file referenced by this ODSFile object cannot be found or
+   * cannot be opened for reading, the exception AO_SYSTEM_PROBLEM will
+   * be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_FILE_LOCKED
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @return  The ODSReadTransfer interface to read from the file.
+   */
+   ODSReadTransfer read()
+      raises (AoException);
+
+   /** (30009)
+   * Put a file that is already residing within reach of the ODS server
+   * under control of the ODS server.
+   * This method allows to put files under control of the ODS server
+   * (make them a 'managed file') without the need to stream their bytes
+   * through the ODSWriteTransfer interface.
+   * The parameter 'sourceUrl' specifies the location of the file that
+   * shall become a managed file. This location must reference a file
+   * which is accessible by the server. The server will move the file to
+   * a location where managed files reside and give it a name of its own
+   * choice; the file will no longer exist at its previous location. The
+   * server will store file name and location in the attribute derived
+   * from 'ao_location' and store the size of the file in the attribute
+   * derived from 'ao_size'.
+   * The string value of 'sourceUrl' must comply to the URL specification
+   * given in RFC 2396 with the restriction that ASAM ODS only supports
+   * absolute URLs with the access scheme "file:", otherwise the
+   * exception AO_BAD_PARAMETER  will be thrown.
+   * In case there is no file defined by the attribute derived from
+   * 'ao_location', the exception AO_BAD_OPERATION will be thrown.
+   * In case the file cannot be physically moved from its original
+   * location to a server-location where managed files reside, the
+   * exception AO_SYSTEM_PROBLEM will be thrown (e.g. if the file
+   * specified by 'sourceUrl' does not exist, or if it cannot be
+   * physically moved, etc.).
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_PARAMETER
+   *    AO_BAD_OPERATION
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @param  sourceUrl  Filename URL of the file to take under control as
+   *                    a managed file.
+   */
+   void takeUnderControl(
+      in T_STRING sourceUrl)
+      raises (AoException);
+
+   /** (30010)
+   * Remove a file that is currently under control of the ODS server out
+   * of control of the server and move it to a specified location within
+   * reach of the server.
+   * This method allows to take files out of control of the ODS server
+   * and place them at a specified location, without the need to stream
+   * their bytes through the ODSReadTransfer interface.
+   * The parameter 'targetUrl' specifies the location to which the
+   * currently managed file shall be moved. This location must be
+   * accessible by the server. The server will move the file from the
+   * location where managed files reside to the location given by
+   * 'targetUrl'; the file will no longer exist at its previous location.
+   * The server will set the value of the attribute derived from
+   * 'ao_location' to undefined and of the attribute derived from
+   * 'ao_size' to 0.
+   * The string value of 'targetUrl' must comply to the URL specification
+   * given in RFC 2396 with the restriction that ASAM ODS only supports
+   * absolute URLs with the access scheme "file:"; otherwise the
+   * exception AO_BAD_PARAMETER  will be thrown.
+   * In case the file specified by 'targetUrl' already exists the
+   * exception AO_BAD_PARAMETER will be thrown and no action will be
+   * performed by this method.
+   * In case the file specified by 'targetUrl' cannot be physically moved
+   * to the intended location, the exception AO_SYSTEM_PROBLEM will be
+   * thrown and no action will be performed by this method.
+   * In case the file referenced by this ODSFile object is currently
+   * opened for write access (i.e. an ODSWriteTransfer object for this
+   * file exists) or for read access (i.e. one or more ODSReadTransfer
+   * objects for this file exist) an exception AO_FILE_LOCKED will be
+   * thrown and no action will be performed by this method.
+   * In case there is no file defined by the attribute derived from
+   * 'ao_location', the exception AO_BAD_OPERATION will be thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_PARAMETER
+   *    AO_FILE_LOCKED
+   *    AO_SYSTEM_PROBLEM
+   *    AO_BAD_OPERATION
+   *    AO_BAD_PARAMETER
+   *
+   * @param  targetUrl  Filename URL of the file where to move the
+   *                    managed file.
+   */
+   void removeFromControl(
+      in T_STRING targetUrl)
+      raises (AoException);
+
+}; // Interface ODSFile.
+
+/**
+* The interface which allows a read transfer (from the ODS server to a
+* client) of the content of a file that is under control of the ODS
+* server.
+*/
+interface ODSReadTransfer {
+
+   const T_LONG READALL = -1; // Read all bytes of the file.
+
+   /** (31000)
+   * Close this ODSReadTransfer interface.
+   * 
+   * This method closes the file on the ODS server's file system and
+   * destroys this ODSReadTransfer object.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void close()
+      raises (AoException);
+
+   /** (31001)
+   * Read a sequence of bytes from the file.
+   * This method reads the file at the ODS server referenced by this
+   * ODSReadTransfer and returns a sequence of bytes from that file.
+   * 
+   * The parameter 'maxOctets' controls the return behavior of the ODS
+   * server. If the file contains more bytes than are given by
+   * 'maxOctets', only 'maxOctets' bytes will be returned in the first
+   * method invocation. A subsequent method invocation will return the
+   * next 'maxOctets' bytes from the file, etc., until the complete file
+   * contents has been returned. Further method invocations return an
+   * empty sequence.
+   * 
+   * If 'maxOctets' is given with a equal to the constant READALL(-1),
+   * there is no restriction on the number of bytes, and the complete
+   * file contents will be returned with only one method invocation.
+   * 
+   * Note that only a sequential reading, starting at the first byte of
+   * the file, is supported by this interface. If previous parts of the
+   * file need to be accessed again, the current ODSReadTransfer object
+   * must be closed and a new one must be instantiated.
+   * 
+   * In case the parameter 'maxOctets' is negative other then the
+   * constant READALL the exception AO_BAD_PARAMETER is thrown.
+   * 
+   * In case there is any problem reading the file, the exception
+   * AO_SYSTEM_PROBLEM is thrown.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_SYSTEM_PROBLEM
+   *    AO_BAD_PARAMETER
+   *
+   * @param  maxOctets  The maximum number of bytes to be returned by one
+   *                    method call.
+   *
+   * @return  The next (at most 'maxOctets') bytes in the file.
+   */
+   S_BYTE getOctetSeq(
+      in T_LONG maxOctets)
+      raises (AoException);
+
+   /** (31002)
+   * Skip a number of bytes while reading the file.
+   * This method moves the read pointer in the file a number of bytes
+   * ahead, starting at its current position; it will not return those
+   * bytes. The parameter 'numOctets' specifies the number of bytes to
+   * skip.
+   * 
+   * The method returns the true number of bytes that were skipped. This
+   * may differ from 'numOctets' e.g. if the end of the file was reached.
+   * If the read pointer has reached the end of the file any further
+   * method invocations will return a value of 0 for 'numSkipped'.
+   * 
+   * This method may be invoked several times and may be arbitrarily
+   * combined with getOctetSeq().
+   * 
+   * Note that only a sequential reading, starting at the first byte of
+   * the file, is supported by this interface. If previous parts of the
+   * file need to be accessed again, the current ODSReadTransfer object
+   * must be closed and a new one must be instantiated.
+   * 
+   * If 'numOctets' is given with a value less than 0, the method will
+   * throw the exception AO_BAD_PARAMETER and will not perform any file
+   * access nor change the read pointer.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_BAD_PARAMETER
+   *
+   * @param  numOctets  The number of bytes to be skipped.
+   *
+   * @return  the real number of bytes skipped in the file.
+   */
+   T_LONGLONG skipOctets(
+      in T_LONGLONG numOctets)
+      raises (AoException);
+
+   /** (31003)
+   * Retrieve the current position of the read pointer in the file.
+   * 
+   * This method returns the current byte position of the file pointer.
+   * The start of the file corresponds to a position of 0.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The current position of the read pointer in the file.
+   */
+   T_LONGLONG getPosition()
+      raises (AoException);
+
+}; // Interface ODSReadTransfer.
+
+/**
+* The interface which allows a write transfer (from a client to the ODS
+* server) of the content of a file that is under control of the ODS
+* server.
+*/
+interface ODSWriteTransfer {
+
+   /** (32000)
+   * Close this ODSWriteTransfer interface.
+   * This method closes the file on the ODS server's file system; thereby
+   * any data to be written to the file and still residing in ODS server
+   * cache will be flushed to the file. 
+   * The method finally destroys this ODSWriteTransfer object and also
+   * the corresponding CORBA object. Access to such objects after having
+   * invoked this close method will lead to a CORBA exception.
+   * In case the file creation and/or write operations have been
+   * performed within a transaction, this method will not yet save the
+   * operations' results permanently at the physical file location but
+   * keep them in intermediate storage until the transaction is
+   * committed. The file will be locked for any access through
+   * ODSReadTransfer or ODSWriteTransfer within any other session until
+   * the end of the transaction.
+   * Any subsequent read transfers or write transfers within the same
+   * transaction are allowed, and will work on the latest version of the
+   * file. In case the transaction is committed without a preceding close
+   * operation the ODSWriteTransfer will be closed automatically by the
+   * server.
+   * In case the file creation and/or write operations have been
+   * performed outside a transaction, this method will make all changes
+   * permanent.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   */
+   void close()
+      raises (AoException);
+
+   /** (32001)
+   * Write a sequence of bytes to the file.
+   * This method writes a sequence of bytes to the file at the ODS server
+   * represented by this ODSWriteTransfer. 
+   * 
+   * The parameter 'buffer' contains the byte sequence that is to be
+   * written to the file. The contents of 'buffer' will be appended at
+   * the end of the file (which may also be the very start of the file in
+   * case the file was newly created), and subsequent method invocations
+   * will add their bytes at the then actual end of the file.
+   * 
+   * Note that only a sequential writing is supported by this interface.
+   * If previous parts of the file need to be changed, the file must be
+   * removed and a new one must be created.
+   * 
+   * In case the current location of the file runs out of memory or any
+   * other operating system problem occurs the ODS server will return the
+   * exception AO_SYSTEM_PROBLEM. In this case the results of the actual
+   * putOctetSeq() invocation will be undone (no byte of 'buffer' is
+   * added to the file) and the file may be closed without containing
+   * 'buffer' at its end.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *    AO_NO_MEMORY
+   *    AO_SYSTEM_PROBLEM
+   *
+   * @param  buffer  The buffer containing the sequence of bytes that
+   *                 shall be written to the file.
+   */
+   void putOctectSeq(
+      in S_BYTE buffer)
+      raises (AoException);
+
+   /** (32002)
+   * Retrieve the current position of the write pointer in the file.
+   * 
+   * This method returns the current byte position of the write pointer.
+   * The start of the file corresponds to a position of 0.
+   *
+   * @throws AoException
+   * with the following possible error codes:
+   *    AO_CONNECTION_LOST
+   *    AO_IMPLEMENTATION_PROBLEM
+   *    AO_NOT_IMPLEMENTED
+   *    AO_NO_MEMORY
+   *    AO_SESSION_NOT_ACTIVE
+   *
+   * @return  The current position of the write pointer in the file.
+   */
+   T_LONGLONG getPosition()
+      raises (AoException);
+
+}; // Interface ODSWriteTransfer.
+
+}; // Module ods.
+
+}; // Module asam.
+
+}; // Module org.
+
+
+#endif
+
+/**
+* The ASAM ODS error codes.
+*
+* AO_ACCESS_DENIED
+* The ODS server denied the access.
+*
+* AO_BAD_OPERATION
+* A method was called which is not possible for the current state.
+*
+* AO_BAD_PARAMETER
+* A parameter of wrong type or value was passed to the method. The
+* minorCode tells which parameter (1, 2, 3 or 4) is bad. If more than one
+* parameter is bad, only the first one is reported.
+*
+* AO_CONNECTION_LOST
+* Due to a hardware or network software problem the connection to the
+* server was lost.
+*
+* AO_CONNECT_FAILED
+* The connect to a server failed. This error may occur if the server is
+* down or currently unreachable.
+*
+* AO_CONNECT_REFUSED
+* The connection was refused by the server. This error may occur if the
+* presented authentication information is either incorrect or incomplete.
+* This error shall not occur if the server does not accept any more
+* sessions due to overload problems. See AO_SESSION_LIMIT_REACHED for
+* this case.
+*
+* AO_DUPLICATE_BASE_ATTRIBUTE
+* Any application element may have only one base attribute of a certain
+* type. This means it may have only one attribute of base attribute type
+* NAME, one ID, one VERSION and so on.
+*
+* AO_DUPLICATE_NAME
+* The implicit or explicit specified name is already in use but it is
+* required to be unique.
+*
+* AO_DUPLICATE_VALUE
+* The attribute is marked unique in the application model. Thus duplicate
+* values are not allowed.
+*
+* AO_FILE_LOCKED
+* The kind of access to a managed file that was requested cannot be
+* granted, as the file is currently in use by another read or write
+* transfer through the OO-API.
+*
+* AO_HAS_BASE_ATTRIBUTE
+* Base attribute found. It is not allowed to modify the datatype, unique-
+* or obligatory flag .
+*
+* AO_HAS_BASE_RELATION
+* Base relation found. It is not allowed to modify the relationtype,
+* -range or -ship of an application relation derived from a base
+* relation.
+*
+* AO_HAS_INSTANCES
+* The operation is not allowed for elements that have instances.
+*
+* AO_HAS_REFERENCES
+* The requested operation is not permitted because the target element has
+* references.
+*
+* AO_IMPLEMENTATION_PROBLEM
+* This error is reserved for the reporting of implementation specific
+* problems that are not properly handled by the standard error
+* definitions. An application should not crash if this error occurs but
+* there is no way to react to this error other than reporting and
+* ignoring
+* it. The intend of this error is not to leave implementation specific
+* errors unreported.
+*
+* AO_INCOMPATIBLE_UNITS
+* The units are incompatible. No conversion rule is known.
+*
+* AO_INVALID_ASAM_PATH
+* The specified Asam path is invalid.
+*
+* AO_INVALID_ATTRIBUTE_TYPE
+* The requested attribute type is invalid.
+*
+* AO_INVALID_BASETYPE
+* The specified base type is invalid. The following basetypes are
+* allowed:
+*    AoAny
+*    AoAttributeMap
+*    AoEnvironment
+*    AoFile
+*    AoLocalColumn
+*    AoLog
+*    AoMeasurement
+*    AoMeasurementQuantity
+*    AoNameMap
+*    AoParameter
+*    AoParameterSet
+*    AoPhysicalDimension
+*    AoQuantity
+*    AoQuantityGroup
+*    AoSubmatrix
+*    AoSubTest
+*    AoTest
+*    AoTestDevice
+*    AoTestEquipment
+*    AoTestEquipmentPart
+*    AoTestSequence
+*    AoTestSequencePart
+*    AoUnit
+*    AoUnitGroup
+*    AoUnitUnderTest
+*    AoUnitUnderTestPart
+*    AoUser
+*    AoUserGroup
+*
+* AO_INVALID_BASE_ELEMENT
+* The base element is invalid in this context. If this is an element of
+* type measurement, another element of this type may already exist.
+*
+* AO_INVALID_BUILDUP_FUNCTION
+* The specified build-up function is invalid.
+*
+* AO_INVALID_COLUMN
+* The specified column is invalid.
+*
+* AO_INVALID_COUNT
+* The specified number of points is invalid (probably negative).
+*
+* AO_INVALID_DATATYPE
+* The datatype is not allowed in the given context or it conflicts with
+* an existing datatype definition.
+* 
+* This error may also occur in non-typesave language bindings. To avoid
+* this error in all language bindings it is recommended to use always the
+* definitions of the enumeration "DataType".
+*
+* AO_INVALID_ELEMENT
+* The element is invalid in this context.
+*
+* AO_INVALID_LENGTH
+* The given length is invalid. Negative length values are not allowed.
+*
+* AO_INVALID_ORDINALNUMBER
+* The ordinal number is either already used or less than zero.
+*
+* AO_INVALID_RELATION
+* The relation is invalid. The related elements and the base relation do
+* not fit.
+*
+* AO_INVALID_RELATIONSHIP
+* This error may occur only in non-typesave language bindings. To avoid
+* this error in all language bindings it is recommended to use always the
+* definitions of the enumeration "Relationship".
+*
+* AO_INVALID_RELATION_RANGE
+* The specified relation range is invalid.
+*
+* AO_INVALID_RELATION_TYPE
+* This error may occur only in non-typesave language bindings. To avoid
+* this error in all language bindings it is recommended to use always the
+* definitions of the enumeration "RelationType".
+*
+* AO_INVALID_SET_TYPE
+* The specified set-type is invalid.
+*
+* AO_INVALID_SMATLINK
+* The submatrix link is invalid. Either submatrix 1 or 2 is not specified
+* or the ordinal number is missing when there is more than one SMatLink.
+*
+* AO_INVALID_SUBMATRIX
+* The specified submatrix is invalid.
+*
+* AO_INVALID_VALUEMATRIX_STRUCTURE
+* The server is unable to create the valuematrix due to the data of the
+* measurement
+*      - if there are no independent column
+*      - if there are different independent columns
+*      - if there are submatrices with more than one independent
+*        column.
+*      - ..
+*
+* AO_IS_BASE_ATTRIBUTE
+* The application attribute is already of a base attribute type. It can
+* not be changed. If this is required, the application attribute has to
+* be removed from its application element and re-created. This error may
+* occur if an application attribute derived from a base attribute
+* 
+*    a. shall be overwritten by another base
+*       attribute type.
+*    b. shall receive another datatype.
+*    c. shall receive another unique-flag.
+*    d. shall receive another obligatory-flag.
+*
+* AO_IS_BASE_RELATION
+* Properties of base relations may not be changed.
+*
+* AO_IS_MEASUREMENT_MATRIX
+* The matrix is a complex, generated matrix from a measurement not just a
+* simple submatrix. It is only allowed to modify submatrices but not the
+* composed measurement matrices.
+*
+* AO_MATH_ERROR
+* A computation error occurred. This can be an overflow, an underflow or
+* a division by zero.
+*
+* AO_MISSING_APPLICATION_ELEMENT
+* A required application element is missing.
+*
+* AO_MISSING_ATTRIBUTE
+* A required (obligatory) attribute is missing.
+*
+* AO_MISSING_RELATION
+* A required relation is missing.
+*
+* AO_MISSING_VALUE
+* An obligatory value is missing.
+*
+* AO_NOT_FOUND
+* The requested element was not found. This error occurs only in remove
+* or rename operations if the subject of the operation is not found. All
+* get- and list-methods return an empty list if the requested item is not
+* found.
+*
+* AO_NOT_IMPLEMENTED
+* The requested method is not yet implemented. This error is not allowed
+* to occur in a certified implementation. It is intended to allow partial
+* operational tests. during the development process.
+*
+* AO_NOT_UNIQUE
+* This error occurs if the instances of a property are required to be
+* unique.
+*
+* AO_NO_MEMORY
+* No more volatile memory available.
+*
+* AO_NO_PATH_TO_ELEMENT
+* A free-floating element was detected. No navigation path leads to this
+* element.
+*
+* AO_NO_SCALING_COLUMN
+* The column is no scaling column.
+*
+* AO_OPEN_MODE_NOT_SUPPORTED
+* The requested open mode is not supported. Valid open modes are "read"
+* and "write". Anything else is rejected with this error and no session
+* is created.
+*
+* AO_QUERY_INCOMPLETE
+* The execution of the query was not yet completed.
+*
+* AO_QUERY_INVALID
+* Some error in the query string or some inconsistency between the return
+* type of the query string and the  result type specified by parameter
+* "QueryResultType".
+*
+* AO_QUERY_INVALID_RESULTTYPE
+* The requested result type of the query do no metch with the previous
+* definition of the result type.
+*
+* AO_QUERY_PROCESSING_ERROR
+* Some error occured during the execution of the query.
+*
+* AO_QUERY_TIMEOUT_EXCEEDED
+* It was not possible to execute the query within the  time limit set by
+* parameter "MaxDuration".
+*
+* AO_QUERY_TYPE_INVALID
+* The server does not support the specified query language type.
+*
+* AO_SESSION_LIMIT_REACHED
+* The server does not accept any new connections. This error may occur if
+* the server reached the session limit for a distinct user or the total
+* number of sessions allowed.
+*
+* AO_SESSION_NOT_ACTIVE
+* The session is no longer active. This error occurs if an attempt is
+* made to call a method of a closed session. This error shall not be
+* confused with the error AO_CONNECTION_LOST.
+*
+* AO_SYSTEM_PROBLEM
+* The ODS server detected a problem while accessing operating system
+* ressources (e.g. the specified file does not exist, the drive is
+* currently not available, ...).
+*
+* AO_TRANSACTION_ALREADY_ACTIVE
+* There may be only one active transaction at one time. If this error
+* occurs there is already an active transaction. That transaction remains
+* active in case of this error.
+*
+* AO_TRANSACTION_NOT_ACTIVE
+* Write operation have to be done always in the context of a transaction.
+* This error occurs if no transaction is active during a write operation.
+*
+* AO_UNKNOWN_ERROR
+* Use the zero as unknown error to avoid confusing error messages if no
+* error code has been set.
+*
+* AO_UNKNOWN_UNIT
+* The unit is unknown.
+*/
+
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEvent.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEvent.java
new file mode 100644
index 0000000..6f180f3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEvent.java
@@ -0,0 +1,52 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEvent.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public final class AvalonNotificationCorbaEvent implements org.omg.CORBA.portable.IDLEntity
+{
+
+  /**
+  * The mode of the event.
+  */
+  public short mode = (short)0;
+
+  /**
+  * The Id of the application element.
+  */
+  public org.asam.ods.T_LONGLONG aeId = null;
+
+  /**
+  * The Id of the instance.
+  */
+  public org.asam.ods.T_LONGLONG ieId = null;
+
+  /**
+  * The Id of the AoUser instance.
+  */
+  public org.asam.ods.T_LONGLONG userId = null;
+
+  /**
+  * The timestamp of the event.
+  */
+  public String timestamp = null;
+
+  public AvalonNotificationCorbaEvent ()
+  {
+  } // ctor
+
+  public AvalonNotificationCorbaEvent (short _mode, org.asam.ods.T_LONGLONG _aeId, org.asam.ods.T_LONGLONG _ieId, org.asam.ods.T_LONGLONG _userId, String _timestamp)
+  {
+    mode = _mode;
+    aeId = _aeId;
+    ieId = _ieId;
+    userId = _userId;
+    timestamp = _timestamp;
+  } // ctor
+
+} // class AvalonNotificationCorbaEvent
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHelper.java
new file mode 100644
index 0000000..16cb18a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHelper.java
@@ -0,0 +1,103 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+abstract public class AvalonNotificationCorbaEventHelper
+{
+  private static String  _id = "IDL:com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEvent:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  private static boolean __active = false;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      synchronized (org.omg.CORBA.TypeCode.class)
+      {
+        if (__typeCode == null)
+        {
+          if (__active)
+          {
+            return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+          }
+          __active = true;
+          org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [5];
+          org.omg.CORBA.TypeCode _tcOf_members0 = null;
+          _tcOf_members0 = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_short);
+          _members0[0] = new org.omg.CORBA.StructMember (
+            "mode",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = org.asam.ods.T_LONGLONGHelper.type ();
+          _members0[1] = new org.omg.CORBA.StructMember (
+            "aeId",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = org.asam.ods.T_LONGLONGHelper.type ();
+          _members0[2] = new org.omg.CORBA.StructMember (
+            "ieId",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = org.asam.ods.T_LONGLONGHelper.type ();
+          _members0[3] = new org.omg.CORBA.StructMember (
+            "userId",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = org.omg.CORBA.ORB.init ().create_string_tc (0);
+          _members0[4] = new org.omg.CORBA.StructMember (
+            "timestamp",
+            _tcOf_members0,
+            null);
+          __typeCode = org.omg.CORBA.ORB.init ().create_struct_tc (com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEventHelper.id (), "AvalonNotificationCorbaEvent", _members0);
+          __active = false;
+        }
+      }
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent read (org.omg.CORBA.portable.InputStream istream)
+  {
+    com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent value = new com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent ();
+    value.mode = istream.read_short ();
+    value.aeId = org.asam.ods.T_LONGLONGHelper.read (istream);
+    value.ieId = org.asam.ods.T_LONGLONGHelper.read (istream);
+    value.userId = org.asam.ods.T_LONGLONGHelper.read (istream);
+    value.timestamp = istream.read_string ();
+    return value;
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent value)
+  {
+    ostream.write_short (value.mode);
+    org.asam.ods.T_LONGLONGHelper.write (ostream, value.aeId);
+    org.asam.ods.T_LONGLONGHelper.write (ostream, value.ieId);
+    org.asam.ods.T_LONGLONGHelper.write (ostream, value.userId);
+    ostream.write_string (value.timestamp);
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHolder.java
new file mode 100644
index 0000000..fbed469
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHolder.java
@@ -0,0 +1,38 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/AvalonNotificationCorbaEventHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public final class AvalonNotificationCorbaEventHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent value = null;
+
+  public AvalonNotificationCorbaEventHolder ()
+  {
+  }
+
+  public AvalonNotificationCorbaEventHolder (com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEventHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEventHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEventHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_DELETE.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_DELETE.java
new file mode 100644
index 0000000..9e91cca
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_DELETE.java
@@ -0,0 +1,18 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/MODE_DELETE.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public interface MODE_DELETE
+{
+
+  /**
+  * The value of the mode field in the event when a delete is registered.
+  */
+  public static final short value = (short)(3);
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_INSERT.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_INSERT.java
new file mode 100644
index 0000000..36a86e6
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_INSERT.java
@@ -0,0 +1,18 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/MODE_INSERT.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public interface MODE_INSERT
+{
+
+  /**
+  * The value of the mode field in the event when an insert is registered.
+  */
+  public static final short value = (short)(1);
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_MODIFYRIGHTS.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_MODIFYRIGHTS.java
new file mode 100644
index 0000000..4d48ccd
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_MODIFYRIGHTS.java
@@ -0,0 +1,18 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/MODE_MODIFYRIGHTS.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public interface MODE_MODIFYRIGHTS
+{
+
+  /**
+  * The value of the mode field in the event when a modifyrights is registered.
+  */
+  public static final short value = (short)(4);
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_REPLACE.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_REPLACE.java
new file mode 100644
index 0000000..dc121c2
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/avalonCorbaNotification/notification/MODE_REPLACE.java
@@ -0,0 +1,18 @@
+package com.highqsoft.avalonCorbaNotification.notification;
+
+
+/**
+* com/highqsoft/avalonCorbaNotification/notification/MODE_REPLACE.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/AvalonEvent.idl
+* Freitag, 5. August 2016 09:43 Uhr MESZ
+*/
+
+public interface MODE_REPLACE
+{
+
+  /**
+  * The value of the mode field in the event when a replace is registered.
+  */
+  public static final short value = (short)(2);
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerException.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerException.java
new file mode 100644
index 0000000..229f144
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerException.java
@@ -0,0 +1,39 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerException.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class CORBAFileServerException extends org.omg.CORBA.UserException
+{
+  public com.highqsoft.corbafileserver.generated.ErrorCode errCode = null;
+  public com.highqsoft.corbafileserver.generated.SeverityFlag sevFlag = null;
+  public String reason = null;
+
+  public CORBAFileServerException ()
+  {
+    super(CORBAFileServerExceptionHelper.id());
+  } // ctor
+
+  public CORBAFileServerException (com.highqsoft.corbafileserver.generated.ErrorCode _errCode, com.highqsoft.corbafileserver.generated.SeverityFlag _sevFlag, String _reason)
+  {
+    super(CORBAFileServerExceptionHelper.id());
+    errCode = _errCode;
+    sevFlag = _sevFlag;
+    reason = _reason;
+  } // ctor
+
+
+  public CORBAFileServerException (String $reason, com.highqsoft.corbafileserver.generated.ErrorCode _errCode, com.highqsoft.corbafileserver.generated.SeverityFlag _sevFlag, String _reason)
+  {
+    super(CORBAFileServerExceptionHelper.id() + "  " + $reason);
+    errCode = _errCode;
+    sevFlag = _sevFlag;
+    reason = _reason;
+  } // ctor
+
+} // class CORBAFileServerException
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHelper.java
new file mode 100644
index 0000000..c0c8e0f
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHelper.java
@@ -0,0 +1,93 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class CORBAFileServerExceptionHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.corbafileserver.generated.CORBAFileServerException that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerException extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  private static boolean __active = false;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      synchronized (org.omg.CORBA.TypeCode.class)
+      {
+        if (__typeCode == null)
+        {
+          if (__active)
+          {
+            return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+          }
+          __active = true;
+          org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [3];
+          org.omg.CORBA.TypeCode _tcOf_members0 = null;
+          _tcOf_members0 = com.highqsoft.corbafileserver.generated.ErrorCodeHelper.type ();
+          _members0[0] = new org.omg.CORBA.StructMember (
+            "errCode",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = com.highqsoft.corbafileserver.generated.SeverityFlagHelper.type ();
+          _members0[1] = new org.omg.CORBA.StructMember (
+            "sevFlag",
+            _tcOf_members0,
+            null);
+          _tcOf_members0 = org.omg.CORBA.ORB.init ().create_string_tc (0);
+          _members0[2] = new org.omg.CORBA.StructMember (
+            "reason",
+            _tcOf_members0,
+            null);
+          __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.id (), "CORBAFileServerException", _members0);
+          __active = false;
+        }
+      }
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerException read (org.omg.CORBA.portable.InputStream istream)
+  {
+    com.highqsoft.corbafileserver.generated.CORBAFileServerException value = new com.highqsoft.corbafileserver.generated.CORBAFileServerException ();
+    // read and discard the repository ID
+    istream.read_string ();
+    value.errCode = com.highqsoft.corbafileserver.generated.ErrorCodeHelper.read (istream);
+    value.sevFlag = com.highqsoft.corbafileserver.generated.SeverityFlagHelper.read (istream);
+    value.reason = istream.read_string ();
+    return value;
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.corbafileserver.generated.CORBAFileServerException value)
+  {
+    // write the repository ID
+    ostream.write_string (id ());
+    com.highqsoft.corbafileserver.generated.ErrorCodeHelper.write (ostream, value.errCode);
+    com.highqsoft.corbafileserver.generated.SeverityFlagHelper.write (ostream, value.sevFlag);
+    ostream.write_string (value.reason);
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHolder.java
new file mode 100644
index 0000000..0ace26a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHolder.java
@@ -0,0 +1,38 @@
+package com.highqsoft.corbafileserver.generated;
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerExceptionHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class CORBAFileServerExceptionHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.corbafileserver.generated.CORBAFileServerException value = null;
+
+  public CORBAFileServerExceptionHolder ()
+  {
+  }
+
+  public CORBAFileServerExceptionHolder (com.highqsoft.corbafileserver.generated.CORBAFileServerException initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIF.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIF.java
new file mode 100644
index 0000000..87ec4ef
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIF.java
@@ -0,0 +1,18 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIF.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public interface CORBAFileServerIF extends CORBAFileServerIFOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity 
+{
+
+  /*
+  	  * The version number of the IDL
+  	  */
+  public static final String INTERFACEVERSION = "1.3";
+} // interface CORBAFileServerIF
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHelper.java
new file mode 100644
index 0000000..5944a7d
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHelper.java
@@ -0,0 +1,85 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIFHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class CORBAFileServerIFHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerIF:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.corbafileserver.generated.CORBAFileServerIF that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerIF extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc (com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper.id (), "CORBAFileServerIF");
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerIF read (org.omg.CORBA.portable.InputStream istream)
+  {
+    return narrow (istream.read_Object (_CORBAFileServerIFStub.class));
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.corbafileserver.generated.CORBAFileServerIF value)
+  {
+    ostream.write_Object ((org.omg.CORBA.Object) value);
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerIF narrow (org.omg.CORBA.Object obj)
+  {
+    if (obj == null)
+      return null;
+    else if (obj instanceof com.highqsoft.corbafileserver.generated.CORBAFileServerIF)
+      return (com.highqsoft.corbafileserver.generated.CORBAFileServerIF)obj;
+    else if (!obj._is_a (id ()))
+      throw new org.omg.CORBA.BAD_PARAM ();
+    else
+    {
+      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
+      com.highqsoft.corbafileserver.generated._CORBAFileServerIFStub stub = new com.highqsoft.corbafileserver.generated._CORBAFileServerIFStub ();
+      stub._set_delegate(delegate);
+      return stub;
+    }
+  }
+
+  public static com.highqsoft.corbafileserver.generated.CORBAFileServerIF unchecked_narrow (org.omg.CORBA.Object obj)
+  {
+    if (obj == null)
+      return null;
+    else if (obj instanceof com.highqsoft.corbafileserver.generated.CORBAFileServerIF)
+      return (com.highqsoft.corbafileserver.generated.CORBAFileServerIF)obj;
+    else
+    {
+      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
+      com.highqsoft.corbafileserver.generated._CORBAFileServerIFStub stub = new com.highqsoft.corbafileserver.generated._CORBAFileServerIFStub ();
+      stub._set_delegate(delegate);
+      return stub;
+    }
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHolder.java
new file mode 100644
index 0000000..6acc46b
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFHolder.java
@@ -0,0 +1,38 @@
+package com.highqsoft.corbafileserver.generated;
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIFHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class CORBAFileServerIFHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.corbafileserver.generated.CORBAFileServerIF value = null;
+
+  public CORBAFileServerIFHolder ()
+  {
+  }
+
+  public CORBAFileServerIFHolder (com.highqsoft.corbafileserver.generated.CORBAFileServerIF initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFOperations.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFOperations.java
new file mode 100644
index 0000000..b5f74a7
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFOperations.java
@@ -0,0 +1,496 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIFOperations.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public interface CORBAFileServerIFOperations 
+{
+
+  /**
+        * Save the data associated with the given intput stream.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  String save (org.asam.ods.AoSession aoSess, String name, String subDir, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  String saveForInstance (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the name of an applciation element and the name of the instance element
+        * that holds the external reference
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aeName the application element name.
+        * @param  ieName the instance element name.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  String saveForInstanceName (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Delete the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        */
+  void delete (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Move the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  urlo the url of the file.
+        */
+  void move (org.asam.ods.AoSession aoSess, String url) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Delete the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  url the url of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  void deleteForInstance (org.asam.ods.AoSession aoSess, String url, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Move the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  void moveForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  void getBySocket (org.asam.ods.AoSession aoSess, String name, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the url specification of the file.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  void getForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  String saveBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  String saveForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aeName the application element name.
+         * @param  ieName the instance element name.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  String saveForInstanceNameBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  com.highqsoft.corbafileserver.generated.InputStreamIF read (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  com.highqsoft.corbafileserver.generated.InputStreamIF readForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  size the size of the input stream.
+        */
+  long getSize (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  size the size of the input stream.
+        */
+  long getSizeForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  void terminate (org.asam.ods.AoSession aoSess, String name, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  void terminateForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Get the name of the host where the server is running
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return the hostname
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  String getHostname (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Get a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @return the context value
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY,
+        *    FILESERVER_NOT_FOUND
+        */
+  String getContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Set a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @param value the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  void setContext (org.asam.ods.AoSession aoSess, String key, String value) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Remove a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  void removeContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * List all context keywords.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return a sequence of strings.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  String[] listContext (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Get the version of the CorbaFileServerIF.
+        * Returns getVersion of CorbaFileServer.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @return  The interface version of the CorbaFileServerIF.
+        *
+        */
+  String getInterfaceVersion () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Returns an array of long values representing the length
+        * of the files that were provided in the String array.
+        * The order of the long values must match with the order
+        * of the filenames.
+        *
+        * @param aoSess the aoSession of the caller
+        * @param names the String array of filenames for 
+        *              which to get the sizes
+        * @return an Array of long values containing the file sizes
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        *
+        */
+  long[] getSizes (org.asam.ods.AoSession aoSess, String[] names) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+} // interface CORBAFileServerIFOperations
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOA.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOA.java
new file mode 100644
index 0000000..d1c770a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOA.java
@@ -0,0 +1,963 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOA.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public abstract class CORBAFileServerIFPOA extends org.omg.PortableServer.Servant
+ implements com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations, org.omg.CORBA.portable.InvokeHandler
+{
+
+  // Constructors
+
+  private static java.util.Hashtable _methods = new java.util.Hashtable ();
+  static
+  {
+    _methods.put ("save", new java.lang.Integer (0));
+    _methods.put ("saveForInstance", new java.lang.Integer (1));
+    _methods.put ("saveForInstanceName", new java.lang.Integer (2));
+    _methods.put ("delete", new java.lang.Integer (3));
+    _methods.put ("move", new java.lang.Integer (4));
+    _methods.put ("deleteForInstance", new java.lang.Integer (5));
+    _methods.put ("moveForInstance", new java.lang.Integer (6));
+    _methods.put ("getBySocket", new java.lang.Integer (7));
+    _methods.put ("getForInstanceBySocket", new java.lang.Integer (8));
+    _methods.put ("saveBySocket", new java.lang.Integer (9));
+    _methods.put ("saveForInstanceBySocket", new java.lang.Integer (10));
+    _methods.put ("saveForInstanceNameBySocket", new java.lang.Integer (11));
+    _methods.put ("read", new java.lang.Integer (12));
+    _methods.put ("readForInstance", new java.lang.Integer (13));
+    _methods.put ("getSize", new java.lang.Integer (14));
+    _methods.put ("getSizeForInstance", new java.lang.Integer (15));
+    _methods.put ("terminate", new java.lang.Integer (16));
+    _methods.put ("terminateForInstance", new java.lang.Integer (17));
+    _methods.put ("getHostname", new java.lang.Integer (18));
+    _methods.put ("getContext", new java.lang.Integer (19));
+    _methods.put ("setContext", new java.lang.Integer (20));
+    _methods.put ("removeContext", new java.lang.Integer (21));
+    _methods.put ("listContext", new java.lang.Integer (22));
+    _methods.put ("getInterfaceVersion", new java.lang.Integer (23));
+    _methods.put ("getSizes", new java.lang.Integer (24));
+  }
+
+  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
+                                org.omg.CORBA.portable.InputStream in,
+                                org.omg.CORBA.portable.ResponseHandler $rh)
+  {
+    org.omg.CORBA.portable.OutputStream out = null;
+    java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);
+    if (__method == null)
+      throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+
+    switch (__method.intValue ())
+    {
+
+  /**
+        * Save the data associated with the given intput stream.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+       case 0:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/save
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           com.highqsoft.corbafileserver.generated.InputStreamIF stream = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read (in);
+           String $result = null;
+           $result = this.save (aoSess, name, subDir, stream);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+       case 1:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/saveForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           com.highqsoft.corbafileserver.generated.InputStreamIF stream = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read (in);
+           String $result = null;
+           $result = this.saveForInstance (aoSess, name, subDir, aid, iid, stream);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the name of an applciation element and the name of the instance element
+        * that holds the external reference
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aeName the application element name.
+        * @param  ieName the instance element name.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+       case 2:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/saveForInstanceName
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           String aeName = in.read_string ();
+           String ieName = in.read_string ();
+           com.highqsoft.corbafileserver.generated.InputStreamIF stream = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read (in);
+           String $result = null;
+           $result = this.saveForInstanceName (aoSess, name, subDir, aeName, ieName, stream);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Delete the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        */
+       case 3:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/delete
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           this.delete (aoSess, name);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Move the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  urlo the url of the file.
+        */
+       case 4:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/move
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String url = in.read_string ();
+           this.move (aoSess, url);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Delete the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  url the url of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+       case 5:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/deleteForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String url = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           this.deleteForInstance (aoSess, url, aid, iid);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Move the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+       case 6:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/moveForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           this.moveForInstance (aoSess, name, aid, iid);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+       case 7:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getBySocket
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String host = in.read_string ();
+           int aPort = in.read_long ();
+           this.getBySocket (aoSess, name, host, aPort);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the url specification of the file.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+       case 8:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getForInstanceBySocket
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           String host = in.read_string ();
+           int aPort = in.read_long ();
+           this.getForInstanceBySocket (aoSess, name, aid, iid, host, aPort);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+       case 9:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/saveBySocket
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           String host = in.read_string ();
+           int aPort = in.read_long ();
+           String $result = null;
+           $result = this.saveBySocket (aoSess, name, subDir, host, aPort);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+       case 10:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/saveForInstanceBySocket
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           String host = in.read_string ();
+           int aPort = in.read_long ();
+           String $result = null;
+           $result = this.saveForInstanceBySocket (aoSess, name, subDir, aid, iid, host, aPort);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aeName the application element name.
+         * @param  ieName the instance element name.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+       case 11:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/saveForInstanceNameBySocket
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String subDir = in.read_string ();
+           String aeName = in.read_string ();
+           String ieName = in.read_string ();
+           String host = in.read_string ();
+           int aPort = in.read_long ();
+           String $result = null;
+           $result = this.saveForInstanceNameBySocket (aoSess, name, subDir, aeName, ieName, host, aPort);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  stream the input stream, ready to read by the server.
+        */
+       case 12:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/read
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           com.highqsoft.corbafileserver.generated.InputStreamIF $result = null;
+           $result = this.read (aoSess, name);
+           out = $rh.createReply();
+           com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write (out, $result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        */
+       case 13:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/readForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           com.highqsoft.corbafileserver.generated.InputStreamIF $result = null;
+           $result = this.readForInstance (aoSess, name, aid, iid);
+           out = $rh.createReply();
+           com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write (out, $result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  size the size of the input stream.
+        */
+       case 14:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getSize
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           long $result = (long)0;
+           $result = this.getSize (aoSess, name);
+           out = $rh.createReply();
+           out.write_longlong ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  size the size of the input stream.
+        */
+       case 15:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getSizeForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           long $result = (long)0;
+           $result = this.getSizeForInstance (aoSess, name, aid, iid);
+           out = $rh.createReply();
+           out.write_longlong ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+       case 16:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/terminate
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           String parameter = in.read_string ();
+           this.terminate (aoSess, name, parameter);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+       case 17:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/terminateForInstance
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String name = in.read_string ();
+           org.asam.ods.T_LONGLONG aid = org.asam.ods.T_LONGLONGHelper.read (in);
+           org.asam.ods.T_LONGLONG iid = org.asam.ods.T_LONGLONGHelper.read (in);
+           String parameter = in.read_string ();
+           this.terminateForInstance (aoSess, name, aid, iid, parameter);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Get the name of the host where the server is running
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return the hostname
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+       case 18:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getHostname
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String $result = null;
+           $result = this.getHostname (aoSess);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Get a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @return the context value
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY,
+        *    FILESERVER_NOT_FOUND
+        */
+       case 19:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getContext
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String key = in.read_string ();
+           String $result = null;
+           $result = this.getContext (aoSess, key);
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Set a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @param value the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+       case 20:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/setContext
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String key = in.read_string ();
+           String value = in.read_string ();
+           this.setContext (aoSess, key, value);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Remove a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+       case 21:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/removeContext
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String key = in.read_string ();
+           this.removeContext (aoSess, key);
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * List all context keywords.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return a sequence of strings.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+       case 22:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/listContext
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String $result[] = null;
+           $result = this.listContext (aoSess);
+           out = $rh.createReply();
+           com.highqsoft.corbafileserver.generated.DS_STRINGHelper.write (out, $result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Get the version of the CorbaFileServerIF.
+        * Returns getVersion of CorbaFileServer.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @return  The interface version of the CorbaFileServerIF.
+        *
+        */
+       case 23:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getInterfaceVersion
+       {
+         try {
+           String $result = null;
+           $result = this.getInterfaceVersion ();
+           out = $rh.createReply();
+           out.write_string ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Returns an array of long values representing the length
+        * of the files that were provided in the String array.
+        * The order of the long values must match with the order
+        * of the filenames.
+        *
+        * @param aoSess the aoSession of the caller
+        * @param names the String array of filenames for 
+        *              which to get the sizes
+        * @return an Array of long values containing the file sizes
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        *
+        */
+       case 24:  // com/highqsoft/corbafileserver/generated/CORBAFileServerIF/getSizes
+       {
+         try {
+           org.asam.ods.AoSession aoSess = org.asam.ods.AoSessionHelper.read (in);
+           String names[] = com.highqsoft.corbafileserver.generated.DS_STRINGHelper.read (in);
+           long $result[] = null;
+           $result = this.getSizes (aoSess, names);
+           out = $rh.createReply();
+           com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.write (out, $result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+       default:
+         throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+    }
+
+    return out;
+  } // _invoke
+
+  // Type-specific CORBA::Object operations
+  private static String[] __ids = {
+    "IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerIF:1.0"};
+
+  public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)
+  {
+    return (String[])__ids.clone ();
+  }
+
+  public CORBAFileServerIF _this() 
+  {
+    return CORBAFileServerIFHelper.narrow(
+    super._this_object());
+  }
+
+  public CORBAFileServerIF _this(org.omg.CORBA.ORB orb) 
+  {
+    return CORBAFileServerIFHelper.narrow(
+    super._this_object(orb));
+  }
+
+
+} // class CORBAFileServerIFPOA
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOATie.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOATie.java
new file mode 100644
index 0000000..963e9b3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOATie.java
@@ -0,0 +1,623 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/CORBAFileServerIFPOATie.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public class CORBAFileServerIFPOATie extends CORBAFileServerIFPOA
+{
+
+  // Constructors
+
+  public CORBAFileServerIFPOATie ( com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations delegate ) {
+      this._impl = delegate;
+  }
+  public CORBAFileServerIFPOATie ( com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations delegate , org.omg.PortableServer.POA poa ) {
+      this._impl = delegate;
+      this._poa      = poa;
+  }
+  public com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations _delegate() {
+      return this._impl;
+  }
+  public void _delegate (com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations delegate ) {
+      this._impl = delegate;
+  }
+  public org.omg.PortableServer.POA _default_POA() {
+      if(_poa != null) {
+          return _poa;
+      }
+      else {
+          return super._default_POA();
+      }
+  }
+
+  /**
+        * Save the data associated with the given intput stream.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String save (org.asam.ods.AoSession aoSess, String name, String subDir, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.save(aoSess, name, subDir, stream);
+  } // save
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String saveForInstance (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.saveForInstance(aoSess, name, subDir, aid, iid, stream);
+  } // saveForInstance
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the name of an applciation element and the name of the instance element
+        * that holds the external reference
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aeName the application element name.
+        * @param  ieName the instance element name.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String saveForInstanceName (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.saveForInstanceName(aoSess, name, subDir, aeName, ieName, stream);
+  } // saveForInstanceName
+
+
+  /**
+        * Delete the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        */
+  public void delete (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.delete(aoSess, name);
+  } // delete
+
+
+  /**
+        * Move the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  urlo the url of the file.
+        */
+  public void move (org.asam.ods.AoSession aoSess, String url) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.move(aoSess, url);
+  } // move
+
+
+  /**
+        * Delete the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  url the url of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  public void deleteForInstance (org.asam.ods.AoSession aoSess, String url, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.deleteForInstance(aoSess, url, aid, iid);
+  } // deleteForInstance
+
+
+  /**
+        * Move the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  public void moveForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.moveForInstance(aoSess, name, aid, iid);
+  } // moveForInstance
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  public void getBySocket (org.asam.ods.AoSession aoSess, String name, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.getBySocket(aoSess, name, host, aPort);
+  } // getBySocket
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the url specification of the file.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  public void getForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.getForInstanceBySocket(aoSess, name, aid, iid, host, aPort);
+  } // getForInstanceBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.saveBySocket(aoSess, name, subDir, host, aPort);
+  } // saveBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.saveForInstanceBySocket(aoSess, name, subDir, aid, iid, host, aPort);
+  } // saveForInstanceBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aeName the application element name.
+         * @param  ieName the instance element name.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveForInstanceNameBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.saveForInstanceNameBySocket(aoSess, name, subDir, aeName, ieName, host, aPort);
+  } // saveForInstanceNameBySocket
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  public com.highqsoft.corbafileserver.generated.InputStreamIF read (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.read(aoSess, name);
+  } // read
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  public com.highqsoft.corbafileserver.generated.InputStreamIF readForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.readForInstance(aoSess, name, aid, iid);
+  } // readForInstance
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  size the size of the input stream.
+        */
+  public long getSize (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getSize(aoSess, name);
+  } // getSize
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  size the size of the input stream.
+        */
+  public long getSizeForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getSizeForInstance(aoSess, name, aid, iid);
+  } // getSizeForInstance
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  public void terminate (org.asam.ods.AoSession aoSess, String name, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.terminate(aoSess, name, parameter);
+  } // terminate
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  public void terminateForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.terminateForInstance(aoSess, name, aid, iid, parameter);
+  } // terminateForInstance
+
+
+  /**
+        * Get the name of the host where the server is running
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return the hostname
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public String getHostname (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getHostname(aoSess);
+  } // getHostname
+
+
+  /**
+        * Get a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @return the context value
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY,
+        *    FILESERVER_NOT_FOUND
+        */
+  public String getContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getContext(aoSess, key);
+  } // getContext
+
+
+  /**
+        * Set a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @param value the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public void setContext (org.asam.ods.AoSession aoSess, String key, String value) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.setContext(aoSess, key, value);
+  } // setContext
+
+
+  /**
+        * Remove a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public void removeContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.removeContext(aoSess, key);
+  } // removeContext
+
+
+  /**
+        * List all context keywords.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return a sequence of strings.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public String[] listContext (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.listContext(aoSess);
+  } // listContext
+
+
+  /**
+        * Get the version of the CorbaFileServerIF.
+        * Returns getVersion of CorbaFileServer.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @return  The interface version of the CorbaFileServerIF.
+        *
+        */
+  public String getInterfaceVersion () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getInterfaceVersion();
+  } // getInterfaceVersion
+
+
+  /**
+        * Returns an array of long values representing the length
+        * of the files that were provided in the String array.
+        * The order of the long values must match with the order
+        * of the filenames.
+        *
+        * @param aoSess the aoSession of the caller
+        * @param names the String array of filenames for 
+        *              which to get the sizes
+        * @return an Array of long values containing the file sizes
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        *
+        */
+  public long[] getSizes (org.asam.ods.AoSession aoSess, String[] names) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.getSizes(aoSess, names);
+  } // getSizes
+
+  private com.highqsoft.corbafileserver.generated.CORBAFileServerIFOperations _impl;
+  private org.omg.PortableServer.POA _poa;
+
+} // class CORBAFileServerIFPOATie
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHelper.java
new file mode 100644
index 0000000..f2a9b61
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHelper.java
@@ -0,0 +1,60 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/DS_BYTEHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class DS_BYTEHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/DS_BYTE:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, byte[] that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static byte[] extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_octet);
+      __typeCode = org.omg.CORBA.ORB.init ().create_sequence_tc (0, __typeCode);
+      __typeCode = org.omg.CORBA.ORB.init ().create_alias_tc (com.highqsoft.corbafileserver.generated.DS_BYTEHelper.id (), "DS_BYTE", __typeCode);
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static byte[] read (org.omg.CORBA.portable.InputStream istream)
+  {
+    byte value[] = null;
+    int _len0 = istream.read_long ();
+    value = new byte[_len0];
+    istream.read_octet_array (value, 0, _len0);
+    return value;
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, byte[] value)
+  {
+    ostream.write_long (value.length);
+    ostream.write_octet_array (value, 0, value.length);
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHolder.java
new file mode 100644
index 0000000..eaa85f0
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_BYTEHolder.java
@@ -0,0 +1,39 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/DS_BYTEHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class DS_BYTEHolder implements org.omg.CORBA.portable.Streamable
+{
+  public byte value[] = null;
+
+  public DS_BYTEHolder ()
+  {
+  }
+
+  public DS_BYTEHolder (byte[] initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.DS_BYTEHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.DS_BYTEHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.DS_BYTEHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHelper.java
new file mode 100644
index 0000000..5bbe928
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHelper.java
@@ -0,0 +1,62 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/DS_STRINGHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class DS_STRINGHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/DS_STRING:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, String[] that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static String[] extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().create_string_tc (0);
+      __typeCode = org.omg.CORBA.ORB.init ().create_sequence_tc (0, __typeCode);
+      __typeCode = org.omg.CORBA.ORB.init ().create_alias_tc (com.highqsoft.corbafileserver.generated.DS_STRINGHelper.id (), "DS_STRING", __typeCode);
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static String[] read (org.omg.CORBA.portable.InputStream istream)
+  {
+    String value[] = null;
+    int _len0 = istream.read_long ();
+    value = new String[_len0];
+    for (int _o1 = 0;_o1 < value.length; ++_o1)
+      value[_o1] = istream.read_string ();
+    return value;
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, String[] value)
+  {
+    ostream.write_long (value.length);
+    for (int _i0 = 0;_i0 < value.length; ++_i0)
+      ostream.write_string (value[_i0]);
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHolder.java
new file mode 100644
index 0000000..c37baca
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/DS_STRINGHolder.java
@@ -0,0 +1,39 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/DS_STRINGHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class DS_STRINGHolder implements org.omg.CORBA.portable.Streamable
+{
+  public String value[] = null;
+
+  public DS_STRINGHolder ()
+  {
+  }
+
+  public DS_STRINGHolder (String[] initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.DS_STRINGHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.DS_STRINGHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.DS_STRINGHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCode.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCode.java
new file mode 100644
index 0000000..5b283e8
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCode.java
@@ -0,0 +1,70 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/ErrorCode.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error code.
+   */
+public class ErrorCode implements org.omg.CORBA.portable.IDLEntity
+{
+  private        int __value;
+  private static int __size = 15;
+  private static com.highqsoft.corbafileserver.generated.ErrorCode[] __array = new com.highqsoft.corbafileserver.generated.ErrorCode [__size];
+
+  public static final int _FILESERVER_ASAMODS_EXCEPTION = 0;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_ASAMODS_EXCEPTION = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_ASAMODS_EXCEPTION);
+  public static final int _FILESERVER_ACCESS_DENIED = 1;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_ACCESS_DENIED = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_ACCESS_DENIED);
+  public static final int _FILESERVER_FILE_NOT_FOUND = 2;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_FILE_NOT_FOUND = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_FILE_NOT_FOUND);
+  public static final int _FILESERVER_IO_EXCEPTION = 3;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_IO_EXCEPTION = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_IO_EXCEPTION);
+  public static final int _FILESERVER_INFORMATION = 4;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_INFORMATION = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_INFORMATION);
+  public static final int _FILESERVER_BAD_PARAMETER = 5;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_BAD_PARAMETER = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_BAD_PARAMETER);
+  public static final int _FILESERVER_MISSING_PARAMETER = 6;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_MISSING_PARAMETER = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_MISSING_PARAMETER);
+  public static final int _FILESERVER_CONNECT_FAILED = 7;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_CONNECT_FAILED = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_CONNECT_FAILED);
+  public static final int _FILESERVER_CONNECT_REFUSED = 8;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_CONNECT_REFUSED = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_CONNECT_REFUSED);
+  public static final int _FILESERVER_CONNECTION_LOST = 9;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_CONNECTION_LOST = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_CONNECTION_LOST);
+  public static final int _FILESERVER_IMPLEMENTATION_PROBLEM = 10;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_IMPLEMENTATION_PROBLEM = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_IMPLEMENTATION_PROBLEM);
+  public static final int _FILESERVER_NOT_IMPLEMENTED = 11;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_NOT_IMPLEMENTED = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_NOT_IMPLEMENTED);
+  public static final int _FILESERVER_NO_MEMORY = 12;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_NO_MEMORY = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_NO_MEMORY);
+  public static final int _FILESERVER_NULL_PARAMETER = 13;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_NULL_PARAMETER = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_NULL_PARAMETER);
+  public static final int _FILESERVER_NOT_FOUND = 14;
+  public static final com.highqsoft.corbafileserver.generated.ErrorCode FILESERVER_NOT_FOUND = new com.highqsoft.corbafileserver.generated.ErrorCode(_FILESERVER_NOT_FOUND);
+
+  public int value ()
+  {
+    return __value;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.ErrorCode from_int (int value)
+  {
+    if (value >= 0 && value < __size)
+      return __array[value];
+    else
+      throw new org.omg.CORBA.BAD_PARAM ();
+  }
+
+  protected ErrorCode (int value)
+  {
+    __value = value;
+    __array[__value] = this;
+  }
+} // class ErrorCode
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHelper.java
new file mode 100644
index 0000000..ccbc532
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHelper.java
@@ -0,0 +1,57 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/ErrorCodeHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error code.
+   */
+abstract public class ErrorCodeHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/ErrorCode:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.corbafileserver.generated.ErrorCode that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.corbafileserver.generated.ErrorCode extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().create_enum_tc (com.highqsoft.corbafileserver.generated.ErrorCodeHelper.id (), "ErrorCode", new String[] { "FILESERVER_ASAMODS_EXCEPTION", "FILESERVER_ACCESS_DENIED", "FILESERVER_FILE_NOT_FOUND", "FILESERVER_IO_EXCEPTION", "FILESERVER_INFORMATION", "FILESERVER_BAD_PARAMETER", "FILESERVER_MISSING_PARAMETER", "FILESERVER_CONNECT_FAILED", "FILESERVER_CONNECT_REFUSED", "FILESERVER_CONNECTION_LOST", "FILESERVER_IMPLEMENTATION_PROBLEM", "FILESERVER_NOT_IMPLEMENTED", "FILESERVER_NO_MEMORY", "FILESERVER_NULL_PARAMETER", "FILESERVER_NOT_FOUND"} );
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.ErrorCode read (org.omg.CORBA.portable.InputStream istream)
+  {
+    return com.highqsoft.corbafileserver.generated.ErrorCode.from_int (istream.read_long ());
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.corbafileserver.generated.ErrorCode value)
+  {
+    ostream.write_long (value.value ());
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHolder.java
new file mode 100644
index 0000000..debb152
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/ErrorCodeHolder.java
@@ -0,0 +1,42 @@
+package com.highqsoft.corbafileserver.generated;
+
+/**
+* com/highqsoft/corbafileserver/generated/ErrorCodeHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error code.
+   */
+public final class ErrorCodeHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.corbafileserver.generated.ErrorCode value = null;
+
+  public ErrorCodeHolder ()
+  {
+  }
+
+  public ErrorCodeHolder (com.highqsoft.corbafileserver.generated.ErrorCode initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.ErrorCodeHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.ErrorCodeHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.ErrorCodeHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIF.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIF.java
new file mode 100644
index 0000000..993e85e
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIF.java
@@ -0,0 +1,13 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIF.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public interface InputStreamIF extends InputStreamIFOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity 
+{
+} // interface InputStreamIF
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHelper.java
new file mode 100644
index 0000000..c9edc25
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHelper.java
@@ -0,0 +1,85 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIFHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class InputStreamIFHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/InputStreamIF:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.corbafileserver.generated.InputStreamIF that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.corbafileserver.generated.InputStreamIF extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc (com.highqsoft.corbafileserver.generated.InputStreamIFHelper.id (), "InputStreamIF");
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.InputStreamIF read (org.omg.CORBA.portable.InputStream istream)
+  {
+    return narrow (istream.read_Object (_InputStreamIFStub.class));
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.corbafileserver.generated.InputStreamIF value)
+  {
+    ostream.write_Object ((org.omg.CORBA.Object) value);
+  }
+
+  public static com.highqsoft.corbafileserver.generated.InputStreamIF narrow (org.omg.CORBA.Object obj)
+  {
+    if (obj == null)
+      return null;
+    else if (obj instanceof com.highqsoft.corbafileserver.generated.InputStreamIF)
+      return (com.highqsoft.corbafileserver.generated.InputStreamIF)obj;
+    else if (!obj._is_a (id ()))
+      throw new org.omg.CORBA.BAD_PARAM ();
+    else
+    {
+      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
+      com.highqsoft.corbafileserver.generated._InputStreamIFStub stub = new com.highqsoft.corbafileserver.generated._InputStreamIFStub ();
+      stub._set_delegate(delegate);
+      return stub;
+    }
+  }
+
+  public static com.highqsoft.corbafileserver.generated.InputStreamIF unchecked_narrow (org.omg.CORBA.Object obj)
+  {
+    if (obj == null)
+      return null;
+    else if (obj instanceof com.highqsoft.corbafileserver.generated.InputStreamIF)
+      return (com.highqsoft.corbafileserver.generated.InputStreamIF)obj;
+    else
+    {
+      org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
+      com.highqsoft.corbafileserver.generated._InputStreamIFStub stub = new com.highqsoft.corbafileserver.generated._InputStreamIFStub ();
+      stub._set_delegate(delegate);
+      return stub;
+    }
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHolder.java
new file mode 100644
index 0000000..8145846
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFHolder.java
@@ -0,0 +1,38 @@
+package com.highqsoft.corbafileserver.generated;
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIFHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class InputStreamIFHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.corbafileserver.generated.InputStreamIF value = null;
+
+  public InputStreamIFHolder ()
+  {
+  }
+
+  public InputStreamIFHolder (com.highqsoft.corbafileserver.generated.InputStreamIF initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.InputStreamIFHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFOperations.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFOperations.java
new file mode 100644
index 0000000..fd811dd
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFOperations.java
@@ -0,0 +1,85 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIFOperations.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public interface InputStreamIFOperations 
+{
+
+  /**
+        * Reads up to len bytes of data from the input stream into an array
+        * of bytes. An attempt is made to read as many as len bytes, but a
+        * smaller number may be read, possibly zero. The number of bytes
+        * actually read is returned as an integer.
+        *
+        * This method blocks until input data is available, end of file
+        * is detected, or an exception is thrown.
+        *
+        * If b is null, a NullPointerException is thrown.
+        *
+        * If off is negative, or len is negative, or off+len is greater
+        * than the length of the array b, then an IndexOutOfBoundsException is thrown.
+        *
+        * If len is zero, then no bytes are read and 0 is returned;
+        * otherwise, there is an attempt to read at least one byte.
+        * If no byte is available because the stream is at end of file,
+        * the value -1 is returned; otherwise, at least one byte is read and stored into b.
+        *
+        * The first byte read is stored into element b[off], the next one into b[off+1],
+        * and so on. The number of bytes read is, at most, equal to len. Let k be the number
+        * of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1],
+        * leaving elements b[off+k] through b[off+len-1] unaffected.
+        *
+        * In every case, elements b[0] through b[off] and elements b[off+len]
+        * through b[b.length-1] are unaffected.
+        *
+        * If the first byte cannot be read for any reason other than end of file,
+        * then an IOException is thrown. In particular, an IOException is thrown
+        * if the input stream has been closed.
+        *
+        * The read(b, off, len) method for class InputStream simply calls the method
+        * read() repeatedly. If the first such call results in an IOException,
+        * that exception is returned from the call to the read(b, off, len) method.
+        * If any subsequent call to read() results in a IOException, the exception
+        * is caught and treated as if it were end of file; the bytes read up to that
+        * point are stored into b and the number of bytes read before the exception
+        * occurred is returned. Subclasses are encouraged to provide a more efficient
+        * implementation of this method.
+        *
+        * @param b - the buffer into which the data is read.
+        * @param off - the start offset in array b  at which the data is written.
+        * @param len - the maximum number of bytes to read.
+        * @return the total number of bytes read into the buffer,
+        *         or -1 is there is no more data because the end
+        *         of the stream has been reached.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  int read (com.highqsoft.corbafileserver.generated.DS_BYTEHolder b, int off, int len) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Close the input stream.
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  void close () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Get the length of the input stream.
+        *
+        * @return the length of the file to be transferd.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  int length () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+
+  /**
+        * Reset the stream
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  void reset () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+} // interface InputStreamIFOperations
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOA.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOA.java
new file mode 100644
index 0000000..19fb442
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOA.java
@@ -0,0 +1,190 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIFPOA.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public abstract class InputStreamIFPOA extends org.omg.PortableServer.Servant
+ implements com.highqsoft.corbafileserver.generated.InputStreamIFOperations, org.omg.CORBA.portable.InvokeHandler
+{
+
+  // Constructors
+
+  private static java.util.Hashtable _methods = new java.util.Hashtable ();
+  static
+  {
+    _methods.put ("read", new java.lang.Integer (0));
+    _methods.put ("close", new java.lang.Integer (1));
+    _methods.put ("length", new java.lang.Integer (2));
+    _methods.put ("reset", new java.lang.Integer (3));
+  }
+
+  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
+                                org.omg.CORBA.portable.InputStream in,
+                                org.omg.CORBA.portable.ResponseHandler $rh)
+  {
+    org.omg.CORBA.portable.OutputStream out = null;
+    java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);
+    if (__method == null)
+      throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+
+    switch (__method.intValue ())
+    {
+
+  /**
+        * Reads up to len bytes of data from the input stream into an array
+        * of bytes. An attempt is made to read as many as len bytes, but a
+        * smaller number may be read, possibly zero. The number of bytes
+        * actually read is returned as an integer.
+        *
+        * This method blocks until input data is available, end of file
+        * is detected, or an exception is thrown.
+        *
+        * If b is null, a NullPointerException is thrown.
+        *
+        * If off is negative, or len is negative, or off+len is greater
+        * than the length of the array b, then an IndexOutOfBoundsException is thrown.
+        *
+        * If len is zero, then no bytes are read and 0 is returned;
+        * otherwise, there is an attempt to read at least one byte.
+        * If no byte is available because the stream is at end of file,
+        * the value -1 is returned; otherwise, at least one byte is read and stored into b.
+        *
+        * The first byte read is stored into element b[off], the next one into b[off+1],
+        * and so on. The number of bytes read is, at most, equal to len. Let k be the number
+        * of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1],
+        * leaving elements b[off+k] through b[off+len-1] unaffected.
+        *
+        * In every case, elements b[0] through b[off] and elements b[off+len]
+        * through b[b.length-1] are unaffected.
+        *
+        * If the first byte cannot be read for any reason other than end of file,
+        * then an IOException is thrown. In particular, an IOException is thrown
+        * if the input stream has been closed.
+        *
+        * The read(b, off, len) method for class InputStream simply calls the method
+        * read() repeatedly. If the first such call results in an IOException,
+        * that exception is returned from the call to the read(b, off, len) method.
+        * If any subsequent call to read() results in a IOException, the exception
+        * is caught and treated as if it were end of file; the bytes read up to that
+        * point are stored into b and the number of bytes read before the exception
+        * occurred is returned. Subclasses are encouraged to provide a more efficient
+        * implementation of this method.
+        *
+        * @param b - the buffer into which the data is read.
+        * @param off - the start offset in array b  at which the data is written.
+        * @param len - the maximum number of bytes to read.
+        * @return the total number of bytes read into the buffer,
+        *         or -1 is there is no more data because the end
+        *         of the stream has been reached.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+       case 0:  // com/highqsoft/corbafileserver/generated/InputStreamIF/read
+       {
+         try {
+           com.highqsoft.corbafileserver.generated.DS_BYTEHolder b = new com.highqsoft.corbafileserver.generated.DS_BYTEHolder ();
+           int off = in.read_long ();
+           int len = in.read_long ();
+           int $result = (int)0;
+           $result = this.read (b, off, len);
+           out = $rh.createReply();
+           out.write_long ($result);
+           com.highqsoft.corbafileserver.generated.DS_BYTEHelper.write (out, b.value);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Close the input stream.
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+       case 1:  // com/highqsoft/corbafileserver/generated/InputStreamIF/close
+       {
+         try {
+           this.close ();
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Get the length of the input stream.
+        *
+        * @return the length of the file to be transferd.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+       case 2:  // com/highqsoft/corbafileserver/generated/InputStreamIF/length
+       {
+         try {
+           int $result = (int)0;
+           $result = this.length ();
+           out = $rh.createReply();
+           out.write_long ($result);
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+
+  /**
+        * Reset the stream
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+       case 3:  // com/highqsoft/corbafileserver/generated/InputStreamIF/reset
+       {
+         try {
+           this.reset ();
+           out = $rh.createReply();
+         } catch (com.highqsoft.corbafileserver.generated.CORBAFileServerException $ex) {
+           out = $rh.createExceptionReply ();
+           com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.write (out, $ex);
+         }
+         break;
+       }
+
+       default:
+         throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+    }
+
+    return out;
+  } // _invoke
+
+  // Type-specific CORBA::Object operations
+  private static String[] __ids = {
+    "IDL:com/highqsoft/corbafileserver/generated/InputStreamIF:1.0"};
+
+  public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)
+  {
+    return (String[])__ids.clone ();
+  }
+
+  public InputStreamIF _this() 
+  {
+    return InputStreamIFHelper.narrow(
+    super._this_object());
+  }
+
+  public InputStreamIF _this(org.omg.CORBA.ORB orb) 
+  {
+    return InputStreamIFHelper.narrow(
+    super._this_object(orb));
+  }
+
+
+} // class InputStreamIFPOA
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOATie.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOATie.java
new file mode 100644
index 0000000..75650cd
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/InputStreamIFPOATie.java
@@ -0,0 +1,128 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/InputStreamIFPOATie.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public class InputStreamIFPOATie extends InputStreamIFPOA
+{
+
+  // Constructors
+
+  public InputStreamIFPOATie ( com.highqsoft.corbafileserver.generated.InputStreamIFOperations delegate ) {
+      this._impl = delegate;
+  }
+  public InputStreamIFPOATie ( com.highqsoft.corbafileserver.generated.InputStreamIFOperations delegate , org.omg.PortableServer.POA poa ) {
+      this._impl = delegate;
+      this._poa      = poa;
+  }
+  public com.highqsoft.corbafileserver.generated.InputStreamIFOperations _delegate() {
+      return this._impl;
+  }
+  public void _delegate (com.highqsoft.corbafileserver.generated.InputStreamIFOperations delegate ) {
+      this._impl = delegate;
+  }
+  public org.omg.PortableServer.POA _default_POA() {
+      if(_poa != null) {
+          return _poa;
+      }
+      else {
+          return super._default_POA();
+      }
+  }
+
+  /**
+        * Reads up to len bytes of data from the input stream into an array
+        * of bytes. An attempt is made to read as many as len bytes, but a
+        * smaller number may be read, possibly zero. The number of bytes
+        * actually read is returned as an integer.
+        *
+        * This method blocks until input data is available, end of file
+        * is detected, or an exception is thrown.
+        *
+        * If b is null, a NullPointerException is thrown.
+        *
+        * If off is negative, or len is negative, or off+len is greater
+        * than the length of the array b, then an IndexOutOfBoundsException is thrown.
+        *
+        * If len is zero, then no bytes are read and 0 is returned;
+        * otherwise, there is an attempt to read at least one byte.
+        * If no byte is available because the stream is at end of file,
+        * the value -1 is returned; otherwise, at least one byte is read and stored into b.
+        *
+        * The first byte read is stored into element b[off], the next one into b[off+1],
+        * and so on. The number of bytes read is, at most, equal to len. Let k be the number
+        * of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1],
+        * leaving elements b[off+k] through b[off+len-1] unaffected.
+        *
+        * In every case, elements b[0] through b[off] and elements b[off+len]
+        * through b[b.length-1] are unaffected.
+        *
+        * If the first byte cannot be read for any reason other than end of file,
+        * then an IOException is thrown. In particular, an IOException is thrown
+        * if the input stream has been closed.
+        *
+        * The read(b, off, len) method for class InputStream simply calls the method
+        * read() repeatedly. If the first such call results in an IOException,
+        * that exception is returned from the call to the read(b, off, len) method.
+        * If any subsequent call to read() results in a IOException, the exception
+        * is caught and treated as if it were end of file; the bytes read up to that
+        * point are stored into b and the number of bytes read before the exception
+        * occurred is returned. Subclasses are encouraged to provide a more efficient
+        * implementation of this method.
+        *
+        * @param b - the buffer into which the data is read.
+        * @param off - the start offset in array b  at which the data is written.
+        * @param len - the maximum number of bytes to read.
+        * @return the total number of bytes read into the buffer,
+        *         or -1 is there is no more data because the end
+        *         of the stream has been reached.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public int read (com.highqsoft.corbafileserver.generated.DS_BYTEHolder b, int off, int len) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.read(b, off, len);
+  } // read
+
+
+  /**
+        * Close the input stream.
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public void close () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.close();
+  } // close
+
+
+  /**
+        * Get the length of the input stream.
+        *
+        * @return the length of the file to be transferd.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public int length () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    return _impl.length();
+  } // length
+
+
+  /**
+        * Reset the stream
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public void reset () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+    _impl.reset();
+  } // reset
+
+  private com.highqsoft.corbafileserver.generated.InputStreamIFOperations _impl;
+  private org.omg.PortableServer.POA _poa;
+
+} // class InputStreamIFPOATie
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHelper.java
new file mode 100644
index 0000000..76ba344
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHelper.java
@@ -0,0 +1,60 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/LONG_ARRAYHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+abstract public class LONG_ARRAYHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/LONG_ARRAY:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, long[] that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static long[] extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_longlong);
+      __typeCode = org.omg.CORBA.ORB.init ().create_sequence_tc (0, __typeCode);
+      __typeCode = org.omg.CORBA.ORB.init ().create_alias_tc (com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.id (), "LONG_ARRAY", __typeCode);
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static long[] read (org.omg.CORBA.portable.InputStream istream)
+  {
+    long value[] = null;
+    int _len0 = istream.read_long ();
+    value = new long[_len0];
+    istream.read_longlong_array (value, 0, _len0);
+    return value;
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, long[] value)
+  {
+    ostream.write_long (value.length);
+    ostream.write_longlong_array (value, 0, value.length);
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHolder.java
new file mode 100644
index 0000000..d3ab069
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/LONG_ARRAYHolder.java
@@ -0,0 +1,39 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/LONG_ARRAYHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public final class LONG_ARRAYHolder implements org.omg.CORBA.portable.Streamable
+{
+  public long value[] = null;
+
+  public LONG_ARRAYHolder ()
+  {
+  }
+
+  public LONG_ARRAYHolder (long[] initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlag.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlag.java
new file mode 100644
index 0000000..f91647f
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlag.java
@@ -0,0 +1,48 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/SeverityFlag.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error severity flags.
+   */
+public class SeverityFlag implements org.omg.CORBA.portable.IDLEntity
+{
+  private        int __value;
+  private static int __size = 4;
+  private static com.highqsoft.corbafileserver.generated.SeverityFlag[] __array = new com.highqsoft.corbafileserver.generated.SeverityFlag [__size];
+
+  public static final int _SUCCESS = 0;
+  public static final com.highqsoft.corbafileserver.generated.SeverityFlag SUCCESS = new com.highqsoft.corbafileserver.generated.SeverityFlag(_SUCCESS);
+  public static final int _INFORMATION = 1;
+  public static final com.highqsoft.corbafileserver.generated.SeverityFlag INFORMATION = new com.highqsoft.corbafileserver.generated.SeverityFlag(_INFORMATION);
+  public static final int _WARNING = 2;
+  public static final com.highqsoft.corbafileserver.generated.SeverityFlag WARNING = new com.highqsoft.corbafileserver.generated.SeverityFlag(_WARNING);
+  public static final int _ERROR = 3;
+  public static final com.highqsoft.corbafileserver.generated.SeverityFlag ERROR = new com.highqsoft.corbafileserver.generated.SeverityFlag(_ERROR);
+
+  public int value ()
+  {
+    return __value;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.SeverityFlag from_int (int value)
+  {
+    if (value >= 0 && value < __size)
+      return __array[value];
+    else
+      throw new org.omg.CORBA.BAD_PARAM ();
+  }
+
+  protected SeverityFlag (int value)
+  {
+    __value = value;
+    __array[__value] = this;
+  }
+} // class SeverityFlag
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHelper.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHelper.java
new file mode 100644
index 0000000..28f7b5b
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHelper.java
@@ -0,0 +1,57 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/SeverityFlagHelper.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error severity flags.
+   */
+abstract public class SeverityFlagHelper
+{
+  private static String  _id = "IDL:com/highqsoft/corbafileserver/generated/SeverityFlag:1.0";
+
+  public static void insert (org.omg.CORBA.Any a, com.highqsoft.corbafileserver.generated.SeverityFlag that)
+  {
+    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+    a.type (type ());
+    write (out, that);
+    a.read_value (out.create_input_stream (), type ());
+  }
+
+  public static com.highqsoft.corbafileserver.generated.SeverityFlag extract (org.omg.CORBA.Any a)
+  {
+    return read (a.create_input_stream ());
+  }
+
+  private static org.omg.CORBA.TypeCode __typeCode = null;
+  synchronized public static org.omg.CORBA.TypeCode type ()
+  {
+    if (__typeCode == null)
+    {
+      __typeCode = org.omg.CORBA.ORB.init ().create_enum_tc (com.highqsoft.corbafileserver.generated.SeverityFlagHelper.id (), "SeverityFlag", new String[] { "SUCCESS", "INFORMATION", "WARNING", "ERROR"} );
+    }
+    return __typeCode;
+  }
+
+  public static String id ()
+  {
+    return _id;
+  }
+
+  public static com.highqsoft.corbafileserver.generated.SeverityFlag read (org.omg.CORBA.portable.InputStream istream)
+  {
+    return com.highqsoft.corbafileserver.generated.SeverityFlag.from_int (istream.read_long ());
+  }
+
+  public static void write (org.omg.CORBA.portable.OutputStream ostream, com.highqsoft.corbafileserver.generated.SeverityFlag value)
+  {
+    ostream.write_long (value.value ());
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHolder.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHolder.java
new file mode 100644
index 0000000..1c0f790
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/SeverityFlagHolder.java
@@ -0,0 +1,42 @@
+package com.highqsoft.corbafileserver.generated;
+
+/**
+* com/highqsoft/corbafileserver/generated/SeverityFlagHolder.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+
+/**
+   * The error severity flags.
+   */
+public final class SeverityFlagHolder implements org.omg.CORBA.portable.Streamable
+{
+  public com.highqsoft.corbafileserver.generated.SeverityFlag value = null;
+
+  public SeverityFlagHolder ()
+  {
+  }
+
+  public SeverityFlagHolder (com.highqsoft.corbafileserver.generated.SeverityFlag initialValue)
+  {
+    value = initialValue;
+  }
+
+  public void _read (org.omg.CORBA.portable.InputStream i)
+  {
+    value = com.highqsoft.corbafileserver.generated.SeverityFlagHelper.read (i);
+  }
+
+  public void _write (org.omg.CORBA.portable.OutputStream o)
+  {
+    com.highqsoft.corbafileserver.generated.SeverityFlagHelper.write (o, value);
+  }
+
+  public org.omg.CORBA.TypeCode _type ()
+  {
+    return com.highqsoft.corbafileserver.generated.SeverityFlagHelper.type ();
+  }
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_CORBAFileServerIFStub.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_CORBAFileServerIFStub.java
new file mode 100644
index 0000000..fd7e9f7
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_CORBAFileServerIFStub.java
@@ -0,0 +1,1136 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/_CORBAFileServerIFStub.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public class _CORBAFileServerIFStub extends org.omg.CORBA.portable.ObjectImpl implements com.highqsoft.corbafileserver.generated.CORBAFileServerIF
+{
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String save (org.asam.ods.AoSession aoSess, String name, String subDir, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("save", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write ($out, stream);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return save (aoSess, name, subDir, stream        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // save
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String saveForInstance (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("saveForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write ($out, stream);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return saveForInstance (aoSess, name, subDir, aid, iid, stream        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // saveForInstance
+
+
+  /**
+        * Save the data associated with the given intput stream.
+        * Specify the name of an applciation element and the name of the instance element
+        * that holds the external reference
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  subDir an alternative sub directory, that can be specified,
+        *                if the filename should not used to determine the destination folder.
+        * @param  aeName the application element name.
+        * @param  ieName the instance element name.
+        * @param  stream the input stream, ready to read by the server.
+        * @return the url string of the created file.
+        */
+  public String saveForInstanceName (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, com.highqsoft.corbafileserver.generated.InputStreamIF stream) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("saveForInstanceName", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                $out.write_string (aeName);
+                $out.write_string (ieName);
+                com.highqsoft.corbafileserver.generated.InputStreamIFHelper.write ($out, stream);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return saveForInstanceName (aoSess, name, subDir, aeName, ieName, stream        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // saveForInstanceName
+
+
+  /**
+        * Delete the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        */
+  public void delete (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("delete", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                delete (aoSess, name        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // delete
+
+
+  /**
+        * Move the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  urlo the url of the file.
+        */
+  public void move (org.asam.ods.AoSession aoSess, String url) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("move", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (url);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                move (aoSess, url        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // move
+
+
+  /**
+        * Delete the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  url the url of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  public void deleteForInstance (org.asam.ods.AoSession aoSess, String url, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("deleteForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (url);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                deleteForInstance (aoSess, url, aid, iid        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // deleteForInstance
+
+
+  /**
+        * Move the data associated with the given name.
+        * Specify the ApplicationElement id and the InstanceElement id
+        * of the component that holds the external reference.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        */
+  public void moveForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("moveForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                moveForInstance (aoSess, name, aid, iid        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // moveForInstance
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  public void getBySocket (org.asam.ods.AoSession aoSess, String name, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getBySocket", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (host);
+                $out.write_long (aPort);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                getBySocket (aoSess, name, host, aPort        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getBySocket
+
+
+  /**
+         * Get the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the url specification of the file.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         */
+  public void getForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getForInstanceBySocket", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $out.write_string (host);
+                $out.write_long (aPort);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                getForInstanceBySocket (aoSess, name, aid, iid, host, aPort        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getForInstanceBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("saveBySocket", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                $out.write_string (host);
+                $out.write_long (aPort);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return saveBySocket (aoSess, name, subDir, host, aPort        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // saveBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aid the application element id.
+         * @param  iid the instance element id.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveForInstanceBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("saveForInstanceBySocket", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $out.write_string (host);
+                $out.write_long (aPort);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return saveForInstanceBySocket (aoSess, name, subDir, aid, iid, host, aPort        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // saveForInstanceBySocket
+
+
+  /**
+         * Save the data using a socket.
+         *
+         * @throws CORBAFileServerException
+         * with the following possible error codes:
+         *    FILESERVER_CONNECT_FAILED
+         *    FILESERVER_BAD_PARAMETER
+         *    FILESERVER_CONNECTION_LOST
+         *    FILESERVER_IMPLEMENTATION_PROBLEM
+         *    FILESERVER_NOT_IMPLEMENTED
+         *    FILESERVER_NO_MEMORY
+         *
+         * @param  aoSess the ASAM ODS session.
+         * @param  name the name of the file.
+         * @param  subDir an alternative sub directory, that can be specified,
+         *                if the filename should not used to determine the destination folder.
+         * @param  aeName the application element name.
+         * @param  ieName the instance element name.
+         * @param  host the hostname for the socket connection.
+         * @param  port the port for the socket connection.
+         * @return the url string of the created file.
+         */
+  public String saveForInstanceNameBySocket (org.asam.ods.AoSession aoSess, String name, String subDir, String aeName, String ieName, String host, int aPort) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("saveForInstanceNameBySocket", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (subDir);
+                $out.write_string (aeName);
+                $out.write_string (ieName);
+                $out.write_string (host);
+                $out.write_long (aPort);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return saveForInstanceNameBySocket (aoSess, name, subDir, aeName, ieName, host, aPort        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // saveForInstanceNameBySocket
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  public com.highqsoft.corbafileserver.generated.InputStreamIF read (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("read", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $in = _invoke ($out);
+                com.highqsoft.corbafileserver.generated.InputStreamIF $result = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read ($in);
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return read (aoSess, name        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // read
+
+
+  /**
+        * Read the data associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  stream the input stream, ready to read by the server.
+        */
+  public com.highqsoft.corbafileserver.generated.InputStreamIF readForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("readForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $in = _invoke ($out);
+                com.highqsoft.corbafileserver.generated.InputStreamIF $result = com.highqsoft.corbafileserver.generated.InputStreamIFHelper.read ($in);
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return readForInstance (aoSess, name, aid, iid        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // readForInstance
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  size the size of the input stream.
+        */
+  public long getSize (org.asam.ods.AoSession aoSess, String name) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getSize", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $in = _invoke ($out);
+                long $result = $in.read_longlong ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getSize (aoSess, name        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getSize
+
+
+  /**
+        *  Get size of the file associated with the given name.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  size the size of the input stream.
+        */
+  public long getSizeForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getSizeForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $in = _invoke ($out);
+                long $result = $in.read_longlong ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getSizeForInstance (aoSess, name, aid, iid        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getSizeForInstance
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  public void terminate (org.asam.ods.AoSession aoSess, String name, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("terminate", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                $out.write_string (parameter);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                terminate (aoSess, name, parameter        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // terminate
+
+
+  /**
+        * This method can be called by the client when the server should be start a termination process.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECT_FAILED
+        *    FILESERVER_BAD_PARAMETER
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param  name the name of the file.
+        * @param  aid the application element id.
+        * @param  iid the instance element id.
+        * @param  parameter the parameter string. The content depends on the
+        *         server side terminate implementation.
+        */
+  public void terminateForInstance (org.asam.ods.AoSession aoSess, String name, org.asam.ods.T_LONGLONG aid, org.asam.ods.T_LONGLONG iid, String parameter) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("terminateForInstance", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (name);
+                org.asam.ods.T_LONGLONGHelper.write ($out, aid);
+                org.asam.ods.T_LONGLONGHelper.write ($out, iid);
+                $out.write_string (parameter);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                terminateForInstance (aoSess, name, aid, iid, parameter        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // terminateForInstance
+
+
+  /**
+        * Get the name of the host where the server is running
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return the hostname
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public String getHostname (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getHostname", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getHostname (aoSess        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getHostname
+
+
+  /**
+        * Get a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @return the context value
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY,
+        *    FILESERVER_NOT_FOUND
+        */
+  public String getContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getContext", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (key);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getContext (aoSess, key        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getContext
+
+
+  /**
+        * Set a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @param value the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public void setContext (org.asam.ods.AoSession aoSess, String key, String value) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("setContext", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (key);
+                $out.write_string (value);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                setContext (aoSess, key, value        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // setContext
+
+
+  /**
+        * Remove a context variable.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @param key the keyword of the context value.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public void removeContext (org.asam.ods.AoSession aoSess, String key) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("removeContext", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $out.write_string (key);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                removeContext (aoSess, key        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // removeContext
+
+
+  /**
+        * List all context keywords.
+        *
+        * @param  aoSess the ASAM ODS session.
+        * @return a sequence of strings.
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        */
+  public String[] listContext (org.asam.ods.AoSession aoSess) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("listContext", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                $in = _invoke ($out);
+                String $result[] = com.highqsoft.corbafileserver.generated.DS_STRINGHelper.read ($in);
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return listContext (aoSess        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // listContext
+
+
+  /**
+        * Get the version of the CorbaFileServerIF.
+        * Returns getVersion of CorbaFileServer.
+        *
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        * @return  The interface version of the CorbaFileServerIF.
+        *
+        */
+  public String getInterfaceVersion () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getInterfaceVersion", true);
+                $in = _invoke ($out);
+                String $result = $in.read_string ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getInterfaceVersion (        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getInterfaceVersion
+
+
+  /**
+        * Returns an array of long values representing the length
+        * of the files that were provided in the String array.
+        * The order of the long values must match with the order
+        * of the filenames.
+        *
+        * @param aoSess the aoSession of the caller
+        * @param names the String array of filenames for 
+        *              which to get the sizes
+        * @return an Array of long values containing the file sizes
+        * @throws CORBAFileServerException
+        * with the following possible error codes:
+        *    FILESERVER_CONNECTION_LOST
+        *    FILESERVER_IMPLEMENTATION_PROBLEM
+        *    FILESERVER_NOT_IMPLEMENTED
+        *    FILESERVER_NO_MEMORY
+        *
+        *
+        */
+  public long[] getSizes (org.asam.ods.AoSession aoSess, String[] names) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("getSizes", true);
+                org.asam.ods.AoSessionHelper.write ($out, aoSess);
+                com.highqsoft.corbafileserver.generated.DS_STRINGHelper.write ($out, names);
+                $in = _invoke ($out);
+                long $result[] = com.highqsoft.corbafileserver.generated.LONG_ARRAYHelper.read ($in);
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return getSizes (aoSess, names        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // getSizes
+
+  // Type-specific CORBA::Object operations
+  private static String[] __ids = {
+    "IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerIF:1.0"};
+
+  public String[] _ids ()
+  {
+    return (String[])__ids.clone ();
+  }
+
+  private void readObject (java.io.ObjectInputStream s) throws java.io.IOException
+  {
+     String str = s.readUTF ();
+     String[] args = null;
+     java.util.Properties props = null;
+     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);
+   try {
+     org.omg.CORBA.Object obj = orb.string_to_object (str);
+     org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
+     _set_delegate (delegate);
+   } finally {
+     orb.destroy() ;
+   }
+  }
+
+  private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException
+  {
+     String[] args = null;
+     java.util.Properties props = null;
+     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);
+   try {
+     String str = orb.object_to_string (this);
+     s.writeUTF (str);
+   } finally {
+     orb.destroy() ;
+   }
+  }
+} // class _CORBAFileServerIFStub
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_InputStreamIFStub.java b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_InputStreamIFStub.java
new file mode 100644
index 0000000..e6a97ec
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/com/highqsoft/corbafileserver/generated/_InputStreamIFStub.java
@@ -0,0 +1,207 @@
+package com.highqsoft.corbafileserver.generated;
+
+
+/**
+* com/highqsoft/corbafileserver/generated/_InputStreamIFStub.java .
+* Generated by the IDL-to-Java compiler (portable), version "3.2"
+* from src/main/idl/corbafileserver.idl
+* Donnerstag, 16. Juni 2016 10:30 Uhr MESZ
+*/
+
+public class _InputStreamIFStub extends org.omg.CORBA.portable.ObjectImpl implements com.highqsoft.corbafileserver.generated.InputStreamIF
+{
+
+
+  /**
+        * Reads up to len bytes of data from the input stream into an array
+        * of bytes. An attempt is made to read as many as len bytes, but a
+        * smaller number may be read, possibly zero. The number of bytes
+        * actually read is returned as an integer.
+        *
+        * This method blocks until input data is available, end of file
+        * is detected, or an exception is thrown.
+        *
+        * If b is null, a NullPointerException is thrown.
+        *
+        * If off is negative, or len is negative, or off+len is greater
+        * than the length of the array b, then an IndexOutOfBoundsException is thrown.
+        *
+        * If len is zero, then no bytes are read and 0 is returned;
+        * otherwise, there is an attempt to read at least one byte.
+        * If no byte is available because the stream is at end of file,
+        * the value -1 is returned; otherwise, at least one byte is read and stored into b.
+        *
+        * The first byte read is stored into element b[off], the next one into b[off+1],
+        * and so on. The number of bytes read is, at most, equal to len. Let k be the number
+        * of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1],
+        * leaving elements b[off+k] through b[off+len-1] unaffected.
+        *
+        * In every case, elements b[0] through b[off] and elements b[off+len]
+        * through b[b.length-1] are unaffected.
+        *
+        * If the first byte cannot be read for any reason other than end of file,
+        * then an IOException is thrown. In particular, an IOException is thrown
+        * if the input stream has been closed.
+        *
+        * The read(b, off, len) method for class InputStream simply calls the method
+        * read() repeatedly. If the first such call results in an IOException,
+        * that exception is returned from the call to the read(b, off, len) method.
+        * If any subsequent call to read() results in a IOException, the exception
+        * is caught and treated as if it were end of file; the bytes read up to that
+        * point are stored into b and the number of bytes read before the exception
+        * occurred is returned. Subclasses are encouraged to provide a more efficient
+        * implementation of this method.
+        *
+        * @param b - the buffer into which the data is read.
+        * @param off - the start offset in array b  at which the data is written.
+        * @param len - the maximum number of bytes to read.
+        * @return the total number of bytes read into the buffer,
+        *         or -1 is there is no more data because the end
+        *         of the stream has been reached.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public int read (com.highqsoft.corbafileserver.generated.DS_BYTEHolder b, int off, int len) throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("read", true);
+                $out.write_long (off);
+                $out.write_long (len);
+                $in = _invoke ($out);
+                int $result = $in.read_long ();
+                b.value = com.highqsoft.corbafileserver.generated.DS_BYTEHelper.read ($in);
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return read (b, off, len        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // read
+
+
+  /**
+        * Close the input stream.
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public void close () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("close", true);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                close (        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // close
+
+
+  /**
+        * Get the length of the input stream.
+        *
+        * @return the length of the file to be transferd.
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public int length () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("length", true);
+                $in = _invoke ($out);
+                int $result = $in.read_long ();
+                return $result;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                return length (        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // length
+
+
+  /**
+        * Reset the stream
+        *
+        * @throws CORBAFileServerException if an IO exception occurs.
+        */
+  public void reset () throws com.highqsoft.corbafileserver.generated.CORBAFileServerException
+  {
+            org.omg.CORBA.portable.InputStream $in = null;
+            try {
+                org.omg.CORBA.portable.OutputStream $out = _request ("reset", true);
+                $in = _invoke ($out);
+                return;
+            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
+                $in = $ex.getInputStream ();
+                String _id = $ex.getId ();
+                if (_id.equals ("IDL:com/highqsoft/corbafileserver/generated/CORBAFileServerException:1.0"))
+                    throw com.highqsoft.corbafileserver.generated.CORBAFileServerExceptionHelper.read ($in);
+                else
+                    throw new org.omg.CORBA.MARSHAL (_id);
+            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
+                reset (        );
+            } finally {
+                _releaseReply ($in);
+            }
+  } // reset
+
+  // Type-specific CORBA::Object operations
+  private static String[] __ids = {
+    "IDL:com/highqsoft/corbafileserver/generated/InputStreamIF:1.0"};
+
+  public String[] _ids ()
+  {
+    return (String[])__ids.clone ();
+  }
+
+  private void readObject (java.io.ObjectInputStream s) throws java.io.IOException
+  {
+     String str = s.readUTF ();
+     String[] args = null;
+     java.util.Properties props = null;
+     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);
+   try {
+     org.omg.CORBA.Object obj = orb.string_to_object (str);
+     org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
+     _set_delegate (delegate);
+   } finally {
+     orb.destroy() ;
+   }
+  }
+
+  private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException
+  {
+     String[] args = null;
+     java.util.Properties props = null;
+     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);
+   try {
+     String str = orb.object_to_string (this);
+     s.writeUTF (str);
+   } finally {
+     orb.destroy() ;
+   }
+  }
+} // class _InputStreamIFStub
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java
new file mode 100644
index 0000000..2e40f5c
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java
@@ -0,0 +1,230 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.asam.ods.AoException;
+import org.asam.ods.AoSession;
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.file.FileService;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.dflt.model.EntityFactory;
+import org.eclipse.mdm.api.odsadapter.filetransfer.CORBAFileService;
+import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.notification.ODSNotificationServiceFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.query.ODSQueryService;
+import org.eclipse.mdm.api.odsadapter.search.ODSSearchService;
+import org.omg.CORBA.ORB;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.highqsoft.corbafileserver.generated.CORBAFileServerIF;
+
+/**
+ * ODSContext encapsulates a session to the ASAM ODS CORBA API and provides the
+ * ODS specific services implementations.
+ *
+ * @since 1.0.0
+ */
+public class ODSContext implements ApplicationContext {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSContext.class);
+
+	private Map<String, String> parameters;
+	private final Transfer transfer = Transfer.SOCKET;
+
+	private CORBAFileServerIF fileServer;
+	private ODSModelManager modelManager;
+	private ODSQueryService queryService;
+	private EntityLoader entityLoader;
+	private ODSEntityManager entityManager;
+	private ODSSearchService searchService;
+
+	/**
+	 * Creates a new ODS application context.
+	 * 
+	 * @param orb        the CORBA ORB used to connect to the ODS API
+	 * @param aoSession
+	 * @param fileServer
+	 * @param parameters
+	 * @throws AoException
+	 */
+	public ODSContext(ORB orb, AoSession aoSession, CORBAFileServerIF fileServer, Map<String, String> parameters)
+			throws AoException {
+		this.fileServer = fileServer;
+		this.parameters = parameters;
+
+		this.modelManager = new ODSModelManager(orb, aoSession);
+		this.queryService = new ODSQueryService(this.modelManager);
+		this.entityManager = new ODSEntityManager(this);
+		this.entityLoader = new EntityLoader(modelManager, queryService);
+		this.searchService = new ODSSearchService(this, queryService, entityLoader);
+		LOGGER.debug("ODSContext initialized.");
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<EntityManager> getEntityManager() {
+		return Optional.of(entityManager);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<EntityFactory> getEntityFactory() {
+		try {
+			return Optional.of(new ODSEntityFactory(modelManager, entityManager.loadLoggedOnUser()));
+		} catch (DataAccessException e) {
+			throw new IllegalStateException("Unable to load instance of the logged in user.");
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<ModelManager> getModelManager() {
+		return Optional.of(modelManager);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<QueryService> getQueryService() {
+		// TODO
+		// java docs: cache this service for ONE request!
+		return Optional.of(new ODSQueryService(modelManager));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<SearchService> getSearchService() {
+		return Optional.of(searchService);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<FileService> getFileService() {
+		if (fileServer == null) {
+			return Optional.empty();
+		}
+		return Optional.of(new CORBAFileService(this, transfer));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<NotificationService> getNotificationService() {
+		try {
+			return Optional.of(new ODSNotificationServiceFactory().create(this, parameters));
+		} catch (ConnectionException e) {
+			throw new IllegalStateException("Unable to create notification manager.", e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Map<String, String> getParameters() {
+		return parameters;
+	}
+
+	/**
+	 * @returns the string "ods"
+	 */
+	@Override
+	public String getAdapterType() {
+		return "ods";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void close() {
+		try {
+			modelManager.close();
+		} catch (AoException e) {
+			LOGGER.warn("Unable to close sesssion due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Returns the {@link ODSModelManager} used for this context.
+	 * 
+	 * @return the {@link ODSModelManager}
+	 */
+	public ODSModelManager getODSModelManager() {
+		return modelManager;
+	}
+
+	/**
+	 * Returns the {@link AoSession} used for this context.
+	 * 
+	 * @return {@link AoSession} used for this context.
+	 */
+	public AoSession getAoSession() {
+		return modelManager.getAoSession();
+	}
+
+	/**
+	 * Returns the ORB used for this context
+	 * 
+	 * @return ORB used for this context
+	 */
+	public ORB getORB() {
+		return modelManager.getORB();
+	}
+
+	/**
+	 * Returns the {@link CORBAFileServerIF}.
+	 *
+	 * @return The {@code CORBAFileServerIF} is returned or null, if missing.
+	 */
+	public CORBAFileServerIF getFileServer() {
+		return fileServer;
+	}
+
+	/**
+	 * Returns a new {@link ODSContext} with a new ODS co-session.
+	 *
+	 * @return The created {@code ODSContext} is returned.
+	 * @throws AoException Thrown on errors.
+	 */
+	public ODSContext newContext() throws AoException {
+		return new ODSContext(modelManager.getORB(), getAoSession().createCoSession(), fileServer, parameters);
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java
new file mode 100644
index 0000000..0310632
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java
@@ -0,0 +1,237 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.asam.ods.AoException;
+import org.asam.ods.AoFactory;
+import org.asam.ods.AoFactoryHelper;
+import org.asam.ods.AoSession;
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.ApplicationContextFactory;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Object;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.highqsoft.corbafileserver.generated.CORBAFileServerIF;
+import com.highqsoft.corbafileserver.generated.CORBAFileServerIFHelper;
+
+/**
+ * ASAM ODS implementation of the {@link ApplicationContextFactory} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class ODSContextFactory implements ApplicationContextFactory {
+
+	public static final String PARAM_NAMESERVICE = "nameservice";
+
+	public static final String PARAM_SERVICENAME = "servicename";
+
+	public static final String PARAM_USER = "user";
+
+	public static final String PARAM_PASSWORD = "password";
+
+	private static final String PARAM_FOR_USER = "for_user";
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSContextFactory.class);
+
+	private static final ORB orb = ORB.init(new String[] {}, System.getProperties());
+
+	public ODSContextFactory() {
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>
+	 * <b>Note:</b> Given parameters {@code Map} must contain values for each of the
+	 * following keys:
+	 *
+	 * <ul>
+	 * <li>{@value #PARAM_NAMESERVICE}</li>
+	 * <li>{@value #PARAM_SERVICENAME}</li>
+	 * <li>{@value #PARAM_USER}</li>
+	 * <li>{@value #PARAM_PASSWORD}</li>
+	 * </ul>
+	 *
+	 * Listed names are available via public fields of this class.
+	 */
+	@Override
+	public ApplicationContext connect(Map<String, String> parameters) throws ConnectionException {
+		AoSession aoSession = null;
+		try (ServiceLocator serviceLocator = new ServiceLocator(orb, getParameter(parameters, PARAM_NAMESERVICE))) {
+			String nameOfService = getParameter(parameters, PARAM_SERVICENAME).replace(".ASAM-ODS", "");
+
+			AoFactory aoFactory = serviceLocator.resolveFactory(nameOfService);
+			String aoFactoryName = aoFactory.getName();
+			LOGGER.info("Connecting to ODS Server (name: {}, description: {}, interface version: {}, type: {}) ...",
+					aoFactoryName, aoFactory.getDescription(), aoFactory.getInterfaceVersion(), aoFactory.getType());
+
+			// Create a parameters map without password (which should not be visible from
+			// this point onwards),
+			// leaving the original map untouched:
+			Map<String, String> parametersWithoutPassword = new HashMap<>(parameters);
+			if (LOGGER.isDebugEnabled()) {
+				parametersWithoutPassword.put(PARAM_PASSWORD, "****");
+				LOGGER.debug("Connecting to ODS using the connection parameters: {}",
+						sessionParametersAsString(parametersWithoutPassword));
+			}
+			parametersWithoutPassword.remove(PARAM_PASSWORD);
+
+			aoSession = aoFactory.newSession(sessionParametersAsString(parameters));
+
+			LOGGER.info("Connection to ODS server '{}' established.", aoFactoryName);
+
+			CORBAFileServerIF fileServer = serviceLocator.resolveFileServer(nameOfService);
+
+			return new ODSContext(orb, aoSession, fileServer, parametersWithoutPassword);
+		} catch (AoException e) {
+			closeSession(aoSession);
+			throw new ConnectionException("Unable to connect to ODS server due to: " + e.reason, e);
+		}
+	}
+
+	private String sessionParametersAsString(Map<String, String> parameters) throws ConnectionException {
+		ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder()
+				.put("USER", getParameter(parameters, PARAM_USER))
+				.put("PASSWORD", getParameter(parameters, PARAM_PASSWORD)).put("CREATE_COSESSION_ALLOWED", "TRUE");
+
+		String forUserName = parameters.get(PARAM_FOR_USER);
+		if (!Strings.isNullOrEmpty(forUserName)) {
+			builder.put("FOR_USER", forUserName);
+		}
+		return Joiner.on(",").withKeyValueSeparator("=").join(builder.build());
+	}
+
+	/**
+	 * Closes given {@link AoSession} with catching and logging errors.
+	 *
+	 * @param aoSession The {@code AoSession} that shall be closed.
+	 */
+	private static void closeSession(AoSession aoSession) {
+		if (aoSession == null) {
+			return;
+		}
+
+		try {
+			aoSession.close();
+		} catch (AoException e) {
+			LOGGER.warn("Unable to close sesssion due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Reads the property identified by given property name.
+	 *
+	 * @param parameters The properties {@code Map}.
+	 * @param name       The property name.
+	 * @return The property value is returned.
+	 * @throws ConnectionException Thrown if property does not exist or is empty.
+	 */
+	private static String getParameter(Map<String, String> parameters, String name) throws ConnectionException {
+		String value = parameters.get(name);
+		if (value == null || value.isEmpty()) {
+			throw new ConnectionException("Connection parameter with name '" + name + "' is either missing or empty.");
+		}
+
+		return value;
+	}
+
+	/**
+	 * Used to resolve CORBA service object by ID and kind.
+	 */
+	private static final class ServiceLocator implements AutoCloseable {
+
+		private NamingContextExt namingContext;
+
+		/**
+		 * Constructor.
+		 *
+		 * @param orb  The {@link ORB} singleton instance.
+		 * @param path The naming context path.
+		 * @throws ConnectionException Thrown if unable to resolve the naming context.
+		 */
+		public ServiceLocator(ORB orb, String path) throws ConnectionException {
+			namingContext = NamingContextExtHelper.narrow(orb.string_to_object(path));
+			if (namingContext == null) {
+				throw new ConnectionException("Unable to resolve NameService '" + path + "'.");
+			}
+		}
+
+		/**
+		 * Resolves and returns the {@link AoFactory} service for given ID.
+		 *
+		 * @param id Used as identifier.
+		 * @return The {@code AoFactory} is returned.
+		 * @throws ConnectionException Thrown if unable to resolve the {@code
+		 * 		AoFactory}          .
+		 */
+		public AoFactory resolveFactory(String id) throws ConnectionException {
+			return AoFactoryHelper.narrow(resolve(id, "ASAM-ODS"));
+		}
+
+		/**
+		 * Resolves and returns the {@link CORBAFileServerIF} service for given ID.
+		 *
+		 * @param id Used as identifier.
+		 * @return The {@code CORBAFileServerIF} or null, if none found, is returned.
+		 */
+		public CORBAFileServerIF resolveFileServer(String id) {
+			try {
+				return CORBAFileServerIFHelper.narrow(resolve(id, "CORBA-FT"));
+			} catch (ConnectionException e) {
+				LOGGER.warn(e.getMessage());
+				return null;
+			}
+		}
+
+		/**
+		 * Resolves a CORBA service object for given id and kind.
+		 *
+		 * @param id   Used as identifier.
+		 * @param kind Used as qualifier.
+		 * @return The resolved CORBA service object is returned.
+		 * @throws ConnectionException Thrown in case of errors.
+		 */
+		public Object resolve(String id, String kind) throws ConnectionException {
+			try {
+				return namingContext.resolve(new NameComponent[] { new NameComponent(id, kind) });
+			} catch (NotFound | CannotProceed | InvalidName e) {
+				throw new ConnectionException("Unable to resolve service '" + id + "." + kind + "'.", e);
+			}
+		}
+
+		@Override
+		public void close() throws ConnectionException {
+			namingContext._release();
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
new file mode 100644
index 0000000..3be7627
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
@@ -0,0 +1,467 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.asam.ods.AoException;
+import org.asam.ods.ApplicationStructure;
+import org.asam.ods.ElemId;
+import org.asam.ods.InstanceElement;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.massdata.ReadRequest;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.ContextDescribable;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Environment;
+import org.eclipse.mdm.api.base.model.MeasuredValues;
+import org.eclipse.mdm.api.base.model.StatusAttachable;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.dflt.model.Classification;
+import org.eclipse.mdm.api.dflt.model.Status;
+import org.eclipse.mdm.api.dflt.model.TemplateTest;
+import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
+import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.transaction.ODSTransaction;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ASAM ODS implementation of the {@link EntityManager} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class ODSEntityManager implements EntityManager {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSEntityManager.class);
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+	private final Transfer transfer = Transfer.SOCKET;
+
+	private final ODSContext context;
+	private final ODSModelManager odsModelManager;
+	private final QueryService queryService;
+	private final EntityLoader entityLoader;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param context The {@link ODSContext}.
+	 */
+	public ODSEntityManager(ODSContext context) {
+		this.context = context;
+		this.odsModelManager = context.getODSModelManager();
+		this.queryService = context.getQueryService()
+				.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
+		entityLoader = new EntityLoader(odsModelManager, queryService);
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Environment loadEnvironment() throws DataAccessException {
+		List<Environment> environments = loadAll(Environment.class);
+		if (environments.size() != 1) {
+			throw new DataAccessException("Unable to laod the environment entity.");
+		}
+
+		return environments.get(0);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<User> loadLoggedOnUser() throws DataAccessException {
+		InstanceElement ieUser = null;
+		try {
+			ieUser = odsModelManager.getAoSession().getUser();
+			return Optional.of(
+					entityLoader.load(new Key<>(User.class), Long.toString(ODSConverter.fromODSLong(ieUser.getId()))));
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to load the logged in user entity due to: " + e.reason, e);
+		} finally {
+			try {
+				if (ieUser != null) {
+					ieUser.destroy();
+					ieUser._release();
+				}
+			} catch (AoException aoe) {
+				LOGGER.warn("Unable to destroy the CORBA resource due to: " + aoe.reason, aoe);
+				ieUser._release();
+			}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> load(Class<T> entityClass, Collection<String> instanceIDs)
+			throws DataAccessException {
+		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> load(Class<T> entityClass, ContextType contextType,
+			Collection<String> instanceIDs) throws DataAccessException {
+		return entityLoader.loadAll(new Key<>(entityClass, contextType), instanceIDs);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> Optional<T> loadParent(Entity child, Class<T> entityClass) throws DataAccessException {
+		EntityType parentEntityType = odsModelManager.getEntityType(entityClass);
+		EntityType childEntityType = odsModelManager.getEntityType(child);
+		Query query = queryService.createQuery().selectID(parentEntityType);
+
+		if (child instanceof Channel && ChannelGroup.class.equals(entityClass)) {
+			// this covers the gap between channel and channel group via local
+			// column
+			EntityType localColumnEntityType = odsModelManager.getEntityType("LocalColumn");
+			query.join(childEntityType, localColumnEntityType).join(localColumnEntityType, parentEntityType);
+		} else {
+			query.join(childEntityType, parentEntityType);
+		}
+
+		Optional<String> instanceID = query.fetchSingleton(Filter.idOnly(childEntityType, child.getID()))
+				.map(r -> r.getRecord(parentEntityType)).map(Record::getID);
+		if (instanceID.isPresent()) {
+			return Optional.of(entityLoader.load(new Key<>(entityClass), instanceID.get()));
+		}
+
+		return Optional.empty();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> loadAll(Class<T> entityClass, String pattern) throws DataAccessException {
+		return entityLoader.loadAll(new Key<>(entityClass), pattern);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends StatusAttachable> List<T> loadAll(Class<T> entityClass, Status status, String pattern)
+			throws DataAccessException {
+		EntityType entityType = odsModelManager.getEntityType(entityClass);
+		EntityType classificationType = odsModelManager.getEntityType(Classification.class);
+		EntityType statusEntityType = odsModelManager.getEntityType(status.getTypeName());
+
+		List<String> instanceIDs = queryService.createQuery().join(entityType, classificationType)
+				.join(classificationType, statusEntityType).selectID(entityType)
+				.fetch(Filter.and().id(statusEntityType, status.getID()).name(entityType, pattern)).stream()
+				.map(r -> r.getRecord(entityType)).map(Record::getID).collect(Collectors.toList());
+
+		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
+	}
+
+	/*
+	 * @Override public List<Status> loadAllStatus(Class<? extends StatusAttachable>
+	 * entityClass, String pattern) throws DataAccessException { return
+	 * entityLoader.loadAll(new Key<>(Status.class, entityClass), pattern); }
+	 */
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> loadAll(Class<T> entityClass, ContextType contextType, String pattern)
+			throws DataAccessException {
+		return entityLoader.loadAll(new Key<>(entityClass, contextType), pattern);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> loadChildren(Entity parent, Class<T> entityClass, String pattern)
+			throws DataAccessException {
+		EntityType parentEntityType = odsModelManager.getEntityType(parent);
+		EntityType childEntityType = odsModelManager.getEntityType(entityClass);
+		Query query = queryService.createQuery();
+
+		if (parent instanceof ChannelGroup && Channel.class.equals(entityClass)) {
+			// this covers the gap between channel and channel group via local
+			// column
+			EntityType localColumnEntityType = odsModelManager.getEntityType("LocalColumn");
+			query.join(childEntityType, localColumnEntityType).join(localColumnEntityType, parentEntityType);
+		} else {
+			query.join(childEntityType, parentEntityType);
+		}
+
+		List<String> instanceIDs = query.selectID(childEntityType)
+				.fetch(Filter.and().id(parentEntityType, parent.getID()).name(childEntityType, pattern)).stream()
+				.map(r -> r.getRecord(childEntityType)).map(Record::getID).collect(Collectors.toList());
+		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
+	}
+
+	// /**
+	// * {@inheritDoc}
+	// */
+	// @Override
+	// public <T extends StatusAttachable> List<T> loadChildren(Entity parent,
+	// Class<T> entityClass, Status status,
+	// String pattern) throws DataAccessException {
+	// EntityType parentEntityType = modelManager.getEntityType(parent);
+	// EntityType childEntityType = modelManager.getEntityType(entityClass);
+	// EntityType statusEntityType =
+	// modelManager.getEntityType(status.getTypeName());
+	//
+	// List<String> instanceIDs = modelManager.createQuery()
+	// .join(childEntityType, parentEntityType, statusEntityType)
+	// .selectID(childEntityType)
+	// .fetch(Filter.and()
+	// .id(parentEntityType, parent.getID())
+	// .id(statusEntityType, status.getID())
+	// .name(childEntityType, pattern))
+	// .stream().map(r ->
+	// r.getRecord(childEntityType)).map(Record::getID).collect(Collectors.toList());
+	//
+	// return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
+	// }
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<ContextType> loadContextTypes(ContextDescribable contextDescribable) throws DataAccessException {
+		EntityType contextDescribableEntityType = odsModelManager.getEntityType(contextDescribable);
+		Query query = queryService.createQuery();
+
+		Map<ContextType, EntityType> contextRootEntityTypes = new EnumMap<>(ContextType.class);
+		for (ContextType contextType : ContextType.values()) {
+			EntityType entityType = odsModelManager.getEntityType(ContextRoot.class, contextType);
+			contextRootEntityTypes.put(contextType, entityType);
+			query.join(contextDescribableEntityType.getRelation(entityType), JoinType.OUTER).selectID(entityType);
+		}
+
+		Optional<Result> result = query
+				.fetchSingleton(Filter.idOnly(contextDescribableEntityType, contextDescribable.getID()));
+		if (result.isPresent()) {
+			List<ContextType> contextTypes = new ArrayList<>();
+			for (Entry<ContextType, EntityType> entry : contextRootEntityTypes.entrySet()) {
+				Optional<String> instanceID = result.map(r -> r.getRecord(entry.getValue())).map(Record::getID);
+				if (instanceID.isPresent()) {
+					contextTypes.add(entry.getKey());
+				}
+			}
+
+			return contextTypes;
+		}
+
+		return Collections.emptyList();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Map<ContextType, ContextRoot> loadContexts(ContextDescribable contextDescribable,
+			ContextType... contextTypes) throws DataAccessException {
+		EntityType contextDescribableEntityType = odsModelManager.getEntityType(contextDescribable);
+		Query query = queryService.createQuery();
+
+		Map<ContextType, EntityType> contextRootEntityTypes = new EnumMap<>(ContextType.class);
+		for (ContextType contextType : contextTypes.length == 0 ? ContextType.values() : contextTypes) {
+			EntityType entityType = odsModelManager.getEntityType(ContextRoot.class, contextType);
+			contextRootEntityTypes.put(contextType, entityType);
+			query.join(contextDescribableEntityType.getRelation(entityType), JoinType.OUTER).selectID(entityType);
+		}
+
+		Optional<Result> result = query
+				.fetchSingleton(Filter.idOnly(contextDescribableEntityType, contextDescribable.getID()));
+		if (result.isPresent()) {
+			Map<ContextType, ContextRoot> contextRoots = new EnumMap<>(ContextType.class);
+			for (Entry<ContextType, EntityType> entry : contextRootEntityTypes.entrySet()) {
+				String instanceID = result.get().getRecord(entry.getValue()).getID();
+				if (ODSUtils.isValidID(instanceID)) {
+					contextRoots.put(entry.getKey(),
+							entityLoader.load(new Key<>(ContextRoot.class, entry.getKey()), instanceID));
+				}
+			}
+
+			return contextRoots;
+		}
+
+		return Collections.emptyMap();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T extends Entity> List<T> loadRelatedEntities(Entity entity, String relationName, Class<T> relatedClass) {
+		ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity));
+		ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID()));
+
+		try {
+			T_LONGLONG[] instanceIds = context.getAoSession().getApplElemAccess().getRelInst(elemId, relationName);
+			List<String> instanceIDs = Stream.of(instanceIds).map(ODSConverter::fromODSLong).map(l -> l.toString())
+					.collect(Collectors.toList());
+			return entityLoader.loadAll(new Key<>(relatedClass), instanceIDs);
+		} catch (AoException e) {
+			throw new DataAccessException("" + e.reason, e); // TODO
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<MeasuredValues> readMeasuredValues(ReadRequest readRequest) throws DataAccessException {
+		return new ReadRequestHandler(odsModelManager, queryService).execute(readRequest);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Transaction startTransaction() throws DataAccessException {
+		try {
+			return new ODSTransaction(context, loadEnvironment(), transfer);
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to start transaction due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Retrives the ASAM paths for the given entities. The ASAM paths are prefixed
+	 * with a servicename, in the form
+	 * <code>corbaloc:[iop|ssliop]:1.2@HOSTNAME:PORT/NameService/MDM.ASAM-ODS/</code>
+	 * 
+	 * @returns returns a map with the ASAM paths to the given entities. If a entity
+	 *          is not found in the ODS server the entity is not included in the
+	 *          result map.
+	 * @throws DataAccessException      if links could not be loaded for the given
+	 *                                  entities
+	 * @throws IllegalArgumentException if a the source or typeName of an entity is
+	 *                                  invalid
+	 * @see org.eclipse.mdm.api.base.BaseEntityManager#getLinks(Collection)
+	 */
+	@Override
+	public Map<Entity, String> getLinks(Collection<Entity> entities) throws DataAccessException {
+
+		Map<Entity, String> linkMap = new HashMap<>();
+
+		ApplicationStructure appStructure;
+		try {
+			appStructure = odsModelManager.getAoSession().getApplicationStructure();
+		} catch (AoException e) {
+			throw new DataAccessException("Could not load application structure! Reason: " + e.reason, e);
+		}
+
+		String serverRoot = context.getParameters().get(ODSContextFactory.PARAM_NAMESERVICE) + "/"
+				+ context.getParameters().get(ODSContextFactory.PARAM_SERVICENAME);
+
+		Map<String, List<Entity>> entitiesByTypeName = entities.stream().filter(e -> e.getTypeName() != null)
+				.collect(Collectors.groupingBy(Entity::getTypeName));
+
+		for (Map.Entry<String, List<Entity>> entry : entitiesByTypeName.entrySet()) {
+			ODSEntityType et = (ODSEntityType) odsModelManager.getEntityType(entry.getKey());
+
+			List<ElemId> elemIds = entry.getValue().stream()
+					.map(e -> new ElemId(et.getODSID(), ODSConverter.toODSLong(Long.parseLong(e.getID()))))
+					.collect(Collectors.toList());
+
+			try {
+				InstanceElement[] instances = appStructure.getInstancesById(elemIds.toArray(new ElemId[0]));
+
+				for (InstanceElement ie : instances) {
+					String id = Long.toString(ODSConverter.fromODSLong(ie.getId()));
+					String asamPath = serverRoot + ie.getAsamPath();
+					entry.getValue().stream().filter(e -> e.getID().equals(id)).findFirst()
+							.ifPresent(e -> linkMap.put(e, asamPath));
+				}
+			} catch (AoException e) {
+				LOGGER.debug("Could not load links for entities: " + entities + ". Reason: " + e.reason, e);
+			}
+		}
+
+		return linkMap;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<TemplateTest> loadTemplate(Test test) {
+		return Optional.ofNullable(ODSEntityFactory.extract(test).getMutableStore().get(TemplateTest.class));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<TemplateTestStep> loadTemplate(TestStep testStep) {
+		return Optional.ofNullable(ODSEntityFactory.extract(testStep).getMutableStore().get(TemplateTestStep.class));
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java
new file mode 100644
index 0000000..bd6b2d0
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java
@@ -0,0 +1,377 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.asam.ods.AoException;
+import org.asam.ods.Column;
+import org.asam.ods.ElemId;
+import org.asam.ods.NameValueSeqUnit;
+import org.asam.ods.T_LONGLONG;
+import org.asam.ods.ValueMatrix;
+import org.asam.ods.ValueMatrixMode;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.massdata.ReadRequest;
+import org.eclipse.mdm.api.base.massdata.ReadRequest.ValuesMode;
+import org.eclipse.mdm.api.base.model.AxisType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.MeasuredValues;
+import org.eclipse.mdm.api.base.model.SequenceRepresentation;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Reads mass data specified in {@link ReadRequest}s.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ReadRequestHandler {
+	public static final class ColumnAttributes {
+		private String name;
+		private SequenceRepresentation sequenceRepresentation;
+		private double[] generationParameters;
+		private boolean independent;
+		private AxisType axisType;
+
+		public ColumnAttributes(String name, SequenceRepresentation sequenceRepresentation,
+				double[] generationParameters, boolean independent, AxisType axisType) {
+			this.name = name;
+			this.sequenceRepresentation = sequenceRepresentation;
+			this.generationParameters = generationParameters;
+			this.independent = independent;
+			this.axisType = axisType;
+		}
+
+		public String getName() {
+			return name;
+		}
+
+		public void setName(String name) {
+			this.name = name;
+		}
+
+		public SequenceRepresentation getSequenceRepresentation() {
+			return sequenceRepresentation;
+		}
+
+		public void setSequenceRepresentation(SequenceRepresentation sequenceRepresentation) {
+			this.sequenceRepresentation = sequenceRepresentation;
+		}
+
+		public double[] getGenerationParameters() {
+			return generationParameters;
+		}
+
+		public void setGenerationParameters(double[] generationParameters) {
+			this.generationParameters = generationParameters;
+		}
+
+		public boolean isIndependentColumn() {
+			return independent;
+		}
+
+		public void setIndependentColumn(boolean independent) {
+			this.independent = independent;
+		}
+
+		public AxisType getAxisType() {
+			return axisType;
+		}
+
+		public void setAxisType(AxisType axisType) {
+			this.axisType = axisType;
+		}
+
+	}
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ODSModelManager modelManager;
+	private final QueryService queryService;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to gain access to value matrices.
+	 */
+	public ReadRequestHandler(ODSModelManager modelManager, QueryService queryService) {
+		this.modelManager = modelManager;
+		this.queryService = queryService;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Loads {@link MeasuredValues} as defined in given {@link ReadRequest}.
+	 *
+	 * @param readRequest The {@code MeasuredValues} request configuration.
+	 * @return The loaded {@code MeasuredValues} are returned.
+	 * @throws DataAccessException Thrown if unable to load {@code
+	 * 		MeasuredValues}     .
+	 */
+	public List<MeasuredValues> execute(ReadRequest readRequest) throws DataAccessException {
+		ValueMatrix valueMatrix = null;
+		Column[] arrColumns = null;
+
+		try {
+			valueMatrix = getValueMatrix(readRequest);
+			List<Pair<Column, ColumnAttributes>> listColumnPairs = getODSColumns(readRequest, valueMatrix);
+
+			arrColumns = listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new);
+			ColumnAttributes[] arrColumnAttributes = listColumnPairs.stream().map(Pair::getRight)
+					.toArray(ColumnAttributes[]::new);
+
+			NameValueSeqUnit[] nvsus = valueMatrix.getValue(arrColumns, readRequest.getStartIndex(),
+					readRequest.getRequestSize());
+			return ODSConverter.fromODSMeasuredValuesSeq(nvsus, arrColumnAttributes);
+		} catch (AoException aoe) {
+			throw new DataAccessException(aoe.reason, aoe);
+		} finally {
+			releaseColumns(arrColumns);
+			releaseValueMatrix(valueMatrix);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Loads all for each defined {@link Channel} in given {@link ReadRequest} and
+	 * loads the corresponding {@link Column} using given {@link ValueMatrix}.
+	 *
+	 * @param readRequest Defines required {@code Column}s.
+	 * @param valueMatrix Used to load required {@code Column}s.
+	 * @return {@code Column} configured in given {@code ReadRequest} are returned
+	 *         with defined {@link Unit} setup.
+	 * @throws AoException         Throw if unable to load all available
+	 *                             {@code Column}s.
+	 * @throws DataAccessException Thrown on wrong {@code ReadRequest} setup.
+	 */
+	private List<Pair<Column, ColumnAttributes>> getODSColumns(ReadRequest readRequest, ValueMatrix valueMatrix)
+			throws AoException, DataAccessException {
+		List<Pair<Column, ColumnAttributes>> listColumnPairs = new ArrayList<>();
+		Map<String, Column> mapColumns = new HashMap<>();
+
+		try {
+			if (readRequest.isLoadAllChannels()) {
+				// TODO should it be possible to overwrite the unit of some
+				// channels?!
+				// -> this results in a performance issue since we need to call
+				// getName()
+				// on each column for mapping! (no longer, see below!)
+				Column[] columns = valueMatrix.getColumns("*");
+
+				if (null != columns) {
+					for (Column column : columns) {
+						String columnName = column.getName();
+						if (mapColumns.containsKey(columnName)) {
+							releaseColumns(columns);
+							throw new DataAccessException(
+									String.format("Duplicate column name '%s' found within submatrix ID %d!",
+											columnName, Long.valueOf(readRequest.getChannelGroup().getID())));
+						}
+
+						mapColumns.put(columnName, column);
+					}
+				}
+			} else {
+				for (Entry<Channel, Unit> entry : readRequest.getChannels().entrySet()) {
+					Channel channel = entry.getKey();
+					Unit unit = entry.getValue();
+					String channelName = channel.getName();
+					Column[] columns = valueMatrix.getColumns(channelName);
+					if (columns == null || columns.length != 1) {
+						releaseColumns(columns);
+						throw new DataAccessException(String.format(
+								"Zero or more than one column with name '%s' found within submatrix ID %d!",
+								channelName, Long.valueOf(readRequest.getChannelGroup().getID())));
+					}
+
+					Column column = columns[0];
+					if (!unit.nameEquals(channel.getUnit().getName())) {
+						column.setUnit(unit.getName());
+					}
+
+					mapColumns.put(channelName, column);
+				}
+			}
+
+			if (mapColumns.size() > 0) {
+				EntityType localColumnEntityType = modelManager.getEntityType("LocalColumn");
+				Attribute idAttr = localColumnEntityType.getAttribute("Id");
+				Attribute nameAttr = localColumnEntityType.getAttribute("Name");
+				Attribute submatrixAttr = localColumnEntityType.getAttribute("SubMatrix");
+
+				// Don't query GenerationParameters together with other non-ID attributes as
+				// Avalon dislikes this:
+				Query query1 = queryService.createQuery()
+						.select(Lists.newArrayList(idAttr, nameAttr,
+								localColumnEntityType.getAttribute("SequenceRepresentation"),
+								localColumnEntityType.getAttribute("IndependentFlag"),
+								localColumnEntityType.getAttribute("axistype")));
+
+				Filter filter = Filter.and().add(ComparisonOperator.EQUAL.create(submatrixAttr,
+						Long.valueOf(readRequest.getChannelGroup().getID())));
+
+				Set<String> setColumnNames = mapColumns.keySet();
+
+				Map<String, ColumnAttributes> mapColumnAttributes = new HashMap<>();
+
+				for (Result result : query1.fetch(filter)) {
+					Map<String, Value> mapValues = result.getRecord(localColumnEntityType).getValues();
+
+					String columnName = mapValues.get("Name").extract();
+
+					if (setColumnNames.contains(columnName)) {
+						ColumnAttributes ca = new ColumnAttributes(columnName,
+								(ValuesMode.CALCULATED == readRequest.getValuesMode() ? SequenceRepresentation.EXPLICIT
+										: mapValues.get("SequenceRepresentation").extract()),
+								new double[0], ((short) mapValues.get("IndependentFlag").extract() != 0),
+								mapValues.get("axistype").extract());
+
+						mapColumnAttributes.put(mapValues.get("Id").extract(), ca);
+					}
+				}
+
+				if (ValuesMode.CALCULATED != readRequest.getValuesMode()) {
+					Query query2 = queryService.createQuery().select(idAttr,
+							localColumnEntityType.getAttribute("GenerationParameters"));
+
+					for (Result result : query2.fetch(filter)) {
+						Map<String, Value> mapValues = result.getRecord(localColumnEntityType).getValues();
+
+						ColumnAttributes ca = mapColumnAttributes.get(mapValues.get("Id").extract());
+
+						if (ca != null) {
+							ca.setGenerationParameters(mapValues.get("GenerationParameters").extract());
+						}
+					}
+				}
+
+				for (Map.Entry<String, ColumnAttributes> me : mapColumnAttributes.entrySet()) {
+					ColumnAttributes ca = me.getValue();
+					listColumnPairs.add(new ImmutablePair<Column, ColumnAttributes>(mapColumns.get(ca.getName()), ca));
+				}
+			}
+
+			return listColumnPairs;
+		} catch (AoException e) {
+			releaseColumns(listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new));
+			throw new DataAccessException("Unable to load column due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Returns the {@link ValueMatrix} CORBA service object associated with given
+	 * {@link ReadRequest}.
+	 *
+	 * @param readRequest The {@code ReadRequest}.
+	 * @return The {@code ValueMatrix} is returned.
+	 * @throws AoException Thrown if unable to load the {@code ValueMatrix}.
+	 */
+	private ValueMatrix getValueMatrix(ReadRequest readRequest) throws AoException {
+		Entity entity = readRequest.getChannelGroup();
+		T_LONGLONG iid = ODSConverter.toODSID(entity.getID());
+		T_LONGLONG aid = ((ODSEntityType) modelManager.getEntityType(entity)).getODSID();
+		ValueMatrixMode valueMatrixMode = ValueMatrixMode.CALCULATED;
+		switch (readRequest.getValuesMode()) {
+		case CALCULATED:
+			valueMatrixMode = ValueMatrixMode.CALCULATED;
+			break;
+		case STORAGE:
+			valueMatrixMode = ValueMatrixMode.STORAGE;
+			break;
+		default:
+			throw new DataAccessException(
+					String.format("Unsupported ValueMode %s!", readRequest.getValuesMode().name()));
+		}
+
+		return modelManager.getApplElemAccess().getValueMatrixInMode(new ElemId(aid, iid), valueMatrixMode);
+	}
+
+	/**
+	 * Releases given {@link ValueMatrix} CORBA object.
+	 *
+	 * @param valueMatrix Will be released.
+	 */
+	private void releaseValueMatrix(ValueMatrix valueMatrix) {
+		if (valueMatrix == null) {
+			return;
+		}
+
+		try {
+			valueMatrix.destroy();
+		} catch (AoException aoe) {
+			// ignore
+		} finally {
+			valueMatrix._release();
+		}
+	}
+
+	/**
+	 * Releases each CORBA {@link Column} object.
+	 *
+	 * @param columns Will be released.
+	 */
+	private void releaseColumns(Column[] columns) {
+		if (columns == null) {
+			return;
+		}
+
+		for (Column column : columns) {
+			try {
+				column.destroy();
+			} catch (AoException e) {
+				// ignore
+			} catch (Exception e) {
+				// ignore
+			} finally {
+				column._release();
+			}
+		}
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java
new file mode 100644
index 0000000..acc7865
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java
@@ -0,0 +1,521 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.filetransfer;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.asam.ods.AoSession;
+import org.asam.ods.ElemId;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
+import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
+import org.omg.PortableServer.POAPackage.ObjectNotActive;
+import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.highqsoft.corbafileserver.generated.CORBAFileServerException;
+import com.highqsoft.corbafileserver.generated.CORBAFileServerIF;
+import com.highqsoft.corbafileserver.generated.DS_BYTEHolder;
+import com.highqsoft.corbafileserver.generated.ErrorCode;
+import com.highqsoft.corbafileserver.generated.InputStreamIF;
+import com.highqsoft.corbafileserver.generated.InputStreamIFPOA;
+import com.highqsoft.corbafileserver.generated.SeverityFlag;
+
+/**
+ * Service provides access to the low level {@link CORBAFileServerIF} file
+ * service API.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class CORBAFileServer {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(CORBAFileServer.class);
+	private static final int DEFAULT_BUFFER_SIZE = 100_000;
+	private static final int SOCKET_TIMEOUT = 5_000;
+	private static final String INTERFACE_NAME_PROPERTY = "org.eclipse.mdm.api.odsadapter.filetransfer.interfaceName";
+	private static final String HOST_NAME_PROPERTY = "org.eclipse.mdm.api.odsadapter.filetransfer.hostname";
+
+	private final CORBAFileServerIF fileServer;
+	private final AoSession aoSession;
+	private final ORB orb;
+
+	private final Transfer transfer;
+
+	private final int bufferSize;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param context  Used for setup.
+	 * @param transfer The transfer type for up- and downloads.
+	 */
+	CORBAFileServer(ODSContext context, Transfer transfer) {
+		ModelManager mm = context.getModelManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+		if (!(mm instanceof ODSModelManager)) {
+			throw new IllegalArgumentException("The supplied ModelManager must be an ODSModelManager!");
+		}
+
+		fileServer = context.getFileServer();
+		aoSession = context.getAoSession();
+		orb = context.getORB();
+		this.transfer = transfer;
+
+		bufferSize = getBufferSize();
+	}
+
+	/**
+	 * Opens a consumable download {@link InputStream} for given {@link FileLink}.
+	 *
+	 * @param fileLink Used to access the remote path.
+	 * @param elemId   Used for security checks.
+	 * @return The consumable {@code InputStream} is returned.
+	 * @throws IOException Thrown if unable to open an the {@code InputStream}.
+	 */
+	public InputStream openStream(FileLink fileLink, ElemId elemId) throws IOException {
+		InputStream inputStream;
+		if (transfer.isStream()) {
+			inputStream = new InputStreamAdapter(openSimpleStream(fileLink, elemId));
+		} else if (transfer.isSocket()) {
+			inputStream = openSocketStream(fileLink, elemId);
+		} else {
+			throw new IllegalStateException("Transfer state '" + transfer + "' is not supported.");
+		}
+
+		return new BufferedInputStream(inputStream, bufferSize);
+	}
+
+	/**
+	 * Uploads given {@link InputStream} for given {@link FileLink}.
+	 *
+	 * @param inputStream The {@code InputStream} to be uploaded.
+	 * @param fileLink    The associated {@code FileLink}.
+	 * @param elemId      Used for security checks.
+	 * @throws IOException Thrown if unable to upload given {@code InputStream}.
+	 */
+	public void uploadStream(InputStream inputStream, FileLink fileLink, ElemId elemId) throws IOException {
+		String remotePath;
+		if (transfer.isStream()) {
+			remotePath = uploadVIAStream(inputStream, fileLink, elemId);
+		} else if (transfer.isSocket()) {
+			remotePath = uploadVIASocket(inputStream, fileLink, elemId);
+		} else {
+			throw new IllegalStateException("Transfer state '" + transfer + "' is not supported.");
+		}
+
+		fileLink.setRemotePath(remotePath);
+	}
+
+	/**
+	 * Loads the file size for given {@link FileLink}.
+	 *
+	 * @param fileLink The {@code FileLink} whose file size will be loaded.
+	 * @param elemId   Used for security checks.
+	 * @return The file size is returned.
+	 * @throws IOException Thrown if unable to load the file size.
+	 */
+	public long loadSize(FileLink fileLink, ElemId elemId) throws IOException {
+		try {
+			return fileServer.getSizeForInstance(aoSession, fileLink.getRemotePath(), elemId.aid, elemId.iid);
+		} catch (CORBAFileServerException e) {
+			throw new IOException("Unable to query file size due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Deletes the {@link FileLink} from the remote storage.
+	 *
+	 * @param fileLink Will be deleted from the remote storage.
+	 * @param elemId   Used for security checks.
+	 * @throws IOException Thrown if unable to delete given {@code FileLink}.
+	 */
+	public void delete(FileLink fileLink, ElemId elemId) throws IOException {
+		try {
+			fileServer.deleteForInstance(aoSession, fileLink.getRemotePath(), elemId.aid, elemId.iid);
+		} catch (CORBAFileServerException e) {
+			throw new IOException("Unable to delete remote file due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Opens a simple {@link InputStreamIF} using the {@link CORBAFileServerIF}.
+	 *
+	 * @param fileLink Used to access the remote path.
+	 * @param elemId   Used for security checks.
+	 * @return The {@code InputStreamIF} is returned.
+	 * @throws IOException Thrown if unable to open the {@code InputStreamIF}.
+	 */
+	private InputStreamIF openSimpleStream(FileLink fileLink, ElemId elemId) throws IOException {
+		try {
+			return fileServer.readForInstance(aoSession, fileLink.getRemotePath(), elemId.aid, elemId.iid);
+		} catch (CORBAFileServerException e) {
+			throw new IOException("Unable to open stream for file transfer due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Opens a socket {@link InputStream} using the {@link CORBAFileServerIF}.
+	 *
+	 * @param fileLink Used to access the remote path.
+	 * @param elemId   Used for security checks.
+	 * @return The {@code InputStream} is returned.
+	 * @throws IOException Thrown if unable to open the socket {@code
+	 * 		InputStream}.
+	 */
+	private InputStream openSocketStream(FileLink fileLink, ElemId elemId) throws IOException {
+		// auto assigned port with awaiting exactly ONE incoming connection
+		try (ServerSocket serverSocket = new ServerSocket(0, 1, getInterfaceAddress())) {
+			serverSocket.setSoTimeout(SOCKET_TIMEOUT * 6);
+
+			new Thread(() -> {
+				try {
+					/*
+					 * NOTE: Since a socket file transfer registration may block until this server
+					 * socket's accept method is called, the registration is done asynchronously!
+					 */
+					fileServer.getForInstanceBySocket(aoSession, fileLink.getRemotePath(), elemId.aid, elemId.iid,
+							serverSocket.getInetAddress().getHostAddress(), serverSocket.getLocalPort());
+				} catch (CORBAFileServerException e) {
+					LOGGER.error("Unable to initialize socket stream, awaiting socket timeout.", e);
+				}
+			}).start();
+
+			Socket client = serverSocket.accept();
+			client.setSoTimeout(SOCKET_TIMEOUT);
+			return client.getInputStream();
+		}
+	}
+
+	private InetAddress getInterfaceAddress() throws SocketException {
+		String hostnameProperty = System.getProperty(HOST_NAME_PROPERTY);
+		if (!StringUtils.isEmpty(hostnameProperty)) {
+			LOGGER.debug("Using host name '" + hostnameProperty + "' for file transfer.");
+			try {
+				return InetAddress.getByName(hostnameProperty);
+			} catch (UnknownHostException e) {
+				LOGGER.warn("Specified host name '" + hostnameProperty + "' cannot be used for file transfer.", e);
+				// continue with lookup by interface name
+			}
+		}
+
+		String property = System.getProperty(INTERFACE_NAME_PROPERTY);
+		if (StringUtils.isEmpty(property)) {
+			LOGGER.debug("Using no specified interface for file transfer, property not set.");
+			return null;
+		}
+		List<NetworkInterface> interfaces = getInterfaceList();
+		List<NetworkInterface> filteredInterfaces = getFilteredInterfaces(interfaces);
+		for (NetworkInterface filteredInterface : filteredInterfaces) {
+			if (filteredInterface.getName().equals(property)
+					&& filteredInterface.getInetAddresses().hasMoreElements()) {
+				InetAddress inetAddress = filteredInterface.getInetAddresses().nextElement();
+				LOGGER.debug("Using interface {} with address {} for file transfer.", filteredInterface.getName(),
+						inetAddress);
+				return inetAddress;
+			}
+		}
+		return getFallback(filteredInterfaces);
+	}
+
+	private InetAddress getFallback(List<NetworkInterface> filteredInterfaces) {
+		if (filteredInterfaces.isEmpty()) {
+			LOGGER.debug("Using no specified interface for file transfer, property set but no running interface.");
+			return null;
+		}
+		NetworkInterface networkInterface = filteredInterfaces.get(0);
+		Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
+		if (inetAddresses.hasMoreElements()) {
+			InetAddress address = inetAddresses.nextElement();
+			LOGGER.debug("Using interface {} with address {} for file transfer.", networkInterface.getName(), address);
+			return address;
+		}
+		return null;
+	}
+
+	private List<NetworkInterface> getFilteredInterfaces(List<NetworkInterface> interfaces) throws SocketException {
+		List<NetworkInterface> filteredInterfaces = new ArrayList<>();
+		for (NetworkInterface anInterface : interfaces) {
+			if (anInterface.isUp() && !anInterface.isLoopback() && !anInterface.isVirtual()) {
+				filteredInterfaces.add(anInterface);
+			}
+		}
+		return filteredInterfaces;
+	}
+
+	private List<NetworkInterface> getInterfaceList() throws SocketException {
+		List<NetworkInterface> result = new ArrayList<>();
+		Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+		while (networkInterfaces.hasMoreElements()) {
+			result.add(networkInterfaces.nextElement());
+		}
+		return result;
+	}
+
+	/**
+	 * Uploads given {@link InputStream} for given {@link FileLink} using the
+	 * {@link CORBAFileServerIF}.
+	 *
+	 * @param inputStream The {@code InputStream} to be uploaded.
+	 * @param fileLink    The associated {@code FileLink}.
+	 * @param elemId      Used for security checks.
+	 * @return The remote path of the uploaded {@code InputStream} is returned.
+	 * @throws IOException Thrown if unable to upload given {@code InputStream}.
+	 */
+	private String uploadVIAStream(InputStream inputStream, FileLink fileLink, ElemId elemId) throws IOException {
+		try (CORBAInputStreamAdapter stream = new CORBAInputStreamAdapter(orb, inputStream, fileLink.getSize())) {
+			return fileServer.saveForInstance(aoSession, fileLink.getFileName(), "", elemId.aid, elemId.iid,
+					stream._this());
+		} catch (CORBAFileServerException e) {
+			throw new IOException("Unable to upload file via stream due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * Uploads given {@link InputStream} for given {@link FileLink} via socket
+	 * upload using the {@link CORBAFileServerIF}.
+	 *
+	 * @param inputStream The {@code InputStream} to be uploaded.
+	 * @param fileLink    The associated {@code FileLink}.
+	 * @param elemId      Used for security checks.
+	 * @return The remote path of the uploaded {@code InputStream} is returned.
+	 * @throws IOException Thrown if unable to upload given {@code InputStream}.
+	 */
+	private String uploadVIASocket(InputStream inputStream, FileLink fileLink, ElemId elemId) throws IOException {
+		// auto assigned port with awaiting exactly ONE incoming connection
+		try (ServerSocket serverSocket = new ServerSocket(0, 1, getInterfaceAddress())) {
+			serverSocket.setSoTimeout(SOCKET_TIMEOUT * 6);
+
+			new Thread(() -> {
+				try (Socket client = serverSocket.accept(); OutputStream outputStream = client.getOutputStream()) {
+					byte[] buffer = new byte[bufferSize];
+
+					int length;
+					while ((length = inputStream.read(buffer)) > -1) {
+						outputStream.write(buffer, 0, length);
+					}
+				} catch (IOException e) {
+					LOGGER.error("Unable to initialize socket stream, awaiting socket timeout.", e);
+				}
+			}).start();
+
+			int localPort = serverSocket.getLocalPort();
+			String localHostName = serverSocket.getInetAddress().getHostAddress();
+			try {
+				return fileServer.saveForInstanceBySocket(aoSession, fileLink.getFileName(), "", elemId.aid, elemId.iid,
+						localHostName, localPort);
+			} catch (CORBAFileServerException e) {
+				String message = String.format("Unable to upload file via socket to %s:%d due to: %s", localHostName,
+						localPort, e.reason);
+				throw new IOException(message, e);
+			}
+		}
+	}
+
+	/**
+	 * Tries to load the buffer size used by the {@link CORBAFileServerIF} to reach
+	 * best performance. In case of errors a default buffer size of of
+	 * {@value #DEFAULT_BUFFER_SIZE} is used.
+	 *
+	 * @return The buffer size is returned.
+	 */
+	private int getBufferSize() {
+		try {
+			// try to use the same buffer size as the corba file server for best
+			// performance
+			return Integer.parseInt(fileServer.getContext(aoSession, "CORBAFileServer.BufferSize"));
+		} catch (NumberFormatException | CORBAFileServerException e) {
+			return DEFAULT_BUFFER_SIZE;
+		}
+	}
+
+	/**
+	 * A simple {@link InputStream} adapter implementation for an
+	 * {@link InputStreamIF}.
+	 */
+	private static final class InputStreamAdapter extends InputStream {
+
+		private final InputStreamIF inputStream;
+
+		/**
+		 * Constructor.
+		 *
+		 * @param inputStream The wrapped {@link InputStreamIF}.
+		 */
+		private InputStreamAdapter(InputStreamIF inputStream) {
+			this.inputStream = inputStream;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public int read() throws IOException {
+			byte[] b = new byte[1];
+			return read(b) == -1 ? -1 : b[0];
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public int read(byte[] buffer, int offset, int length) throws IOException {
+			try {
+				DS_BYTEHolder byteHolder = new DS_BYTEHolder();
+				int receivedBytes = inputStream.read(byteHolder, offset, length);
+				if (receivedBytes > 0) {
+					System.arraycopy(byteHolder.value, 0, buffer, 0, receivedBytes);
+				}
+				return receivedBytes;
+			} catch (CORBAFileServerException e) {
+				throw new IOException("Failed to retrieve bytes from CORBA input stream due to: " + e.reason, e);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void close() throws IOException {
+			try {
+				inputStream.close();
+			} catch (CORBAFileServerException e) {
+				throw new IOException("Unable to close CORBA input stream due to: " + e.reason, e);
+			} finally {
+				inputStream._release();
+			}
+		}
+
+	}
+
+	// remotely consumable local input stream
+	/**
+	 * A simple {@link InputStreamIF} adapter implementation for an
+	 * {@link InputStream}.
+	 */
+	private static final class CORBAInputStreamAdapter extends InputStreamIFPOA implements AutoCloseable {
+
+		private final InputStream inputStream;
+		private final long length;
+
+		private final byte[] objectID;
+		private final POA poa;
+
+		/**
+		 * Constructor.
+		 *
+		 * @param orb         Used to access the root {@link POA} to activate this CORBA
+		 *                    service object.
+		 * @param inputStream The wrapped {@link InputStream}.
+		 * @param length      The length of the wrapped {@code InputStream}.
+		 * @throws IOException Thrown on errors.
+		 */
+		private CORBAInputStreamAdapter(ORB orb, InputStream inputStream, long length) throws IOException {
+			this.inputStream = inputStream;
+			this.length = length;
+
+			try {
+				poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+				poa.the_POAManager().activate();
+				objectID = poa.activate_object(this);
+			} catch (AdapterInactive | InvalidName | ServantAlreadyActive | WrongPolicy e) {
+				throw new IOException("Unable to create CORBA input stream.", e);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public int read(DS_BYTEHolder b, int off, int len) throws CORBAFileServerException {
+			b.value = new byte[len];
+
+			try {
+				return inputStream.read(b.value, off, len);
+			} catch (IOException e) {
+				throw new CORBAFileServerException(ErrorCode.FILESERVER_IO_EXCEPTION, SeverityFlag.ERROR,
+						e.getMessage());
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void close() throws CORBAFileServerException {
+			try {
+				inputStream.close();
+			} catch (IOException e) {
+				throw new CORBAFileServerException(ErrorCode.FILESERVER_IO_EXCEPTION, SeverityFlag.ERROR,
+						e.getMessage());
+			} finally {
+				try {
+					poa.deactivate_object(objectID);
+				} catch (ObjectNotActive | WrongPolicy e) {
+					LOGGER.warn("Unable to deactive CORBA input stream", e);
+				}
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public int length() throws CORBAFileServerException {
+			/*
+			 * NOTE: A file length is of type long and therefore, for very large files (>
+			 * 2.14 GB), the exact length is lost due to narrowing conversion!
+			 */
+			return (int) length;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public void reset() throws CORBAFileServerException {
+			try {
+				inputStream.reset();
+			} catch (IOException e) {
+				throw new CORBAFileServerException(ErrorCode.FILESERVER_IO_EXCEPTION, SeverityFlag.ERROR,
+						e.getMessage());
+			}
+		}
+
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileService.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileService.java
new file mode 100644
index 0000000..2e84f2e
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileService.java
@@ -0,0 +1,473 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.filetransfer;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.reducing;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+
+import org.asam.ods.ElemId;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.file.FileService;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * CORBA file service implementation of the {@link FileService} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class CORBAFileService implements FileService {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(CORBAFileService.class);
+
+	private static final int THREAD_POOL_SIZE = 5;
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final CORBAFileServer fileServer;
+	private final ModelManager modelManager;
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param context  Used for {@link Entity} to {@link ElemId} conversion.
+	 * @param transfer The transfer type for up- and downloads.
+	 */
+	public CORBAFileService(ODSContext context, Transfer transfer) {
+		this.modelManager = context.getModelManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+
+		fileServer = new CORBAFileServer(context, transfer);
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void downloadSequential(Entity entity, Path target, Collection<FileLink> fileLinks,
+			ProgressListener progressListener) throws IOException {
+		downloadSequential(toElemID(entity), target, fileLinks, progressListener);
+	}
+
+	private void downloadSequential(ElemId elemId, Path target, Collection<FileLink> fileLinks,
+			ProgressListener progressListener) throws IOException {
+		Map<String, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isRemote)
+				.collect(Collectors.groupingBy(FileLink::getRemotePath));
+
+		long totalSize = calculateDownloadSize(elemId, groups);
+		final AtomicLong transferred = new AtomicLong();
+		LocalTime start = LocalTime.now();
+		UUID id = UUID.randomUUID();
+		LOGGER.debug("Sequential download of {} file(s) with id '{}' started.", groups.size(), id);
+		for (List<FileLink> group : groups.values()) {
+			FileLink fileLink = group.get(0);
+
+			download(elemId, target, fileLink, (b, p) -> {
+				double tranferredBytes = transferred.addAndGet(b);
+				if (progressListener != null) {
+					progressListener.progress(b, (float) (tranferredBytes / totalSize));
+				}
+			});
+
+			for (FileLink other : group.subList(1, group.size())) {
+				other.setLocalStream(fileLink.getLocalStream());
+			}
+		}
+		LOGGER.debug("Sequential download with id '{}' finished in {}.", id, Duration.between(start, LocalTime.now()));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void downloadParallel(Entity entity, Path target, Collection<FileLink> fileLinks,
+			ProgressListener progressListener) throws IOException {
+		downloadParallel(toElemID(entity), target, fileLinks, progressListener);
+	}
+
+	private void downloadParallel(ElemId elemId, Path target, Collection<FileLink> fileLinks,
+			ProgressListener progressListener) throws IOException {
+		Map<String, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isRemote)
+				.collect(Collectors.groupingBy(FileLink::getRemotePath));
+
+		long totalSize = calculateDownloadSize(elemId, groups);
+		final AtomicLong transferred = new AtomicLong();
+		List<Callable<Void>> downloadTasks = new ArrayList<>();
+		for (List<FileLink> group : groups.values()) {
+			downloadTasks.add(() -> {
+				FileLink fileLink = group.get(0);
+
+				download(elemId, target, fileLink, (b, p) -> {
+					double tranferredBytes = transferred.addAndGet(b);
+					if (progressListener != null) {
+						progressListener.progress(b, (float) (tranferredBytes / totalSize));
+					}
+				});
+
+				for (FileLink other : group.subList(1, group.size())) {
+					other.setLocalStream(fileLink.getLocalStream());
+				}
+
+				return null;
+			});
+		}
+
+		ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
+		LocalTime start = LocalTime.now();
+		UUID id = UUID.randomUUID();
+		LOGGER.debug("Parallel download of {} file(s) with id '{}' started.", groups.size(), id);
+		try {
+			List<Throwable> errors = executorService.invokeAll(downloadTasks).stream().map(future -> {
+				try {
+					future.get();
+					return null;
+				} catch (ExecutionException | InterruptedException e) {
+					LOGGER.error("Download of failed due to: " + e.getMessage(), e);
+					return e;
+				}
+			}).filter(Objects::nonNull).collect(Collectors.toList());
+
+			if (!errors.isEmpty()) {
+				throw new IOException("Download faild for '" + errors.size() + "' files.");
+			}
+			LOGGER.debug("Parallel download with id '{}' finished in {}.", id,
+					Duration.between(start, LocalTime.now()));
+		} catch (InterruptedException e) {
+			throw new IOException("Unable to download files due to: " + e.getMessage(), e);
+		} finally {
+			executorService.shutdown();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void download(Entity entity, Path target, FileLink fileLink, ProgressListener progressListener)
+			throws IOException {
+		download(toElemID(entity), target, fileLink, progressListener);
+	}
+
+	private void download(ElemId elemId, Path target, FileLink fileLink, ProgressListener progressListener)
+			throws IOException {
+		if (Files.exists(target)) {
+			if (!Files.isDirectory(target)) {
+				throw new IllegalArgumentException("Target path is not a directory.");
+			}
+		} else {
+			Files.createDirectory(target);
+		}
+
+		try (InputStream inputStream = openStream(elemId, fileLink, progressListener)) {
+			Path absolutePath = target.resolve(fileLink.getFileName()).toAbsolutePath();
+			String remotePath = fileLink.getRemotePath();
+			LOGGER.debug("Starting download of file '{}' to '{}'.", remotePath, absolutePath);
+			LocalTime start = LocalTime.now();
+			Files.copy(inputStream, absolutePath);
+			LOGGER.debug("File '{}' successfully downloaded in {} to '{}'.", remotePath,
+					Duration.between(start, LocalTime.now()), absolutePath);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public InputStream openStream(Entity entity, FileLink fileLink, ProgressListener progressListener)
+			throws IOException {
+		return openStream(toElemID(entity), fileLink, progressListener);
+	}
+
+	private InputStream openStream(ElemId elemId, FileLink fileLink, ProgressListener progressListener)
+			throws IOException {
+		InputStream sourceStream;
+		if (fileLink.isLocal()) {
+			// file is locally available -> USE this shortcut!
+			sourceStream = fileLink.getLocalStream();
+		} else if (fileLink.isRemote()) {
+			sourceStream = fileServer.openStream(fileLink, elemId);
+		} else {
+			throw new IllegalArgumentException("File link is neither in local nor remote state: " + fileLink);
+		}
+
+		// NOTE: Access to immediate input stream is buffered.
+		if (progressListener != null) {
+			loadSize(elemId, fileLink);
+			// NOTE: Progress updates immediately triggered by the stream
+			// consumer.
+			return new TracedInputStream(sourceStream, progressListener, fileLink.getSize());
+		}
+		return sourceStream;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void loadSize(Entity entity, FileLink fileLink) throws IOException {
+		loadSize(toElemID(entity), fileLink);
+	}
+
+	private void loadSize(ElemId elemId, FileLink fileLink) throws IOException {
+		if (fileLink.getSize() > -1) {
+			// file size is already known
+			return;
+		} else if (fileLink.isRemote()) {
+			fileLink.setFileSize(fileServer.loadSize(fileLink, elemId));
+		} else {
+			throw new IllegalArgumentException("File link is neither in local nor remote state: " + fileLink);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void uploadSequential(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener)
+			throws IOException {
+		uploadSequential(toElemID(entity), fileLinks, progressListener);
+	}
+
+	private void uploadSequential(ElemId elemId, Collection<FileLink> fileLinks, ProgressListener progressListener)
+			throws IOException {
+		Map<InputStream, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isLocal)
+				.collect(Collectors.groupingBy(FileLink::getLocalStream));
+
+		long totalSize = groups.values().stream().map(l -> l.get(0)).mapToLong(FileLink::getSize).sum();
+		final AtomicLong transferred = new AtomicLong();
+		LocalTime start = LocalTime.now();
+		UUID id = UUID.randomUUID();
+		LOGGER.debug("Sequential upload of {} file(s) with id '{}' started.", groups.size(), id);
+		for (List<FileLink> group : groups.values()) {
+			FileLink fileLink = group.get(0);
+
+			upload(elemId, fileLink, (b, p) -> {
+				double tranferredBytes = transferred.addAndGet(b);
+				if (progressListener != null) {
+					progressListener.progress(b, (float) (tranferredBytes / totalSize));
+				}
+			});
+
+			for (FileLink other : group.subList(1, group.size())) {
+				other.setRemotePath(fileLink.getRemotePath());
+			}
+		}
+		LOGGER.debug("Sequential upload with id '{}' finished in {}.", id, Duration.between(start, LocalTime.now()));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void uploadParallel(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener)
+			throws IOException {
+		uploadParallel(toElemID(entity), fileLinks, progressListener);
+	}
+
+	private void uploadParallel(ElemId elemId, Collection<FileLink> fileLinks, ProgressListener progressListener)
+			throws IOException {
+		Map<InputStream, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isLocal)
+				.collect(Collectors.groupingBy(FileLink::getLocalStream));
+
+		long totalSize = groups.values().stream().map(l -> l.get(0)).mapToLong(FileLink::getSize).sum();
+		final AtomicLong transferred = new AtomicLong();
+		List<Callable<Void>> downloadTasks = new ArrayList<>();
+		for (List<FileLink> group : groups.values()) {
+			downloadTasks.add(() -> {
+				FileLink fileLink = group.get(0);
+
+				upload(elemId, fileLink, (b, p) -> {
+					double tranferredBytes = transferred.addAndGet(b);
+					if (progressListener != null) {
+						progressListener.progress(b, (float) (tranferredBytes / totalSize));
+					}
+				});
+
+				for (FileLink other : group.subList(1, group.size())) {
+					other.setRemotePath(fileLink.getRemotePath());
+				}
+
+				return null;
+			});
+		}
+
+		ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
+		LocalTime start = LocalTime.now();
+		UUID id = UUID.randomUUID();
+		LOGGER.debug("Parallel upload of {} file(s) with id '{}' started.", groups.size(), id);
+		try {
+			List<Throwable> errors = executorService.invokeAll(downloadTasks).stream().map(future -> {
+				try {
+					future.get();
+					return null;
+				} catch (ExecutionException | InterruptedException e) {
+					LOGGER.error("Upload of failed due to: " + e.getMessage(), e);
+					return e;
+				}
+			}).filter(Objects::nonNull).collect(Collectors.toList());
+
+			if (!errors.isEmpty()) {
+				throw new IOException("Upload faild for '" + errors.size() + "' files.");
+			}
+			LOGGER.debug("Parallel upload with id '{}' finished in {}.", id, Duration.between(start, LocalTime.now()));
+		} catch (InterruptedException e) {
+			throw new IOException("Unable to upload files due to: " + e.getMessage(), e);
+		} finally {
+			executorService.shutdown();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void delete(Entity entity, Collection<FileLink> fileLinks) {
+		delete(toElemID(entity), fileLinks);
+	}
+
+	private void delete(ElemId elemId, Collection<FileLink> fileLinks) {
+		fileLinks.stream().filter(FileLink::isRemote)
+				.collect(groupingBy(FileLink::getRemotePath, reducing((fl1, fl2) -> fl1))).values().stream()
+				.filter(Optional::isPresent).map(Optional::get).forEach(fl -> delete(elemId, fl));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void delete(Entity entity, FileLink fileLink) {
+		delete(toElemID(entity), fileLink);
+	}
+
+	private void delete(ElemId elemId, FileLink fileLink) {
+		if (!fileLink.isRemote()) {
+			// nothing to do
+			return;
+		}
+
+		try {
+			fileServer.delete(fileLink, elemId);
+			LOGGER.debug("File '{}' sucessfully deleted.", fileLink.getRemotePath());
+		} catch (IOException e) {
+			LOGGER.warn("Failed to delete remote file.", e);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+	
+	/**
+	 * Uploads given {@link FileLink}. The upload progress may be traced with a
+	 * progress listener.
+	 *
+	 * @param elemId           Used for security checks.
+	 * @param fileLink         The {@code FileLink} to upload.
+	 * @param progressListener The progress listener.
+	 * @throws IOException Thrown if unable to upload file.
+	 */
+	private void upload(ElemId elemId, FileLink fileLink, ProgressListener progressListener) throws IOException {
+		if (fileLink.isRemote()) {
+			// nothing to do
+			return;
+		} else if (!fileLink.isLocal()) {
+			throw new IllegalArgumentException("File link does not have a local path.");
+		}
+
+		InputStream sourceStream = fileLink.getLocalStream();
+		if (progressListener != null) {
+			sourceStream = new TracedInputStream(sourceStream, progressListener, fileLink.getSize());
+		}
+
+		LOGGER.debug("Starting upload of file '{}'.", fileLink.getFileName());
+		LocalTime start = LocalTime.now();
+		fileServer.uploadStream(sourceStream, fileLink, elemId);
+		LOGGER.debug("File '{}' successfully uploaded in {} to '{}'.", fileLink.getFileName(),
+				Duration.between(start, LocalTime.now()), fileLink.getRemotePath());
+	}
+
+	/**
+	 * Creates an ODS entity identity {@link ElemId} object for given
+	 * {@link Entity}.
+	 *
+	 * @param entity The {@code Entity}.
+	 * @return The created {@code ElemId} is returned.
+	 */
+	private ElemId toElemID(Entity entity) {
+		return new ElemId(((ODSEntityType) modelManager.getEntityType(entity)).getODSID(),
+				ODSConverter.toODSID(entity.getID()));
+	}
+
+	/**
+	 * Calculates the total download size for given {@link FileLink} groups.
+	 *
+	 * @param entity Used for security checks.
+	 * @param groups The {@code FileLink} groups.
+	 * @return The total download size is returned.
+	 * @throws IOException Thrown if unable to load the file size.
+	 */
+	private long calculateDownloadSize(ElemId elemId, Map<String, List<FileLink>> groups) throws IOException {
+		List<FileLink> links = groups.values().stream().map(l -> l.get(0)).collect(Collectors.toList());
+		long totalSize = 0;
+		for (FileLink fileLink : links) {
+			loadSize(elemId, fileLink);
+			// overflow may occur in case of total size exceeds 9223 PB!
+			totalSize = Math.addExact(totalSize, fileLink.getSize());
+		}
+
+		return totalSize;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/TracedInputStream.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/TracedInputStream.java
new file mode 100644
index 0000000..27c4184
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/TracedInputStream.java
@@ -0,0 +1,92 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.filetransfer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.mdm.api.base.file.FileService.ProgressListener;
+
+/**
+ * This is an {@link InputStream} wrapper implementation to trace the progress
+ * of an {@code InputStream}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class TracedInputStream extends InputStream {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ProgressListener progressListener;
+	private final InputStream inputStream;
+	private final long size;
+
+	private double transferred = 0;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param inputStream      The traced {@link InputStream}.
+	 * @param progressListener The listener will be used to fire update
+	 *                         notifications.
+	 * @param length           The length of the consumed {@code InputStream}.
+	 */
+	TracedInputStream(InputStream inputStream, ProgressListener progressListener, long length) {
+		this.progressListener = progressListener;
+		this.inputStream = inputStream;
+		size = length;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int read() throws IOException {
+		return inputStream.read();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int read(byte[] buffer, int offset, int length) throws IOException {
+		int read = inputStream.read(buffer, offset, length);
+		if (read > -1) {
+			transferred += read;
+			progressListener.progress(read, (float) (transferred / size));
+		}
+		return read;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void close() throws IOException {
+		inputStream.close();
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/Transfer.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/Transfer.java
new file mode 100644
index 0000000..a658553
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/Transfer.java
@@ -0,0 +1,63 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.filetransfer;
+
+import java.io.InputStream;
+
+/**
+ * Transfer type enumeration.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public enum Transfer {
+
+	// ======================================================================
+	// Enum constants
+	// ======================================================================
+
+	/**
+	 * Simple {@link InputStream}s are used for up- and downloads.
+	 */
+	STREAM,
+
+	/**
+	 * Socket {@link InputStream}s are used for up- and downloads.
+	 */
+	SOCKET;
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Checks whether this transfer is {@link #STREAM}.
+	 *
+	 * @return Returns {@code true} if this instance is {@link #STREAM}.
+	 */
+	boolean isStream() {
+		return STREAM == this;
+	}
+
+	/**
+	 * Checks whether this transfer is {@link #SOCKET}.
+	 *
+	 * @return Returns {@code true} if this instance is {@link #SOCKET}.
+	 */
+	boolean isSocket() {
+		return SOCKET == this;
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/Cache.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/Cache.java
new file mode 100644
index 0000000..f9264b1
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/Cache.java
@@ -0,0 +1,68 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+
+/**
+ * Used to temporarily cache {@link EntityResult}s fore reuse in subsequent
+ * {@link EntityRequest}s.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class Cache {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<EntityConfig<?>, EntityResult<?>> cache = new HashMap<>();
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Caches given {@link EntityResult}.
+	 *
+	 * @param entityResult The {@link EntityResult}.
+	 */
+	public void add(EntityResult<?> entityResult) {
+		cache.put(entityResult.request.entityConfig, entityResult);
+	}
+
+	/**
+	 * Returns the cached {@link EntityResult} associated with given
+	 * {@link EntityConfig}.
+	 *
+	 * @param entityConfig Used as identifier.
+	 * @return The {@code EntityResult} is returned.
+	 * @throws IllegalArgumentException Thrown if requested {@code
+	 * 		EntityResult}            not found.
+	 */
+	public EntityResult<?> get(EntityConfig<?> entityConfig) {
+		EntityResult<?> entityResult = cache.get(entityConfig);
+		if (entityResult == null) {
+			throw new IllegalArgumentException("Entity result not found");
+		}
+
+		return entityResult;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/ChildRequest.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/ChildRequest.java
new file mode 100644
index 0000000..bb1a24b
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/ChildRequest.java
@@ -0,0 +1,205 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import static java.util.stream.Stream.concat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+
+/**
+ * Extends {@link EntityRequest} to load children for a given
+ * {@link EntityRequest}.
+ *
+ * @param <T> The entity type.
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class ChildRequest<T extends Deletable> extends EntityRequest<T> {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final EntityRequest<?> parent;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param parentRequest The parent {@link EntityRequest}.
+	 * @param entityConfig  The {@link EntityConfig}.
+	 */
+	ChildRequest(EntityRequest<?> parentRequest, EntityConfig<T> entityConfig) {
+		super(parentRequest, entityConfig);
+		parent = parentRequest;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Loads all related child entities.
+	 *
+	 * @return Returns the queried {@code EntityResult}.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public EntityResult<T> load() throws DataAccessException {
+		filtered = parent.filtered;
+
+		EntityType entityType = entityConfig.getEntityType();
+		Relation parentRelation = entityConfig.getEntityType().getRelation(parent.entityConfig.getEntityType());
+		Relation reflexiveRelation = entityConfig.isReflexive() ? entityType.getRelation(entityType) : null;
+
+		Query query = queryService.createQuery()
+				// select entity attributes
+				.selectAll(entityConfig.getEntityType())
+				// select parent entity ID
+				.select(parentRelation.getAttribute());
+
+		if (entityConfig.isReflexive()) {
+			query.select(reflexiveRelation.getAttribute());
+			// entities with children have to be processed before their
+			// children!
+			query.order(entityType.getIDAttribute());
+		}
+
+		// prepare relations select statements
+		List<RelationConfig> optionalRelations = selectRelations(query, entityConfig.getOptionalConfigs(), false);
+		List<RelationConfig> mandatoryRelations = selectRelations(query, entityConfig.getMandatoryConfigs(), true);
+		List<RelationConfig> inheritedRelations = selectRelations(query, entityConfig.getInheritedConfigs(), true);
+
+		// configure filter
+		Filter adjustedFilter = Filter.or();
+		if (filtered) {
+			// preserve current conditions
+			adjustedFilter.ids(parentRelation, parent.entityResult.getIDs());
+			if (entityConfig.isReflexive()) {
+				// extend to retrieve all reflexive child candidates
+				adjustedFilter.add(ComparisonOperator.IS_NOT_NULL.create(reflexiveRelation.getAttribute(), 0L));
+			}
+		}
+
+		// load entities and prepare mappings for required related entities
+		List<EntityRecord<?>> parentRecords = new ArrayList<>();
+		for (Record record : collectRecords(query.fetch(adjustedFilter))) {
+			Optional<String> parentID = record.getID(parentRelation);
+			Optional<String> reflexiveParentID = Optional.empty();
+			if (entityConfig.isReflexive()) {
+				reflexiveParentID = record.getID(reflexiveRelation);
+			}
+			EntityRecord<T> entityRecord;
+
+			if (parentID.isPresent()) {
+				EntityResult<?> parentResult = parent.entityResult;
+				@SuppressWarnings({ "unchecked", "rawtypes" })
+				Optional<EntityRecord<?>> parentRecord = (Optional) parentResult.get(parentID.get());
+				if (!parentRecord.isPresent()) {
+					continue;
+				}
+
+				entityRecord = entityResult.add(parentRecord.get(), record);
+				parentRecords.add(parentRecord.get());
+			} else if (entityConfig.isReflexive() && reflexiveParentID.isPresent()) {
+				Optional<EntityRecord<T>> parentRecord = entityResult.get(reflexiveParentID.get());
+				if (!parentRecord.isPresent()) {
+					// this entity's parent was not loaded -> skip
+					continue;
+				}
+				// reflexive child
+				entityRecord = entityResult.add(parentRecord.get(), record);
+				parentRecords.add(parentRecord.get());
+			} else {
+				throw new IllegalStateException("Entity without parent found");
+			}
+
+			// collect related instance IDs
+			concat(concat(optionalRelations.stream(), mandatoryRelations.stream()), inheritedRelations.stream())
+					.forEach(rc -> rc.add(entityRecord, record));
+		}
+
+		if (entityResult.isEmpty()) {
+			// no entities found -> neither related nor child entities required
+			return entityResult;
+		}
+
+		// load and map related entities
+		loadRelatedEntities(optionalRelations);
+		loadRelatedEntities(mandatoryRelations);
+		assignRelatedEntities(inheritedRelations);
+
+		// sort children of parent
+		for (EntityRecord<?> entityRecord : parentRecords) {
+			entityRecord.core.getChildrenStore().sort(entityConfig.getEntityClass(), entityConfig.getComparator());
+		}
+
+		// load children
+		for (EntityConfig<? extends Deletable> childConfig : entityConfig.getChildConfigs()) {
+			cache.add(new ChildRequest<>(this, childConfig).load());
+		}
+
+		return entityResult;
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Maps related entities for each given {@link RelationConfig} using the
+	 * entities loaded in previous {@link EntityRequest}.
+	 *
+	 * @param relationConfigs The {@code RelationConfig}s.
+	 * @throws DataAccessException Thrown if unable to load related entities.
+	 */
+	private void assignRelatedEntities(List<RelationConfig> relationConfigs) throws DataAccessException {
+		for (RelationConfig relationConfig : relationConfigs) {
+			EntityConfig<?> relatedConfig = relationConfig.entityConfig;
+
+			boolean isContextTypeDefined = entityConfig.getContextType().isPresent();
+			for (Entity relatedEntity : cache.get(relatedConfig).getEntities()) {
+				boolean setByContextType = !isContextTypeDefined && relatedConfig.getContextType().isPresent();
+				List<EntityRecord<?>> entityRecords = relationConfig.dependants.remove(relatedEntity.getID());
+				entityRecords = entityRecords == null ? new ArrayList<EntityRecord<?>>() : entityRecords;
+				for (EntityRecord<?> entityRecord : entityRecords) {
+					setRelatedEntity(entityRecord, relatedEntity,
+							setByContextType ? relatedConfig.getContextType().get() : null);
+				}
+			}
+
+			if (!relationConfig.dependants.isEmpty()) {
+				// this may occur if the instance id of the related entity
+				// is defined, but the entity itself does not exist
+				throw new IllegalStateException("Unable to load related entities.");
+			}
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityLoader.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityLoader.java
new file mode 100644
index 0000000..fc7a3e4
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityLoader.java
@@ -0,0 +1,123 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+
+/**
+ * Loads complete {@link Entity}s by using the {@link EntityConfig} identified
+ * by given {@link Key}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class EntityLoader {
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ODSModelManager modelManager;
+	private final QueryService queryService;
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager The {@link ODSModelManager}.
+	 */
+	public EntityLoader(ODSModelManager modelManager, QueryService queryService) {
+		this.modelManager = modelManager;
+		this.queryService = queryService;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Loads the entity with given instance ID.
+	 *
+	 * @param <T>        The entity type.
+	 * @param key        Used to resolve the entity configuration.
+	 * @param instanceID The instance ID.
+	 * @return The queried {@code Entity} is returned.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public <T extends Entity> T load(Key<T> key, String instanceID) throws DataAccessException {
+		List<T> entities = loadAll(key, Collections.singletonList(instanceID));
+		if (entities.size() != 1) {
+			throw new DataAccessException("Failed to load entity by instance ID.");
+		}
+		return entities.get(0);
+	}
+
+	/**
+	 * Loads all entities matching given name pattern.
+	 *
+	 * @param <T>     The entity type.
+	 * @param key     Used to resolve the entity configuration.
+	 * @param pattern Is always case sensitive and may contain wildcard characters
+	 *                as follows: "?" for one matching character and "*" for a
+	 *                sequence of matching characters.
+	 * @return A {@link List} with queried entities is returned.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public <T extends Entity> List<T> loadAll(Key<T> key, String pattern) throws DataAccessException {
+		return createRequest(key).loadAll(pattern);
+	}
+
+	/**
+	 * Loads all entities matching given instance IDs.
+	 *
+	 * @param <T>         The entity type.
+	 * @param key         Used to resolve the entity configuration.
+	 * @param instanceIDs The instance IDs.
+	 * @return A {@link List} with queried entities is returned.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public <T extends Entity> List<T> loadAll(Key<T> key, Collection<String> instanceIDs) throws DataAccessException {
+		return createRequest(key).loadAll(instanceIDs);
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Creates a new {@link EntityRequest} for given {@link Key}.
+	 *
+	 * @param <T> The entity type.
+	 * @param key Used to resolve the entity configuration.
+	 * @return The created {@code EntityRequest} is returned.
+	 */
+	private <T extends Entity> EntityRequest<T> createRequest(Key<T> key) {
+		/*
+		 * TODO: add custom request implementations here!
+		 */
+		return new EntityRequest<>(modelManager, queryService, key);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java
new file mode 100644
index 0000000..6f8e89d
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java
@@ -0,0 +1,61 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.model.Entity;
+
+/**
+ * Utility class to group {@link Entity} and its {@link Core}.
+ *
+ * @param <T> The entity type.
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class EntityRecord<T extends Entity> {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	final Core core;
+	final T entity;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param entity The {@link Entity}.
+	 * @param core   The {@link Core} of the {@code Entity}.
+	 */
+	EntityRecord(T entity, Core core) {
+		this.entity = entity;
+		this.core = core;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return "EntityRecord [core=" + core + ", entity=" + entity + "]";
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java
new file mode 100644
index 0000000..067da7a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java
@@ -0,0 +1,334 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import static java.util.stream.Collectors.toList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextSensor;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
+import org.eclipse.mdm.api.dflt.model.TemplateComponent;
+import org.eclipse.mdm.api.dflt.model.TemplateSensor;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+
+/**
+ * Recursively loads entities for a given {@link EntityConfig} with all resolved
+ * dependencies (optional, mandatory children).
+ *
+ * @param <T> The entity type.
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class EntityRequest<T extends Entity> {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	final ODSModelManager odsModelManager;
+	final QueryService queryService;
+	final EntityConfig<T> entityConfig;
+	final EntityResult<T> entityResult = new EntityResult<>(this);
+
+	final Cache cache;
+
+	boolean filtered;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager The {@link ODSModelManager}.
+	 * @param config       The {@link EntityConfig}.
+	 */
+	public EntityRequest(ODSModelManager modelManager, QueryService queryService, Key<T> key) {
+		this.odsModelManager = modelManager;
+		this.queryService = queryService;
+		this.entityConfig = modelManager.getEntityConfig(key);
+		cache = new Cache();
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param parentRequest The parent {@link EntityRequest}.
+	 * @param entityConfig  The {@link EntityConfig}.
+	 */
+	protected EntityRequest(EntityRequest<?> parentRequest, EntityConfig<T> entityConfig) {
+		odsModelManager = parentRequest.odsModelManager;
+		queryService = parentRequest.queryService;
+		cache = parentRequest.cache;
+		this.entityConfig = entityConfig;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Loads all entities matching given name pattern.
+	 *
+	 * @param pattern Is always case sensitive and may contain wildcard characters
+	 *                as follows: "?" for one matching character and "*" for a
+	 *                sequence of matching characters.
+	 * @return A sorted {@link List} with queried entities is returned.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public List<T> loadAll(String pattern) throws DataAccessException {
+		return load(Filter.nameOnly(entityConfig.getEntityType(), pattern)).getSortedEntities();
+	}
+
+	/**
+	 * Loads all entities matching given instance IDs.
+	 *
+	 * @param instanceIDs The instance IDs.
+	 * @return A sorted {@link List} with queried entities is returned.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	public List<T> loadAll(Collection<String> instanceIDs) throws DataAccessException {
+		if (instanceIDs.isEmpty()) {
+			// just to be sure...
+			return Collections.emptyList();
+		}
+
+		return load(Filter.idsOnly(entityConfig.getEntityType(), instanceIDs)).getSortedEntities();
+	}
+
+	public ODSModelManager getODSModelManager() {
+		return odsModelManager;
+	}
+
+	// ======================================================================
+	// Protected methods
+	// ======================================================================
+
+	/**
+	 * Adds foreign key select statements to given {@link Query} for each given
+	 * {@link EntityConfig}.
+	 *
+	 * @param query          The {@link Query}.
+	 * @param relatedConfigs The {@code EntityConfig}s.
+	 * @param mandatory      Flag indicates whether given {@code EntityConfig}s are
+	 *                       mandatory or not.
+	 * @return For each {@code EntityConfig} a corresponding {@code
+	 * 		RelationConfig} is returned in a {@code List}.
+	 */
+	protected List<RelationConfig> selectRelations(Query query, List<EntityConfig<?>> relatedConfigs,
+			boolean mandatory) {
+		List<RelationConfig> relationConfigs = new ArrayList<>();
+		EntityType entityType = entityConfig.getEntityType();
+		for (EntityConfig<?> relatedEntityConfig : relatedConfigs) {
+			RelationConfig relationConfig = new RelationConfig(entityType, relatedEntityConfig, mandatory);
+			query.select(relationConfig.relation.getAttribute());
+			relationConfigs.add(relationConfig);
+		}
+
+		return relationConfigs;
+	}
+
+	/**
+	 * Convenience method collects the queried {@link Record} from each
+	 * {@link Result}.
+	 *
+	 * @param results The {@code Result}s.
+	 * @return The queried {@link Record}s are returned.
+	 */
+	protected List<Record> collectRecords(List<Result> results) {
+		return results.stream().map(r -> r.getRecord(entityConfig.getEntityType())).collect(toList());
+	}
+
+	/**
+	 * Loads and maps related entities for each given {@link RelationConfig}.
+	 *
+	 * @param relationConfigs The {@code RelationConfig}s.
+	 * @throws DataAccessException Thrown if unable to load related entities.
+	 */
+	protected void loadRelatedEntities(List<RelationConfig> relationConfigs) throws DataAccessException {
+		for (RelationConfig relationConfig : relationConfigs) {
+			EntityConfig<?> relatedConfig = relationConfig.entityConfig;
+
+			boolean isContextTypeDefined = entityConfig.getContextType().isPresent();
+			for (Entity relatedEntity : new EntityRequest<>(this, relatedConfig)
+					.loadAll(relationConfig.dependants.keySet())) {
+				boolean setByContextType = !isContextTypeDefined && relatedConfig.getContextType().isPresent();
+				for (EntityRecord<?> entityRecord : relationConfig.dependants.remove(relatedEntity.getID())) {
+					setRelatedEntity(entityRecord, relatedEntity,
+							setByContextType ? relatedConfig.getContextType().get() : null);
+				}
+			}
+
+			if (!relationConfig.dependants.isEmpty()) {
+				// this may occur if the instance id of the related entity
+				// is defined, but the entity itself does not exist
+				throw new IllegalStateException(
+						"Unable to load related entities: " + relationConfig.dependants.toString());
+			}
+		}
+	}
+
+	/**
+	 * Assigns given related {@link Entity} to given {@link EntityRecord}.
+	 *
+	 * @param entityRecord  The {@code EntityRecord} which references given
+	 *                      {@code Entity}.
+	 * @param relatedEntity The related {@code Entity}.
+	 * @param contextType   Used as qualifier for relation assignment.
+	 */
+	protected void setRelatedEntity(EntityRecord<?> entityRecord, Entity relatedEntity, ContextType contextType) {
+		if (contextType == null) {
+			entityRecord.core.getMutableStore().set(relatedEntity);
+		} else {
+			entityRecord.core.getMutableStore().set(relatedEntity, contextType);
+		}
+
+		List<TemplateAttribute> templateAttributes = new ArrayList<>();
+		if (entityRecord.entity instanceof ContextComponent && relatedEntity instanceof TemplateComponent) {
+			templateAttributes.addAll(((TemplateComponent) relatedEntity).getTemplateAttributes());
+		} else if (entityRecord.entity instanceof ContextSensor && relatedEntity instanceof TemplateSensor) {
+			templateAttributes.addAll(((TemplateSensor) relatedEntity).getTemplateAttributes());
+		}
+
+		if (!templateAttributes.isEmpty()) {
+			// hide Value containers that are missing in the template
+			Set<String> names = new HashSet<>(entityRecord.core.getValues().keySet());
+			names.remove(Entity.ATTR_NAME);
+			names.remove(Entity.ATTR_MIMETYPE);
+			templateAttributes.stream().map(Entity::getName).forEach(names::remove);
+			entityRecord.core.hideValues(names);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Loads all entities matching given {@link Filter} including all of related
+	 * entities (optional, mandatory and children).
+	 *
+	 * @param filter The {@link Filter}.
+	 * @return Returns the queried {@code EntityResult}.
+	 * @throws DataAccessException Thrown if unable to load entities.
+	 */
+	private EntityResult<T> load(Filter filter) throws DataAccessException {
+		filtered = !filter.isEmtpty() || entityConfig.isReflexive();
+
+		EntityType entityType = entityConfig.getEntityType();
+		Relation reflexiveRelation = entityConfig.isReflexive() ? entityType.getRelation(entityType) : null;
+
+		Query query = queryService.createQuery().selectAll(entityConfig.getEntityType());
+
+		if (entityConfig.isReflexive()) {
+			query.select(reflexiveRelation.getAttribute());
+			// entities with children have to be processed before their
+			// children!
+			query.order(entityType.getIDAttribute());
+		}
+
+		// prepare relations select statements
+		List<RelationConfig> optionalRelations = selectRelations(query, entityConfig.getOptionalConfigs(), false);
+		List<RelationConfig> mandatoryRelations = selectRelations(query, entityConfig.getMandatoryConfigs(), true);
+
+		// configure filter
+		Filter adjustedFilter = Filter.or();
+		if (filtered) {
+			// preserve current conditions
+			adjustedFilter.merge(filter);
+			if (entityConfig.isReflexive()) {
+				// extend to retrieve all reflexive child candidates
+				adjustedFilter.add(ComparisonOperator.IS_NOT_NULL.create(reflexiveRelation.getAttribute(), 0L));
+			}
+		}
+
+		// load entities and prepare mappings for required related entities
+		List<EntityRecord<?>> parentRecords = new ArrayList<>();
+		for (Record record : collectRecords(query.fetch(adjustedFilter))) {
+			Optional<String> reflexiveParentID = Optional.empty();
+			if (entityConfig.isReflexive()) {
+				reflexiveParentID = record.getID(reflexiveRelation);
+			}
+			EntityRecord<T> entityRecord;
+
+			if (entityConfig.isReflexive() && reflexiveParentID.isPresent()) {
+				Optional<EntityRecord<T>> parentRecord = entityResult.get(reflexiveParentID.get());
+				if (!parentRecord.isPresent()) {
+					// this entity's parent was not loaded -> skip
+					continue;
+				}
+
+				entityRecord = entityResult.add(parentRecord.get(), record);
+				parentRecords.add(parentRecord.get());
+			} else {
+				entityRecord = entityResult.add(record);
+			}
+
+			// collect related instance IDs
+			Stream.concat(optionalRelations.stream(), mandatoryRelations.stream())
+					.forEach(rc -> rc.add(entityRecord, record));
+		}
+
+		if (entityResult.isEmpty()) {
+			// no entities found -> neither related nor child entities required
+			return entityResult;
+		}
+
+		// load and map related entities
+		loadRelatedEntities(optionalRelations);
+		loadRelatedEntities(mandatoryRelations);
+
+		// sort children of parent
+		if (entityConfig.isReflexive()) {
+			@SuppressWarnings("unchecked")
+			EntityConfig<Deletable> childConfig = (EntityConfig<Deletable>) entityConfig;
+			for (EntityRecord<?> entityRecord : parentRecords) {
+				entityRecord.core.getChildrenStore().sort(childConfig.getEntityClass(), childConfig.getComparator());
+			}
+		}
+
+		// load children
+		for (EntityConfig<? extends Deletable> childConfig : entityConfig.getChildConfigs()) {
+			cache.add(new ChildRequest<>(this, childConfig).load());
+		}
+
+		return entityResult;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityResult.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityResult.java
new file mode 100644
index 0000000..ac17653
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityResult.java
@@ -0,0 +1,206 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_ENUMERATION_NAME;
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SCALAR_TYPE;
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SEQUENCE;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.DefaultCore;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.EnumRegistry;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
+import org.eclipse.mdm.api.dflt.model.CatalogComponent;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+
+/**
+ * Container for entities by executing an {@link EntityRequest}.
+ *
+ * @param <T> The entity type.
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class EntityResult<T extends Entity> {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<String, EntityRecord<T>> entityRecords = new HashMap<>();
+	private final List<T> entities = new ArrayList<>();
+
+	final EntityRequest<T> request;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param request The associated {@link EntityRequest}.
+	 */
+	EntityResult(EntityRequest<T> request) {
+		this.request = request;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Returns the {@link EntityRecord} identified by given instance ID.
+	 *
+	 * @param id The instance ID.
+	 * @return {@code Optional} is empty if {@code EntityRecord} not found.
+	 */
+	public Optional<EntityRecord<T>> get(String id) {
+		return Optional.ofNullable(entityRecords.get(id));
+	}
+
+	/**
+	 * Creates an {@link EntityRecord} for given {@link Record} and mapps it
+	 * internally by its instance ID.
+	 *
+	 * @param record The {@code Record}.
+	 * @return The created {@code EntityRecord} is returned.
+	 */
+	public EntityRecord<T> add(Record record) {
+		return create(new DefaultCore(record));
+	}
+
+	/**
+	 * Creates an {@link EntityRecord} for given {@link Record} using given parent
+	 * {@code EntityRecord} and maps it internally by its instance ID.
+	 *
+	 * @param parentRecord The created {@code EntityRecord} will be related as a
+	 *                     child with this one.
+	 * @param record       The {@code Record}.
+	 * @return The created {@code EntityRecord} is returned.
+	 */
+	public EntityRecord<T> add(EntityRecord<?> parentRecord, Record record) {
+		Core core = new DefaultCore(record);
+
+		if (CatalogAttribute.class.equals(request.entityConfig.getEntityClass())) {
+			// add read only properties from application model
+			adjustCatalogAttributeCore(parentRecord.entity, core);
+		}
+
+		EntityRecord<T> childRecord = create(core);
+		childRecord.core.getPermanentStore().set(parentRecord.entity);
+		parentRecord.core.getChildrenStore().add((Deletable) childRecord.entity);
+		return childRecord;
+	}
+
+	/**
+	 * Returns the {@link Entity}s of this entity result.
+	 *
+	 * @return Returned {@code Collection} is unmodifiable.
+	 */
+	public List<T> getEntities() {
+		return Collections.unmodifiableList(entities);
+	}
+
+	/**
+	 * Returns the {@link Entity}s of this entity result sorted.
+	 *
+	 * @return Returned {@code Collection} is unmodifiable.
+	 */
+	public List<T> getSortedEntities() {
+		return Collections.unmodifiableList(
+				entities.stream().sorted(request.entityConfig.getComparator()).collect(Collectors.toList()));
+	}
+
+	/**
+	 * Returns the instance IDs of the entities held by this entity result.
+	 *
+	 * @return Returned {@code Collection} is unmodifiable.
+	 */
+	public Collection<String> getIDs() {
+		return Collections.unmodifiableCollection(entityRecords.keySet());
+	}
+
+	/**
+	 * Checks whether this entity result holds entities or is empty.
+	 *
+	 * @return Returns {@code true} if this entity result has no entities.
+	 */
+	public boolean isEmpty() {
+		return entities.isEmpty();
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Adds further meta data to the given {@link CatalogAttribute} {@link Core}.
+	 *
+	 * @param catalogComponent     The parent {@link CatalogComponent}.
+	 * @param catalogAttributeCore The {@code CatalogAttribute} {@code Core}.
+	 */
+	private void adjustCatalogAttributeCore(Entity catalogComponent, Core catalogAttributeCore) {
+		EntityType entityType = request.odsModelManager.getEntityType(catalogComponent.getName());
+		Attribute attribute = entityType.getAttribute(catalogAttributeCore.getValues().get(Entity.ATTR_NAME).extract());
+
+		Map<String, Value> values = catalogAttributeCore.getValues();
+		Value enumerationName = ValueType.STRING.create(VATTR_ENUMERATION_NAME);
+		values.put(VATTR_ENUMERATION_NAME, enumerationName);
+		if (attribute.getValueType().isEnumerationType()) {
+			enumerationName.set(attribute.getEnumObj().getName());
+		}
+
+		Enumeration<?> scalarTypeObj = EnumRegistry.getInstance().get("ScalarType");
+		Value scalarType = ValueType.ENUMERATION.create(scalarTypeObj, VATTR_SCALAR_TYPE);
+		scalarType.set(scalarTypeObj.valueOf(attribute.getValueType().toSingleType().name()));
+		values.put(VATTR_SCALAR_TYPE, scalarType);
+
+		values.put(VATTR_SEQUENCE, ValueType.BOOLEAN.create(VATTR_SEQUENCE, attribute.getValueType().isSequence()));
+	}
+
+	/**
+	 * Creates a new {@link EntityRecord} instance for given {@link Core}. The
+	 * {@link EntityRecord} is internally mapped the its instance ID.
+	 *
+	 * @param core The {@code Core}.
+	 * @return The created {@link EntityRecord} is returned.
+	 */
+	private EntityRecord<T> create(Core core) {
+		ODSEntityFactory odsEntityFactory = new ODSEntityFactory(request.getODSModelManager(), null);
+		EntityRecord<T> entityRecord = new EntityRecord<>(
+				odsEntityFactory.createEntity(request.entityConfig.getEntityClass(), core), core);
+		entityRecords.put(core.getID(), entityRecord);
+		entities.add(entityRecord.entity);
+		return entityRecord;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/RelationConfig.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/RelationConfig.java
new file mode 100644
index 0000000..1a4f8c9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/RelationConfig.java
@@ -0,0 +1,86 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+
+/**
+ * Utility class to collect {@link EntityRecord} referencing entities of the
+ * same type specified by an instance of this class.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class RelationConfig {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	final Map<String, List<EntityRecord<?>>> dependants = new HashMap<>();
+	final EntityConfig<?> entityConfig;
+	final Relation relation;
+	final boolean mandatory;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param source       The source {@link EntityType}.
+	 * @param entityConfig The target {@link EntityConfig}.
+	 * @param mandatory    Flag indicates whether a related must exist or not.
+	 */
+	public RelationConfig(EntityType source, EntityConfig<?> entityConfig, boolean mandatory) {
+		this.entityConfig = entityConfig;
+		relation = source.getRelation(entityConfig.getEntityType());
+		this.mandatory = mandatory;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Given {@link EntityRecord} depends on {@link Entity}s which are loaded by
+	 * processing this relation config. Therefore given {@code EntityRecord} cached
+	 * and satisfied as soon as the corresponding entities are loaded.
+	 *
+	 * @param entityRecord The dependant {@code EntityRecord}.
+	 * @param record       The {@link Record} associated with given
+	 *                     {@link EntityRecord}.
+	 */
+	public void add(EntityRecord<?> entityRecord, Record record) {
+		Optional<String> relatedEntityID = record.getID(relation);
+		if (relatedEntityID.isPresent()) {
+			dependants.computeIfAbsent(relatedEntityID.get(), k -> new ArrayList<>()).add(entityRecord);
+		} else if (mandatory) {
+			throw new IllegalStateException("Mandatory relation unsatisfied for relation " + relation.getName());
+		}
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
new file mode 100644
index 0000000..0b6e839
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
@@ -0,0 +1,370 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup.config;
+
+import java.util.Locale;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.ContextSensor;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Environment;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Parameter;
+import org.eclipse.mdm.api.base.model.ParameterSet;
+import org.eclipse.mdm.api.base.model.PhysicalDimension;
+import org.eclipse.mdm.api.base.model.Quantity;
+import org.eclipse.mdm.api.base.model.Sortable;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
+import org.eclipse.mdm.api.dflt.model.CatalogComponent;
+import org.eclipse.mdm.api.dflt.model.CatalogSensor;
+import org.eclipse.mdm.api.dflt.model.Classification;
+import org.eclipse.mdm.api.dflt.model.Domain;
+import org.eclipse.mdm.api.dflt.model.ExtSystem;
+import org.eclipse.mdm.api.dflt.model.ExtSystemAttribute;
+import org.eclipse.mdm.api.dflt.model.MDMAttribute;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.dflt.model.ProjectDomain;
+import org.eclipse.mdm.api.dflt.model.Role;
+import org.eclipse.mdm.api.dflt.model.Status;
+import org.eclipse.mdm.api.dflt.model.SystemParameter;
+import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
+import org.eclipse.mdm.api.dflt.model.TemplateComponent;
+import org.eclipse.mdm.api.dflt.model.TemplateRoot;
+import org.eclipse.mdm.api.dflt.model.TemplateSensor;
+import org.eclipse.mdm.api.dflt.model.TemplateTest;
+import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
+import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage;
+import org.eclipse.mdm.api.dflt.model.UserParameter;
+import org.eclipse.mdm.api.dflt.model.ValueList;
+import org.eclipse.mdm.api.dflt.model.ValueListValue;
+import org.eclipse.mdm.api.dflt.model.Versionable;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultEntityConfigRepositoryLoader implements EntityConfigRepositoryLoader {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(DefaultEntityConfigRepositoryLoader.class);
+
+	EntityConfigRepository entityConfigRepository;
+
+	public DefaultEntityConfigRepositoryLoader() {
+	}
+
+	/**
+	 * Loads the {@link EntityConfig}s.
+	 * 
+	 * @return
+	 */
+	@Override
+	public EntityConfigRepository loadEntityConfigurations(ODSModelManager modelManager) {
+		LOGGER.debug("Loading entity configurations...");
+		long start = System.currentTimeMillis();
+
+		entityConfigRepository = new EntityConfigRepository();
+
+		entityConfigRepository.register(create(modelManager, new Key<>(Role.class), "Role", false));
+
+		// Environment | Project | Pool | PhysicalDimension | User | Measurement
+		// | ChannelGroup
+		entityConfigRepository.register(create(modelManager, new Key<>(Environment.class), "Environment", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(Project.class), "Project", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(Pool.class), "StructureLevel", true));
+		entityConfigRepository
+				.register(create(modelManager, new Key<>(PhysicalDimension.class), "PhysDimension", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(User.class), "User", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(Measurement.class), "MeaResult", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(ChannelGroup.class), "SubMatrix", false));
+
+		// Unit
+		EntityConfig<Unit> unitConfig = create(modelManager, new Key<>(Unit.class), "Unit", false);
+		unitConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(PhysicalDimension.class)));
+		entityConfigRepository.register(unitConfig);
+
+		// Quantity
+		EntityConfig<Quantity> quantityConfig = create(modelManager, new Key<>(Quantity.class), "Quantity", false);
+		quantityConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class)));
+		entityConfigRepository.register(quantityConfig);
+
+		// Channel
+		EntityConfig<Channel> channelConfig = create(modelManager, new Key<>(Channel.class), "MeaQuantity", false);
+		channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Unit.class)));
+		channelConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class)));
+		entityConfigRepository.register(channelConfig);
+
+		// ValueList
+		EntityConfig<ValueListValue> valueListValueConfig = create(modelManager, new Key<>(ValueListValue.class),
+				"ValueListValue", true);
+		valueListValueConfig.setComparator(Sortable.COMPARATOR);
+		EntityConfig<ValueList> valueListConfig = create(modelManager, new Key<>(ValueList.class), "ValueList", true);
+		valueListConfig.addChild(valueListValueConfig);
+		entityConfigRepository.register(valueListConfig);
+
+		// ParameterSet
+		EntityConfig<Parameter> parameterConfig = create(modelManager, new Key<>(Parameter.class), "ResultParameter",
+				true);
+		parameterConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Unit.class)));
+		EntityConfig<ParameterSet> parameterSetConfig = create(modelManager, new Key<>(ParameterSet.class),
+				"ResultParameterSet", true);
+		parameterSetConfig.addChild(parameterConfig);
+		entityConfigRepository.register(parameterSetConfig);
+
+		// CatalogComponents
+		registerCatalogComponent(modelManager, ContextType.UNITUNDERTEST);
+		registerCatalogComponent(modelManager, ContextType.TESTSEQUENCE);
+		registerCatalogComponent(modelManager, ContextType.TESTEQUIPMENT);
+
+		// TemplateRoots
+		registerTemplateRoot(modelManager, ContextType.UNITUNDERTEST);
+		registerTemplateRoot(modelManager, ContextType.TESTSEQUENCE);
+		registerTemplateRoot(modelManager, ContextType.TESTEQUIPMENT);
+
+		// TemplateTestStep
+		EntityConfig<TemplateTestStep> templateTestStepConfig = create(modelManager, new Key<>(TemplateTestStep.class),
+				"TplTestStep", true);
+		templateTestStepConfig
+				.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.UNITUNDERTEST)));
+		templateTestStepConfig
+				.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTSEQUENCE)));
+		templateTestStepConfig
+				.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, ContextType.TESTEQUIPMENT)));
+		templateTestStepConfig.setComparator(Versionable.COMPARATOR);
+		entityConfigRepository.register(templateTestStepConfig);
+
+		// Status
+		entityConfigRepository.register(create(modelManager, new Key<>(Status.class), "Status", false));
+
+		// ProjectDomain
+		entityConfigRepository.register(create(modelManager, new Key<>(ProjectDomain.class), "ProjectDomain", false));
+
+		// Domain
+		entityConfigRepository.register(create(modelManager, new Key<>(Domain.class), "Domain", false));
+
+		// Classification
+		EntityConfig<Classification> classificationConfig = create(modelManager, new Key<>(Classification.class),
+				"Classification", false);
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Status.class)));
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ProjectDomain.class)));
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Domain.class)));
+		entityConfigRepository.register(classificationConfig);
+
+		// TestStep
+		EntityConfig<TestStep> testStepConfig = create(modelManager, new Key<>(TestStep.class), "TestStep", true);
+		// testStepConfig.addMandatory(entityConfigRepository.findRoot(new
+		// Key<>(Status.class, TestStep.class)));
+		testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTestStep.class)));
+		testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Classification.class)));
+		testStepConfig.setComparator(Sortable.COMPARATOR);
+		entityConfigRepository.register(testStepConfig);
+
+		// TemplateTest
+		EntityConfig<TemplateTestStepUsage> templateTestStepUsageConfig = create(modelManager,
+				new Key<>(TemplateTestStepUsage.class), "TplTestStepUsage", true);
+		templateTestStepUsageConfig.addMandatory(templateTestStepConfig);
+		templateTestStepUsageConfig.setComparator(Sortable.COMPARATOR);
+		EntityConfig<TemplateTest> templateTestConfig = create(modelManager, new Key<>(TemplateTest.class), "TplTest",
+				true);
+		templateTestConfig.addChild(templateTestStepUsageConfig);
+		templateTestConfig.setComparator(Versionable.COMPARATOR);
+		entityConfigRepository.register(templateTestConfig);
+
+		// Status Test
+		// TODO check MIME type genration
+		// entityConfigRepository.register(create(new Key<>(Status.class,
+		// Test.class), "StatusTest", true));
+
+		// Test
+		EntityConfig<Test> testConfig = create(modelManager, new Key<>(Test.class), "Test", true);
+		testConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(User.class)));
+		// testConfig.addMandatory(entityConfigRepository.findRoot(new
+		// Key<>(Status.class, Test.class)));
+		testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTest.class)));
+		testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Classification.class)));
+		entityConfigRepository.register(testConfig);
+
+		// ContextRoots
+		registerContextRoot(modelManager, ContextType.UNITUNDERTEST);
+		registerContextRoot(modelManager, ContextType.TESTSEQUENCE);
+		registerContextRoot(modelManager, ContextType.TESTEQUIPMENT);
+
+		entityConfigRepository
+				.register(create(modelManager, new Key<>(SystemParameter.class), "SystemParameter", false));
+		entityConfigRepository.register(create(modelManager, new Key<>(UserParameter.class), "UserParameter", false));
+
+		// MDMAttr for external systems
+		EntityConfig<MDMAttribute> mdmAttrConfig = create(modelManager, new Key<>(MDMAttribute.class), "MDMAttr", true);
+		entityConfigRepository.register(mdmAttrConfig);
+		// ExtSystemAttr for external systems
+		EntityConfig<ExtSystemAttribute> extSystemAttrConfig = create(modelManager, new Key<>(ExtSystemAttribute.class), "ExtSystemAttr", true);
+		extSystemAttrConfig.addChild(mdmAttrConfig);
+		entityConfigRepository.register(extSystemAttrConfig);
+		// The external systems themselves
+		EntityConfig<ExtSystem> extSystemConfig = create(modelManager, new Key<>(ExtSystem.class), "ExtSystem", false);
+		entityConfigRepository.register(extSystemConfig);
+
+		LOGGER.debug("Entity configurations loaded in {} ms.", System.currentTimeMillis() - start);
+		return entityConfigRepository;
+	}
+
+	/**
+	 * Loads the {@link EntityConfig}s required for {@link ContextRoot} with given
+	 * {@link ContextType}.
+	 *
+	 * @param contextType The {@code ContextType}.
+	 */
+	private void registerContextRoot(ODSModelManager modelManager, ContextType contextType) {
+		EntityConfig<ContextRoot> contextRootConfig = create(modelManager, new Key<>(ContextRoot.class, contextType),
+				ODSUtils.CONTEXTTYPES.get(contextType), true);
+		contextRootConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(TemplateRoot.class, contextType)));
+		for (Relation contextComponentRelation : contextRootConfig.getEntityType().getChildRelations()) {
+			EntityType contextComponentEntityType = contextComponentRelation.getTarget();
+			EntityConfig<ContextComponent> contextComponentConfig = create(modelManager,
+					new Key<>(ContextComponent.class, contextType), contextComponentEntityType.getName(), true);
+			contextComponentConfig
+					.addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateComponent.class, contextType)));
+			contextRootConfig.addChild(contextComponentConfig);
+			if (contextType.isTestEquipment()) {
+				for (Relation contextSensorRelation : contextComponentEntityType.getChildRelations()) {
+					EntityType contextSensorEntityType = contextSensorRelation.getTarget();
+					EntityConfig<ContextSensor> contextSensorConfig = create(modelManager,
+							new Key<>(ContextSensor.class), contextSensorEntityType.getName(), true);
+					contextSensorConfig
+							.addInherited(entityConfigRepository.findImplicit(new Key<>(TemplateSensor.class)));
+					contextComponentConfig.addChild(contextSensorConfig);
+				}
+			}
+		}
+		entityConfigRepository.register(contextRootConfig);
+	}
+
+	/**
+	 * Loads the {@link EntityConfig}s required for {@link TemplateRoot} with given
+	 * {@link ContextType}.
+	 *
+	 * @param contextType The {@code ContextType}.
+	 */
+	private void registerTemplateRoot(ODSModelManager modelManager, ContextType contextType) {
+		String odsName = ODSUtils.CONTEXTTYPES.get(contextType);
+		EntityConfig<TemplateAttribute> templateAttributeConfig = create(modelManager,
+				new Key<>(TemplateAttribute.class, contextType), "Tpl" + odsName + "Attr", true);
+		templateAttributeConfig
+				.addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class, contextType)));
+		templateAttributeConfig.setComparator(TemplateAttribute.COMPARATOR);
+		EntityConfig<TemplateComponent> templateComponentConfig = create(modelManager,
+				new Key<>(TemplateComponent.class, contextType), "Tpl" + odsName + "Comp", true);
+		templateComponentConfig.addChild(templateAttributeConfig);
+		templateComponentConfig
+				.addMandatory(entityConfigRepository.findRoot(new Key<>(CatalogComponent.class, contextType)));
+		templateComponentConfig.addChild(templateComponentConfig);
+		templateComponentConfig.setComparator(Sortable.COMPARATOR);
+		if (contextType.isTestEquipment()) {
+			EntityConfig<TemplateAttribute> templateSensorAttributeConfig = create(modelManager,
+					new Key<>(TemplateAttribute.class), "TplSensorAttr", true);
+			templateSensorAttributeConfig.setComparator(TemplateAttribute.COMPARATOR);
+			templateSensorAttributeConfig
+					.addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogAttribute.class)));
+			EntityConfig<TemplateSensor> templateSensorConfig = create(modelManager, new Key<>(TemplateSensor.class),
+					"TplSensor", true);
+			templateSensorConfig.addChild(templateSensorAttributeConfig);
+			templateSensorConfig.addMandatory(entityConfigRepository.findRoot(new Key<>(Quantity.class)));
+			templateSensorConfig.addInherited(entityConfigRepository.findImplicit(new Key<>(CatalogSensor.class)));
+			templateSensorConfig.setComparator(Sortable.COMPARATOR);
+			templateComponentConfig.addChild(templateSensorConfig);
+		}
+		EntityConfig<TemplateRoot> templateRootConfig = create(modelManager, new Key<>(TemplateRoot.class, contextType),
+				"Tpl" + odsName + "Root", true);
+		templateRootConfig.addChild(templateComponentConfig);
+		templateRootConfig.setComparator(Versionable.COMPARATOR);
+		entityConfigRepository.register(templateRootConfig);
+	}
+
+	/**
+	 * Loads the {@link EntityConfig}s required for {@link CatalogComponent} with
+	 * given {@link ContextType}.
+	 *
+	 * @param contextType The {@code ContextType}.
+	 */
+	private void registerCatalogComponent(ODSModelManager modelManager, ContextType contextType) {
+		String odsName = ODSUtils.CONTEXTTYPES.get(contextType);
+		EntityConfig<CatalogAttribute> catalogAttributeConfig = create(modelManager,
+				new Key<>(CatalogAttribute.class, contextType), "Cat" + odsName + "Attr", true);
+		catalogAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class)));
+		catalogAttributeConfig.setComparator(Sortable.COMPARATOR);
+		EntityConfig<CatalogComponent> catalogComponentConfig = create(modelManager,
+				new Key<>(CatalogComponent.class, contextType), "Cat" + odsName + "Comp", true);
+		catalogComponentConfig.addChild(catalogAttributeConfig);
+		if (contextType.isTestEquipment()) {
+			EntityConfig<CatalogAttribute> catalogSensorAttributeConfig = create(modelManager,
+					new Key<>(CatalogAttribute.class), "CatSensorAttr", true);
+			catalogSensorAttributeConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ValueList.class)));
+			EntityConfig<CatalogSensor> catalogSensorConfig = create(modelManager, new Key<>(CatalogSensor.class),
+					"CatSensor", true);
+			catalogSensorConfig.addChild(catalogSensorAttributeConfig);
+			catalogComponentConfig.addChild(catalogSensorConfig);
+		}
+		entityConfigRepository.register(catalogComponentConfig);
+	}
+
+	/**
+	 * Creates a new {@link EntityConfig}.
+	 *
+	 * @param            <T> The entity type.
+	 * @param key        Used as identifier.
+	 * @param typeName   Name of the associated {@link EntityType}.
+	 * @param appendName Flag indicates whether to append the entity types base name
+	 *                   to the MIME type.
+	 * @return The created {@code EntityConfig} is returned.
+	 */
+	private <T extends Entity> EntityConfig<T> create(ODSModelManager modelManager, Key<T> key, String typeName,
+			boolean appendName) {
+		EntityConfig<T> entityConfig = new EntityConfig<>(key);
+		ODSEntityType entityType = (ODSEntityType) modelManager.getEntityType(typeName);
+		entityConfig.setEntityType(entityType);
+		entityConfig.setMimeType(buildDefaultMimeType(entityType, appendName));
+		return entityConfig;
+	}
+
+	/**
+	 * Creates a default MIME type for given {@link EntityType}.
+	 *
+	 * @param entityType The {@code EntityType}.
+	 * @param appendName Flag indicates whether to append the entity types base name
+	 *                   to the MIME type.
+	 * @return The created MIME type {@code String} is returned.
+	 */
+	private String buildDefaultMimeType(ODSEntityType entityType, boolean appendName) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("application/x-asam.");
+		sb.append(entityType.getBaseName().toLowerCase(Locale.ROOT));
+		if (appendName) {
+			sb.append('.').append(entityType.getName().toLowerCase(Locale.ROOT));
+		}
+		return sb.toString();
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfig.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfig.java
new file mode 100644
index 0000000..ec95b36
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfig.java
@@ -0,0 +1,372 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup.config;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.StatusAttachable;
+
+/**
+ * Describes the composition of an {@link Entity} with its mandatory, optional
+ * and child relations.
+ *
+ * @param <T> The entity type.
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class EntityConfig<T extends Entity> {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final List<EntityConfig<? extends Deletable>> childConfigs = new ArrayList<>();
+
+	private final List<EntityConfig<?>> inheritedConfigs = new ArrayList<>();
+	private final List<EntityConfig<?>> mandatoryConfigs = new ArrayList<>();
+	private final List<EntityConfig<?>> optionalConfigs = new ArrayList<>();
+
+	private Comparator<? super T> comparator = Entity.COMPARATOR;
+
+	private final Key<T> key;
+
+	private EntityType entityType;
+
+	private boolean reflexive;
+	private String mimeType;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param key The {@link Key} this entity config is bound to.
+	 */
+	public EntityConfig(Key<T> key) {
+		this.key = key;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Returns the {@link Key} this entity config is bound to.
+	 *
+	 * @return The {@code Key} is returned.
+	 */
+	public Key<T> getKey() {
+		return key;
+	}
+
+	/**
+	 * Returns the {@link Entity} class.
+	 *
+	 * @return The {@code Entity} class is returned.
+	 */
+	public Class<T> getEntityClass() {
+		return key.entityClass;
+	}
+
+	/**
+	 * Returns the {@link StatusAttachable} class.
+	 *
+	 * @return Optional is empty if {@code StatusAttachable} is undefined.
+	 */
+	public Optional<Class<? extends StatusAttachable>> getStatusAttachableClass() {
+		return Optional.ofNullable(key.statusAttachableClass);
+	}
+
+	/**
+	 * Returns the {@link ContextType}.
+	 *
+	 * @return Optional is empty {@code ContextType} is undefined.
+	 */
+	public Optional<ContextType> getContextType() {
+		return Optional.ofNullable(key.contextType);
+	}
+
+	/**
+	 * Returns the {@link Comparator} for {@link Entity}s associated with this
+	 * entity config.
+	 *
+	 * @return The {@code Comparator} is returned.
+	 */
+	public Comparator<? super T> getComparator() {
+		return comparator;
+	}
+
+	/**
+	 * Returns the {@link EntityType} of this entity config.
+	 *
+	 * @return The {@code EntityType} is returned.
+	 */
+	public EntityType getEntityType() {
+		return entityType;
+	}
+
+	/**
+	 * Returns the default MIME type for a newly created {@link Entity} associated
+	 * with this entity config.
+	 *
+	 * @return The default MIME type is returned.
+	 */
+	public String getMimeType() {
+		return mimeType;
+	}
+
+	/**
+	 * Returns all related child configs.
+	 *
+	 * @return The returned {@code List} is unmodifiable.
+	 */
+	public List<EntityConfig<? extends Deletable>> getChildConfigs() {
+		return Collections.unmodifiableList(childConfigs);
+	}
+
+	/**
+	 * Returns all related inherited configs.
+	 *
+	 * @return The returned {@code List} is unmodifiable.
+	 */
+	public List<EntityConfig<?>> getInheritedConfigs() {
+		return Collections.unmodifiableList(inheritedConfigs);
+	}
+
+	/**
+	 * Returns all related mandatory configs.
+	 *
+	 * @return The returned {@code List} is unmodifiable.
+	 */
+	public List<EntityConfig<?>> getMandatoryConfigs() {
+		return Collections.unmodifiableList(mandatoryConfigs);
+	}
+
+	/**
+	 * Returns all related optional configs.
+	 *
+	 * @return The returned {@code List} is unmodifiable.
+	 */
+	public List<EntityConfig<?>> getOptionalConfigs() {
+		return Collections.unmodifiableList(optionalConfigs);
+	}
+
+	/**
+	 * Checks whether {@link Entity}s associated with this entity config may have
+	 * children of the same type.
+	 *
+	 * @return Returns {@code true} if this entity config is reflexive.
+	 */
+	public boolean isReflexive() {
+		return reflexive;
+	}
+
+	/**
+	 * Sets a new {@link Comparator} for this entity config.
+	 *
+	 * @param comparator The new {@code Comparator}.
+	 */
+	public void setComparator(Comparator<? super T> comparator) {
+		this.comparator = comparator;
+	}
+
+	/**
+	 * Sets the {@link EntityType} for this entity config.
+	 *
+	 * @param entityType The {@code EntityType}.
+	 * @throws IllegalStateException Thrown if {@link EntityType} is already
+	 *                               defined.
+	 */
+	public void setEntityType(EntityType entityType) {
+		if (this.entityType != null) {
+			throw new IllegalStateException("It is not allowed to override the entity type.");
+		}
+
+		this.entityType = entityType;
+	}
+
+	/**
+	 * Sets the default MIME type for newly created {@link Entity}s associated with
+	 * this entity config.
+	 *
+	 * @param mimeType The default MIME type.
+	 * @throws IllegalStateException Thrown if default MIME type is already defined.
+	 */
+	public void setMimeType(String mimeType) {
+		if (this.mimeType != null && !this.mimeType.isEmpty()) {
+			throw new IllegalStateException("It is not allowed to override the default MIME type.");
+		}
+
+		this.mimeType = mimeType;
+	}
+
+	/**
+	 * Adds a related inherited {@link EntityConfig}.
+	 *
+	 * @param entityConfig The {@code EntityConfig}.
+	 */
+	public void addInherited(EntityConfig<?> entityConfig) {
+		inheritedConfigs.add(entityConfig);
+	}
+
+	/**
+	 * Adds a related mandatory {@link EntityConfig}.
+	 *
+	 * @param entityConfig The {@code EntityConfig}.
+	 */
+	public void addMandatory(EntityConfig<?> entityConfig) {
+		mandatoryConfigs.add(entityConfig);
+	}
+
+	/**
+	 * Adds a related optional {@link EntityConfig}.
+	 *
+	 * @param entityConfig The {@code EntityConfig}.
+	 */
+	public void addOptional(EntityConfig<?> entityConfig) {
+		optionalConfigs.add(entityConfig);
+	}
+
+	/**
+	 * Adds a related child {@link EntityConfig}.
+	 *
+	 * @param childConfig The {@code EntityConfig}.
+	 */
+	public void addChild(EntityConfig<? extends Deletable> childConfig) {
+		if (this == childConfig) {
+			reflexive = true;
+		} else {
+			childConfigs.add(childConfig);
+		}
+	}
+
+	// ======================================================================
+	// Inner classes
+	// ======================================================================
+
+	/**
+	 * Used as an identifier for {@link EntityConfig}s.
+	 *
+	 * @param <T> The entity type.
+	 */
+	public static final class Key<T extends Entity> {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		final Class<? extends StatusAttachable> statusAttachableClass;
+		final Class<T> entityClass;
+		final ContextType contextType;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param entityClass The {@link Entity} class.
+		 */
+		public Key(Class<T> entityClass) {
+			this.entityClass = entityClass;
+			statusAttachableClass = null;
+			contextType = null;
+		}
+
+		/**
+		 * Constructor.
+		 *
+		 * @param entityClass           The {@link Entity} class.
+		 * @param statusAttachableClass The {@link StatusAttachable} class.
+		 */
+		public Key(Class<T> entityClass, Class<? extends StatusAttachable> statusAttachableClass) {
+			this.statusAttachableClass = statusAttachableClass;
+			this.entityClass = entityClass;
+			contextType = null;
+		}
+
+		/**
+		 * Constructor.
+		 *
+		 * @param entityClass The {@link Entity} class.
+		 * @param contextType The {@link ContextType}.
+		 */
+		public Key(Class<T> entityClass, ContextType contextType) {
+			this.entityClass = entityClass;
+			this.contextType = contextType;
+			statusAttachableClass = null;
+		}
+
+		// ======================================================================
+		// Public methods
+		// ======================================================================
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public int hashCode() {
+			return Objects.hash(entityClass, statusAttachableClass, contextType);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public boolean equals(Object object) {
+			// reference check (this == object) omitted
+			if (object instanceof Key) {
+				Key<?> other = (Key<?>) object;
+				return Objects.equals(entityClass, other.entityClass)
+						&& Objects.equals(statusAttachableClass, other.statusAttachableClass)
+						&& Objects.equals(contextType, other.contextType);
+			}
+
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public String toString() {
+			StringBuilder sb = new StringBuilder(entityClass.getSimpleName());
+
+			if (statusAttachableClass != null) {
+				sb.append('_').append(statusAttachableClass.getSimpleName());
+			}
+
+			if (contextType != null) {
+				sb.append('_').append(contextType);
+			}
+
+			return sb.toString();
+		}
+
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepository.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepository.java
new file mode 100644
index 0000000..dad79c4
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepository.java
@@ -0,0 +1,198 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+
+/**
+ * Repository for {@link EntityConfig}s.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class EntityConfigRepository {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	// root types
+	private final Map<Key<?>, EntityConfig<?>> entityConfigs = new HashMap<>();
+
+	// child types (implicit load only!)
+	private final Map<Key<?>, EntityConfig<?>> childConfigs = new HashMap<>();
+	private final Map<String, EntityConfig<?>> contextConfigs = new HashMap<>();
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Returns the {@link EntityConfig} associated with given {@link Key}. This
+	 * method tries to find the associated {@code EntityConfig} in the root
+	 * configurations. If it is not found there, then it tries to find it in the
+	 * child {@code EntityConfig}s.
+	 *
+	 * @param <T> The entity type.
+	 * @param key Used as identifier.
+	 * @return The {@code EntityConfig} is returned.
+	 * @throws IllegalArgumentException Thrown if unable to find associated
+	 *                                  {@code EntityConfig}.
+	 */
+	public <T extends Entity> EntityConfig<T> find(Key<T> key) {
+		Optional<EntityConfig<T>> entityConfig = get(entityConfigs, key);
+		if (entityConfig.isPresent()) {
+			return entityConfig.get();
+		}
+
+		return get(childConfigs, key)
+				.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
+	}
+
+	/**
+	 * Returns the {@link EntityConfig} associated with given {@link Key}. This
+	 * method tries to find the associated {@code EntityConfig} in the root
+	 * configurations.
+	 *
+	 * @param <T> The entity type.
+	 * @param key Used as identifier.
+	 * @return The {@code EntityConfig} is returned.
+	 * @throws IllegalArgumentException Thrown if unable to find associated
+	 *                                  {@code EntityConfig}.
+	 */
+	public <T extends Entity> EntityConfig<T> findRoot(Key<T> key) {
+		return get(entityConfigs, key)
+				.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
+	}
+
+	/**
+	 * Returns the {@link EntityConfig} associated with given {@link Key}. This
+	 * method tries to find the associated {@code EntityConfig} in the child
+	 * configurations.
+	 *
+	 * @param <T> The entity type.
+	 * @param key Used as identifier.
+	 * @return The {@code EntityConfig} is returned.
+	 * @throws IllegalArgumentException Thrown if unable to find associated
+	 *                                  {@code EntityConfig}.
+	 */
+	public <T extends Entity> EntityConfig<T> findImplicit(Key<T> key) {
+		return get(childConfigs, key)
+				.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
+	}
+
+	/**
+	 * Returns the {@link EntityConfig} associated with given {@link EntityType}.
+	 *
+	 * @param entityType Its name is used as identifier.
+	 * @return The {@code EntityConfig} is returned.
+	 * @throws IllegalArgumentException Thrown if unable to find associated
+	 *                                  {@code EntityConfig}.
+	 */
+	public EntityConfig<?> find(EntityType entityType) {
+		Optional<EntityConfig<?>> entityConfig = entityConfigs.values().stream()
+				.filter(ec -> ec.getEntityType().equals(entityType)).findFirst();
+		if (entityConfig.isPresent()) {
+			// entity config is a root type
+			return entityConfig.get();
+		}
+
+		entityConfig = childConfigs.values().stream().filter(ec -> ec.getEntityType().equals(entityType)).findFirst();
+		if (entityConfig.isPresent()) {
+			// entity config is an implicitly loaded child type
+			return entityConfig.get();
+		}
+
+		EntityConfig<?> config = contextConfigs.get(entityType.getName());
+		if (config == null) {
+			throw new IllegalArgumentException("Entity configuration for type '" + entityType + "' not found.");
+		}
+
+		// config is either a context component or context sensor type
+		return config;
+	}
+
+	/**
+	 * Stores given {@link EntityConfig} in this repository.
+	 *
+	 * @param entityConfig The {@code EntityConfig}.
+	 * @throws IllegalArgumentException Thrown if an attempt to overwrite an
+	 *                                  existing {@code EntityConfig} is recorded.
+	 */
+	public void register(EntityConfig<?> entityConfig) {
+		registerChildConfigs(entityConfig);
+
+		EntityConfig<?> currentByClass = entityConfigs.put(entityConfig.getKey(), entityConfig);
+		if (currentByClass != null) {
+			throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Recursively registers all child configurations of given {@link EntityConfig}.
+	 *
+	 * @param entityConfig The {@code EntityConfig}.
+	 * @throws IllegalArgumentException Thrown if an attempt to overwrite an
+	 *                                  existing {@code EntityConfig} is recorded.
+	 */
+	private void registerChildConfigs(EntityConfig<?> entityConfig) {
+		Class<? extends Entity> entityClass = entityConfig.getEntityClass();
+		if (ContextRoot.class.equals(entityClass) || ContextComponent.class.equals(entityClass)) {
+			for (EntityConfig<?> childConfig : entityConfig.getChildConfigs()) {
+				if (contextConfigs.put(childConfig.getEntityType().getName(), childConfig) != null) {
+					throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
+				}
+
+				registerChildConfigs(childConfig);
+			}
+
+			return;
+		}
+		for (EntityConfig<?> childConfig : entityConfig.getChildConfigs()) {
+			if (childConfigs.put(childConfig.getKey(), childConfig) != null) {
+				throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
+			}
+
+			registerChildConfigs(childConfig);
+		}
+	}
+
+	/**
+	 * Retrieves the {@link EntityConfig} associated with given {@link Key} from
+	 * given {@code Map}.
+	 *
+	 * @param <T>           The entity type.
+	 * @param entityConfigs Used to retrieve requested {@code EntityConfig}.
+	 * @param key           Used as identifier.
+	 * @return {@code Optional} is empty if {@code EntityConfig} not found.
+	 */
+	@SuppressWarnings("unchecked")
+	private static <T extends Entity> Optional<EntityConfig<T>> get(Map<Key<?>, EntityConfig<?>> entityConfigs,
+			Key<T> key) {
+		return Optional.ofNullable((EntityConfig<T>) entityConfigs.get(key));
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java
new file mode 100644
index 0000000..4dc521a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/EntityConfigRepositoryLoader.java
@@ -0,0 +1,27 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.lookup.config;
+
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+
+public interface EntityConfigRepositoryLoader {
+
+	/**
+	 * Loads the {@link EntityConfigRepository}.
+	 * 
+	 * @return
+	 */
+	EntityConfigRepository loadEntityConfigurations(ODSModelManager modelManager);
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/NotificationEntityLoader.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/NotificationEntityLoader.java
new file mode 100644
index 0000000..4935288
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/NotificationEntityLoader.java
@@ -0,0 +1,220 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextDescribable;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NotificationEntityLoader {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(NotificationEntityLoader.class);
+
+	private final ODSModelManager modelManager;
+	private final QueryService queryService;
+	private final EntityLoader loader;
+
+	private boolean loadContextDescribable;
+
+	public NotificationEntityLoader(ODSModelManager modelManager, QueryService queryService,
+			boolean loadContextDescribable) {
+		this.modelManager = modelManager;
+		this.queryService = queryService;
+		this.loader = new EntityLoader(modelManager, queryService);
+		this.loadContextDescribable = loadContextDescribable;
+	}
+
+	public <T extends Entity> T load(Key<T> key, String userId) throws DataAccessException {
+		return loader.load(key, userId);
+	}
+
+	public List<? extends Entity> loadEntities(String aid, List<String> ids) throws DataAccessException {
+		return loadEntities(modelManager.getEntityType(aid), ids);
+	}
+
+	/**
+	 * @param entityType entity type of the entities to load.
+	 * @param ids        IDs of the entities to load.
+	 * @return loaded entities.
+	 * @throws DataAccessException Throw if the entities cannot be loaded.
+	 */
+	public List<? extends Entity> loadEntities(EntityType entityType, List<String> ids) throws DataAccessException {
+
+		if (ids.isEmpty()) {
+			return Collections.emptyList();
+		}
+
+		EntityConfig<?> config = getEntityConfig(entityType);
+
+		if (config == null || isLoadContextDescribable(config)) {
+			// entityType not modelled in MDM, try to load its
+			// ContextDescribable if it is a ContextRoot/ContextComponent
+			final EntityType testStep = modelManager.getEntityType(TestStep.class);
+			final EntityType measurement = modelManager.getEntityType(Measurement.class);
+
+			if (hasRelationTo(entityType, testStep, measurement)) {
+				return loadEntityForContextRoot(entityType, ids);
+			} else if (hasRelationTo(entityType, modelManager.getEntityType("UnitUnderTest"),
+					modelManager.getEntityType("TestSequence"), modelManager.getEntityType("TestEquipment"))) {
+				return loadEntityForContextComponent(entityType, ids);
+			} else {
+				LOGGER.debug("Cannot load entitis for entityType " + entityType + " and ids " + ids);
+				return Collections.emptyList();
+			}
+		} else {
+			return loader.loadAll(config.getKey(), ids);
+		}
+	}
+
+	/**
+	 * Loads the ContextDescribables to the given context root instances
+	 * 
+	 * @param contextRoot entityType of the context root
+	 * @param ids         IDs of the context roots.
+	 * @return the loaded ContextDescribables
+	 * @throws DataAccessException Throw if the ContextDescribables cannot be
+	 *                             loaded.
+	 */
+	private List<ContextDescribable> loadEntityForContextRoot(EntityType contextRoot, List<String> ids)
+			throws DataAccessException {
+
+		final EntityType testStep = modelManager.getEntityType(TestStep.class);
+		final EntityType measurement = modelManager.getEntityType(Measurement.class);
+
+		List<String> testStepIDs = queryService.createQuery().selectID(testStep)
+				.join(testStep.getRelation(contextRoot), JoinType.OUTER)
+				.fetch(Filter.and().add(
+						ComparisonOperator.IN_SET.create(contextRoot.getIDAttribute(), ids.toArray(new String[0]))))
+				.stream().map(r -> r.getRecord(testStep)).map(Record::getID).collect(Collectors.toList());
+
+		List<String> measurementIDs = queryService.createQuery().selectID(measurement)
+				.join(measurement.getRelation(contextRoot), JoinType.OUTER)
+				.fetch(Filter.and().add(
+						ComparisonOperator.IN_SET.create(contextRoot.getIDAttribute(), ids.toArray(new String[0]))))
+				.stream().map(r -> r.getRecord(measurement)).map(Record::getID).collect(Collectors.toList());
+
+		List<ContextDescribable> list = new ArrayList<>();
+		list.addAll(loader.loadAll(new Key<>(TestStep.class), testStepIDs));
+		list.addAll(loader.loadAll(new Key<>(Measurement.class), measurementIDs));
+
+		return list;
+	}
+
+	/**
+	 * Loads the ContextDescribables to the given context component instances
+	 * 
+	 * @param contextComponent entityType of the context component
+	 * @param ids              IDs of the contextComponents to load.
+	 * @return the loaded ContextDescribables
+	 * @throws DataAccessException Throw if the ContextDescribables cannot be
+	 *                             loaded.
+	 */
+	private List<ContextDescribable> loadEntityForContextComponent(EntityType contextComponent, List<String> ids)
+			throws DataAccessException {
+
+		// ContextComponent can only have one parent
+		final EntityType contextRoot = contextComponent.getParentRelations().get(0).getTarget();
+
+		final EntityType testStep = modelManager.getEntityType(TestStep.class);
+		final EntityType measurement = modelManager.getEntityType(Measurement.class);
+
+		List<String> testStepIDs = queryService.createQuery().selectID(testStep)
+				.join(testStep.getRelation(contextRoot), JoinType.OUTER)
+				.join(contextRoot.getRelation(contextComponent), JoinType.OUTER)
+				.fetch(Filter.and()
+						.add(ComparisonOperator.IN_SET.create(contextComponent.getIDAttribute(),
+								ids.toArray(new String[0]))))
+				.stream().map(r -> r.getRecord(testStep)).map(Record::getID).collect(Collectors.toList());
+
+		List<String> measurementIDs = queryService.createQuery().selectID(measurement)
+				.join(measurement.getRelation(contextRoot), JoinType.OUTER)
+				.join(contextRoot.getRelation(contextComponent), JoinType.OUTER)
+				.fetch(Filter.and()
+						.add(ComparisonOperator.IN_SET.create(contextComponent.getIDAttribute(),
+								ids.toArray(new String[0]))))
+				.stream().map(r -> r.getRecord(measurement)).map(Record::getID).collect(Collectors.toList());
+
+		List<ContextDescribable> list = new ArrayList<>();
+		list.addAll(loader.loadAll(new Key<>(TestStep.class), testStepIDs));
+		list.addAll(loader.loadAll(new Key<>(Measurement.class), measurementIDs));
+		return list;
+	}
+
+	/**
+	 * @param entityConfig
+	 * @return true, if the entityConfig belongs to a context root or context
+	 *         component and the option loadContextDescribable
+	 */
+	private boolean isLoadContextDescribable(EntityConfig<?> entityConfig) {
+		return loadContextDescribable && (entityConfig.getEntityClass().isAssignableFrom(ContextRoot.class)
+				|| entityConfig.getEntityClass().isAssignableFrom(ContextComponent.class));
+	}
+
+	/**
+	 * Checks if a relation between sourceEntityType and at least one entity type in
+	 * targetEntityType exists.
+	 * 
+	 * @param sourceEntityType  source entity type.
+	 * @param targetEntityTypes list of target enitity types.
+	 * @return true, if relation between source entity type and at least one target
+	 *         entity type exists.
+	 */
+	private boolean hasRelationTo(EntityType sourceEntityType, EntityType... targetEntityTypes) {
+		for (EntityType e : targetEntityTypes) {
+			try {
+				sourceEntityType.getRelation(e);
+				return true;
+			} catch (IllegalArgumentException ex) {
+				return false;
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * @param entityType entity type the {@link EntityConfig} is requested for
+	 * @return {@link EntityConfig} or null if not config was found for the
+	 *         specified entity type
+	 */
+	private EntityConfig<?> getEntityConfig(EntityType entityType) {
+		try {
+			return modelManager.getEntityConfig(entityType);
+		} catch (IllegalArgumentException e) {
+			return null;
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/ODSNotificationServiceFactory.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/ODSNotificationServiceFactory.java
new file mode 100644
index 0000000..d6a30a5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/ODSNotificationServiceFactory.java
@@ -0,0 +1,111 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification;
+
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.odsadapter.ODSContextFactory;
+import org.eclipse.mdm.api.odsadapter.notification.avalon.AvalonNotificationManager;
+import org.eclipse.mdm.api.odsadapter.notification.peak.PeakNotificationManager;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory for creating a notification service.
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class ODSNotificationServiceFactory {
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSNotificationServiceFactory.class);
+
+	public static final String PARAM_SERVER_TYPE = "freetext.notificationType";
+	public static final String PARAM_URL = "freetext.notificationUrl";
+	public static final String PARAM_POLLING_INTERVAL = "freetext.pollingInterval";
+
+	public static final String SERVER_TYPE_PEAK = "peak";
+	public static final String SERVER_TYPE_AVALON = "avalon";
+
+	public static final String PARAM_NAMESERVICE_URL = "nameserviceURL";
+
+	public NotificationService create(ApplicationContext context, Map<String, String> parameters)
+			throws ConnectionException {
+		String type = getParameter(parameters, PARAM_SERVER_TYPE);
+
+		ModelManager mm = context.getModelManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+
+		QueryService queryService = context.getQueryService()
+				.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
+
+		if (!ODSModelManager.class.isInstance(mm)) {
+			throw new ConnectionException("ModelManager is not a ODSModelManager!");
+		}
+
+		if (SERVER_TYPE_PEAK.equalsIgnoreCase(type)) {
+			String url = getParameter(parameters, PARAM_URL);
+
+			LOGGER.info("Connecting to Peak Notification Server ...");
+			LOGGER.info("URL: {}", url);
+
+			try {
+				return new PeakNotificationManager((ODSModelManager) mm, queryService, url, true);
+			} catch (NotificationException e) {
+				throw new ConnectionException("Could not connect to notification service!", e);
+			}
+		} else if (SERVER_TYPE_AVALON.equalsIgnoreCase(type)) {
+
+			String serviceName = getParameter(parameters, ODSContextFactory.PARAM_SERVICENAME);
+			serviceName = serviceName.replace(".ASAM-ODS", "");
+			String nameServiceURL = getParameter(parameters, ODSContextFactory.PARAM_NAMESERVICE);
+
+			LOGGER.info("Connecting to Avalon Notification Server ...");
+			LOGGER.info("Name service URL: {}", nameServiceURL);
+			LOGGER.info("Service name: {}", serviceName);
+
+			long pollingInterval = 500L;
+			try {
+				pollingInterval = Long.parseLong(getParameter(parameters, PARAM_POLLING_INTERVAL));
+			} catch (NumberFormatException | ConnectionException e) {
+				LOGGER.warn("Could not parse parse parameter pollingInterval. Using default value: " + pollingInterval,
+						e);
+			}
+
+			return new AvalonNotificationManager((ODSModelManager) mm, queryService, serviceName, nameServiceURL, true,
+					pollingInterval);
+		} else {
+			throw new ConnectionException("Invalid server type. Expected on of: 'peak'");
+		}
+
+	}
+
+	private String getParameter(Map<String, String> parameters, String name) throws ConnectionException {
+		String value = parameters.get(name);
+		if (value == null || value.isEmpty()) {
+			throw new ConnectionException("Connection parameter with name '" + name + "' is either missing or empty.");
+		}
+
+		return value;
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/AvalonNotificationManager.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/AvalonNotificationManager.java
new file mode 100644
index 0000000..85f51ab
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/AvalonNotificationManager.java
@@ -0,0 +1,191 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.avalon;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextDescribable;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationFilter;
+import org.eclipse.mdm.api.base.notification.NotificationFilter.ModificationType;
+import org.eclipse.mdm.api.base.notification.NotificationListener;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.notification.NotificationEntityLoader;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.omg.CORBA.ORB;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.highqsoft.avalonCorbaNotification.notification.MODE_DELETE;
+import com.highqsoft.avalonCorbaNotification.notification.MODE_INSERT;
+import com.highqsoft.avalonCorbaNotification.notification.MODE_MODIFYRIGHTS;
+import com.highqsoft.avalonCorbaNotification.notification.MODE_REPLACE;
+
+/**
+ * Notification manager for handling notifications from the Avalon Notification
+ * Service
+ * 
+ * ModificationType.MODEL_MODIFIED is not supported!
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class AvalonNotificationManager implements NotificationService {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(AvalonNotificationManager.class);
+
+	private final Map<String, EventProcessor> eventProcessors = new HashMap<>();
+
+	private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+
+	private final ODSModelManager modelManager;
+	private final String serviceName;
+	private final String nameServiceURL;
+	private long pollingInterval = 500L;
+	private final NotificationEntityLoader loader;
+
+	private final ORB orb = ORB.init(new String[] {}, System.getProperties());
+
+	/**
+	 * Creates a new AvalonNotificationManager.
+	 * 
+	 * @param modelManager           ODSModelManager used to laod entities.
+	 * @param serviceName            name of the notification service.
+	 * @param nameServiceURL         URL of the name service.
+	 * @param loadContextDescribable if true, notifications for {@link ContextRoot}
+	 *                               and {@link ContextComponent} will load their
+	 *                               parent {@link ContextDescribable}.
+	 * @param pollingInterval        polling interval in milleseconds
+	 */
+	public AvalonNotificationManager(ODSModelManager modelManager, QueryService queryService, String serviceName,
+			String nameServiceURL, boolean loadContextDescribable, long pollingInterval) {
+		this.modelManager = modelManager;
+		this.serviceName = serviceName;
+		this.nameServiceURL = nameServiceURL;
+		this.pollingInterval = pollingInterval;
+		loader = new NotificationEntityLoader(modelManager, queryService, loadContextDescribable);
+	}
+
+	@Override
+	public void register(String registration, NotificationFilter filter, final NotificationListener listener)
+			throws NotificationException {
+		try {
+			EventProcessor consumer = new EventProcessor(orb, listener, this, nameServiceURL, serviceName);
+
+			List<String> aids = filter.getEntityTypes().stream().map(e -> e.getId()).collect(Collectors.toList());
+
+			Set<ModificationType> modes = filter.getTypes().stream()
+					.filter(m -> !ModificationType.MODEL_MODIFIED.equals(m)).collect(Collectors.toSet());
+
+			consumer.connect();
+			consumer.setFilter(aids, modes);
+
+			ScheduledFuture<?> future = executor.scheduleAtFixedRate(consumer, 0, pollingInterval,
+					TimeUnit.MILLISECONDS);
+			consumer.setFuture(future);
+
+			eventProcessors.put(registration, consumer);
+		} catch (Exception e) {
+			throw new NotificationException("Exception creating notification listener registration!", e);
+		}
+	}
+
+	@Override
+	public void deregister(String registration) {
+		EventProcessor processor = eventProcessors.get(registration);
+		if (processor != null) {
+			processor.disconnect();
+			eventProcessors.remove(registration);
+		}
+	}
+
+	@Override
+	public void close(boolean isDeregisterAll) throws NotificationException {
+		LOGGER.info("Closing NotificationManager...");
+
+		for (String registration : eventProcessors.keySet()) {
+			LOGGER.debug("Disconnecting registration '" + registration + "'.");
+			deregister(registration);
+		}
+
+		try {
+			executor.shutdown();
+			boolean terminated = executor.awaitTermination(10, TimeUnit.SECONDS);
+			if (!terminated) {
+				throw new NotificationException("Could not close all registrations!");
+			}
+		} catch (InterruptedException e) {
+			throw new NotificationException("Could not close all registrations!", e);
+		}
+	}
+
+	void processException(Exception e) {
+		LOGGER.error("Exception during notification processing!", e);
+	}
+
+	void processNotification(short mode, T_LONGLONG aeId, T_LONGLONG ieId, T_LONGLONG userId, String timestamp,
+			NotificationListener notificationListener) {
+
+		try {
+			User user = loader.load(new Key<>(User.class), Long.toString(ODSConverter.fromODSLong(userId)));
+			LOGGER.debug("User loaded");
+
+			EntityType entityType = modelManager.getEntityTypeById(Long.toString(ODSConverter.fromODSLong(aeId)));
+			List<String> ids = Arrays.asList(Long.toString(ODSConverter.fromODSLong(ieId)));
+
+			if (LOGGER.isTraceEnabled()) {
+				LOGGER.trace("Notification event with: entityType=" + entityType + ", user=" + user);
+			}
+
+			switch (mode) {
+			case MODE_INSERT.value:
+				notificationListener.instanceCreated(loader.loadEntities(entityType, ids), user);
+				break;
+			case MODE_REPLACE.value:
+				notificationListener.instanceModified(loader.loadEntities(entityType, ids), user);
+				break;
+			case MODE_DELETE.value:
+				notificationListener.instanceDeleted(entityType, ids, user);
+				break;
+			case MODE_MODIFYRIGHTS.value:
+				notificationListener.securityModified(entityType, ids, user);
+				break;
+			default:
+				processException(new NotificationException("Invalid notification type!"));
+			}
+		} catch (DataAccessException e) {
+			processException(new NotificationException("Cannot load data for notification!", e));
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/EventProcessor.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/EventProcessor.java
new file mode 100644
index 0000000..78e3424
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/avalon/EventProcessor.java
@@ -0,0 +1,272 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.avalon;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ScheduledFuture;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationFilter.ModificationType;
+import org.eclipse.mdm.api.base.notification.NotificationListener;
+import org.omg.CORBA.ORB;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNotification.StructuredEvent;
+import org.omg.CosNotification._EventType;
+import org.omg.CosNotifyChannelAdmin.ClientType;
+import org.omg.CosNotifyChannelAdmin.EventChannel;
+import org.omg.CosNotifyChannelAdmin.EventChannelHelper;
+import org.omg.CosNotifyChannelAdmin.StructuredProxyPullSupplier;
+import org.omg.CosNotifyChannelAdmin.StructuredProxyPullSupplierHelper;
+import org.omg.CosNotifyComm.InvalidEventType;
+import org.omg.CosNotifyComm.StructuredPullConsumerPOA;
+import org.omg.CosNotifyFilter.ConstraintExp;
+import org.omg.CosNotifyFilter.Filter;
+import org.omg.CosNotifyFilter.FilterFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEvent;
+import com.highqsoft.avalonCorbaNotification.notification.AvalonNotificationCorbaEventHelper;
+
+/**
+ * Event processor responsible for receiving avalon events from the notification
+ * service and redirect them to the manager.
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class EventProcessor extends StructuredPullConsumerPOA implements Runnable {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(EventProcessor.class);
+
+	private static final String eventDomainName = "AVALON";
+
+	private final ORB orb;
+	private final NotificationListener listener;
+	private final AvalonNotificationManager manager;
+	private final String nameserviceUrl;
+	private final String serviceName;
+
+	private EventChannel eventChannel;
+	private StructuredProxyPullSupplier proxyPullSupplier;
+
+	private boolean connected = false;
+
+	private ScheduledFuture<?> future;
+
+	/**
+	 * Creates a new event processor.
+	 * 
+	 * @param orb         CORBA orb to use
+	 * @param listener    notification listener consuming the received events
+	 * @param manager     notification manager responsible for processing the events
+	 * @param serviceName service name of the CORBA notification service
+	 */
+	public EventProcessor(ORB orb, NotificationListener listener, AvalonNotificationManager manager,
+			String nameserviceUrl, String serviceName) {
+		this.orb = orb;
+		this.nameserviceUrl = nameserviceUrl;
+		this.listener = listener;
+		this.manager = manager;
+		this.serviceName = String.format("com/highqsoft/avalon/notification/%s.Notification", serviceName);
+	}
+
+	/**
+	 * Connect the event processor to the notification service.
+	 * 
+	 * @throws NotificationException in case the notification service cannot be
+	 *                               connected.
+	 */
+	public synchronized void connect() throws NotificationException {
+		if (isConnected()) {
+			return;
+		}
+
+		try {
+			NamingContextExt nc = NamingContextExtHelper.narrow(orb.string_to_object(nameserviceUrl));
+
+			eventChannel = EventChannelHelper.narrow(nc.resolve(nc.to_name(serviceName)));
+
+			proxyPullSupplier = StructuredProxyPullSupplierHelper.narrow(eventChannel.default_consumer_admin()
+					.obtain_notification_pull_supplier(ClientType.STRUCTURED_EVENT, new org.omg.CORBA.IntHolder()));
+
+			proxyPullSupplier.connect_structured_pull_consumer(this._this(orb));
+			connected = true;
+		} catch (Exception e) {
+			throw new NotificationException("Cannot connect to notification service!", e);
+		}
+	}
+
+	/**
+	 * Disconnect the event processor from the notification service.
+	 */
+	public synchronized void disconnect() {
+		if (isConnected()) {
+			if (future != null) {
+				future.cancel(false);
+			}
+
+			proxyPullSupplier = null;
+
+			eventChannel._release();
+			eventChannel = null;
+
+			connected = false;
+		}
+	}
+
+	/**
+	 * @return true if the event processor is connected to the notification service
+	 */
+	public synchronized boolean isConnected() {
+		return connected;
+	}
+
+	/**
+	 * Sets the event filter.
+	 * 
+	 * @param aids              List with application element IDs to filter for.
+	 *                          Empty list means no all.
+	 * @param modificationTypes Collection of modification types to filter for.
+	 * @throws NotificationException if the filter cannot be set
+	 */
+	public void setFilter(List<String> aids, Set<ModificationType> modificationTypes) throws NotificationException {
+		if (!isConnected()) {
+			throw new IllegalStateException("Cannot set filter when disconnected. Please connect first.");
+		}
+
+		try {
+			FilterFactory filterFactory = eventChannel.default_filter_factory();
+			if (filterFactory == null) {
+				throw new NotificationException("No default filter factory found!");
+			}
+
+			Filter filter = filterFactory.create_filter("EXTENDED_TCL");
+			filter.add_constraints(new ConstraintExp[] {
+					new ConstraintExp(getEventTypes(modificationTypes), getConstraintFilter(aids)) });
+			proxyPullSupplier.add_filter(filter);
+		} catch (Exception e) {
+			throw new NotificationException("Exception when creating filter.", e);
+		}
+	}
+
+	/**
+	 * Sets the ScheduledFuture that will be used to stop the event processor task.
+	 * 
+	 * @param future ScheduledFuture
+	 */
+	public void setFuture(ScheduledFuture<?> future) {
+		this.future = future;
+	}
+
+	@Override
+	public synchronized void run() {
+		if (isConnected()) {
+			org.omg.CORBA.BooleanHolder bh = new org.omg.CORBA.BooleanHolder();
+
+			try {
+				LOGGER.trace("Looking for structured events....");
+				// try to pull an event
+				StructuredEvent event = proxyPullSupplier.try_pull_structured_event(bh);
+				if (bh.value) {
+					AvalonNotificationCorbaEvent ev = AvalonNotificationCorbaEventHelper
+							.extract(event.remainder_of_body);
+					manager.processNotification(ev.mode, ev.aeId, ev.ieId, ev.userId, ev.timestamp, listener);
+				} else {
+					LOGGER.trace("No structured events found.");
+				}
+			} catch (Exception e) {
+				manager.processException(e);
+			}
+		} else {
+			LOGGER.warn("Disconnected.");
+			manager.processException(new NotificationException("Not connected"));
+			if (future != null) {
+				future.cancel(false);
+			}
+		}
+	}
+
+	@Override
+	public void disconnect_structured_pull_consumer() {
+		LOGGER.info("Disconnected!");
+		connected = false;
+	}
+
+	@Override
+	public void offer_change(_EventType[] added, _EventType[] removed) throws InvalidEventType {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * Constructs a constraint filter.
+	 * 
+	 * @param aids Application Element IDs used for filtering. Empty list means no
+	 *             filter.
+	 * @return Constraint filter containing the given aids
+	 */
+	private String getConstraintFilter(List<String> aids) {
+		if (aids.isEmpty()) {
+			return "TRUE";
+		} else {
+			return aids.stream().map(aid -> String.format("$.filterable_data(%s) == %s", "ApplicationElement", aid))
+					.collect(Collectors.joining(" or "));
+		}
+	}
+
+	/**
+	 * Converts ModificationTypes in EventTypes.
+	 * 
+	 * @param modificationTypes
+	 * @return Array with EventTypes
+	 */
+	private _EventType[] getEventTypes(Set<ModificationType> modificationTypes) {
+		if (modificationTypes.isEmpty()) {
+			return new _EventType[0];
+		} else {
+			return modificationTypes.stream().map(s -> new _EventType(eventDomainName, toAvalonString(s)))
+					.collect(Collectors.toList()).toArray(new _EventType[0]);
+		}
+	}
+
+	/**
+	 * Converts a {@link ModificationType} enum value to a event type name for the
+	 * CORBA notification service.
+	 * 
+	 * @param t a modification type
+	 * @return event type name
+	 */
+	private String toAvalonString(ModificationType t) {
+		switch (t) {
+		case INSTANCE_CREATED:
+			return "INSERT";
+		case INSTANCE_MODIFIED:
+			return "REPLACE";
+		case INSTANCE_DELETED:
+			return "DELETE";
+		case SECURITY_MODIFIED:
+			return "MODIFYRIGHTS";
+		case MODEL_MODIFIED:
+			throw new IllegalArgumentException(t.name() + " not supported!");
+		default:
+			throw new IllegalArgumentException("Invalid enum value!");
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java
new file mode 100644
index 0000000..312cf2b
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java
@@ -0,0 +1,103 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.peak;
+
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationListener;
+import org.glassfish.jersey.media.sse.EventInput;
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.peaksolution.ods.notification.protobuf.NotificationProtos.Notification;
+
+/**
+ * Event processor responsible for receiving notification events from the
+ * notification server and redirect them to the manager.
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class EventProcessor implements Runnable {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(EventProcessor.class);
+
+	private EventInput eventInput;
+	private NotificationListener listener;
+	private PeakNotificationManager odsNotificationManager;
+	private MediaType eventMediaType;
+	private boolean closeInvoked = false;
+	private boolean disconnected = false;
+
+	public EventProcessor(EventInput eventInput, NotificationListener listener,
+			PeakNotificationManager odsNotificationManager, MediaType eventMediaType) {
+		this.eventInput = eventInput;
+		this.listener = listener;
+		this.odsNotificationManager = odsNotificationManager;
+		this.eventMediaType = eventMediaType;
+	}
+
+	@Override
+	public void run() {
+
+		while (!eventInput.isClosed()) {
+
+			final InboundEvent inboundEvent = eventInput.read();
+
+			if (inboundEvent == null) {
+				if (!closeInvoked) {
+					odsNotificationManager
+							.processException(new NotificationException("Inbound event input stream closed!"));
+				}
+				disconnected = true;
+				return;
+			}
+
+			try {
+				if (LOGGER.isDebugEnabled()) {
+					LOGGER.trace("Received event: " + inboundEvent);
+				}
+				Notification n = inboundEvent.readData(Notification.class, eventMediaType);
+				odsNotificationManager.processNotification(n, getListener());
+			} catch (ProcessingException e) {
+				odsNotificationManager
+						.processException(new NotificationException("Cannot deserialize notification event!", e));
+				disconnected = true;
+				return;
+			}
+		}
+
+		disconnected = true;
+	}
+
+	public boolean isDisconnected() {
+		return disconnected;
+	}
+
+	public void stop() {
+		closeInvoked = true;
+		// EventInput is closed by the server side after invoking DELETE
+		// /events/{registrationName}. Otherwise we run into a deadlock with
+		// eventInput#read()
+	}
+
+	public NotificationListener getListener() {
+		return listener;
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/JsonMessageBodyProvider.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/JsonMessageBodyProvider.java
new file mode 100644
index 0000000..c29405c
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/JsonMessageBodyProvider.java
@@ -0,0 +1,96 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.peak;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import com.google.common.base.Charsets;
+import com.google.protobuf.GeneratedMessageV3;
+import com.google.protobuf.Message;
+import com.google.protobuf.util.JsonFormat;
+import com.google.protobuf.util.JsonFormat.Parser;
+import com.google.protobuf.util.JsonFormat.Printer;
+
+/**
+ * MessageBodyProvider for handling json payloads.
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+@Provider
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public class JsonMessageBodyProvider implements MessageBodyReader<Message>, MessageBodyWriter<Message> {
+
+	private static final Charset charset = Charsets.UTF_8;
+	private Printer jsonPrinter = JsonFormat.printer();
+	private Parser jsonParser = JsonFormat.parser();
+
+	@Override
+	public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+			final MediaType mediaType) {
+		return Message.class.isAssignableFrom(type);
+	}
+
+	@Override
+	public Message readFrom(final Class<Message> type, final Type genericType, final Annotation[] annotations,
+			final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
+			throws IOException {
+		try {
+			final Method newBuilder = type.getMethod("newBuilder");
+			final GeneratedMessageV3.Builder<?> builder = (GeneratedMessageV3.Builder<?>) newBuilder.invoke(type);
+			jsonParser.merge(new InputStreamReader(entityStream, charset), builder);
+			return builder.build();
+		} catch (Exception e) {
+			throw new WebApplicationException(e);
+		}
+	}
+
+	@Override
+	public long getSize(final Message m, final Class<?> type, final Type genericType, final Annotation[] annotations,
+			final MediaType mediaType) {
+		return -1;
+	}
+
+	@Override
+	public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+			final MediaType mediaType) {
+		return Message.class.isAssignableFrom(type);
+	}
+
+	@Override
+	public void writeTo(final Message m, final Class<?> type, final Type genericType, final Annotation[] annotations,
+			final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders,
+			final OutputStream entityStream) throws IOException {
+		entityStream.write(jsonPrinter.print(m).getBytes(charset));
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java
new file mode 100644
index 0000000..72d1e45
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java
@@ -0,0 +1,277 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.peak;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationFilter;
+import org.eclipse.mdm.api.base.notification.NotificationListener;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.notification.NotificationEntityLoader;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.glassfish.jersey.media.sse.EventInput;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.peaksolution.ods.notification.protobuf.NotificationProtos.Notification;
+
+/**
+ * Notification manager for handling notifications from the Peak ODS Server
+ * Notification Plugin
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class PeakNotificationManager implements NotificationService {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(PeakNotificationManager.class);
+
+	private final Client client;
+	private final WebTarget endpoint;
+
+	private final Map<String, EventProcessor> processors = new HashMap<>();
+
+	private final ExecutorService executor = Executors.newCachedThreadPool();
+
+	private final ODSModelManager modelManager;
+
+	private final NotificationEntityLoader loader;
+
+	/**
+	 * @param modelManager
+	 * @param url                    URL of the notification plugin
+	 * @param loadContextDescribable if true, the corresponding context describable
+	 *                               is loaded if a notification for a context root
+	 *                               or context component is received.
+	 * @throws NotificationException Thrown if the manager cannot connect to the
+	 *                               notification server.
+	 */
+	public PeakNotificationManager(ODSModelManager modelManager, QueryService queryService, String url,
+			boolean loadContextDescribable) throws NotificationException {
+		this.modelManager = modelManager;
+		loader = new NotificationEntityLoader(modelManager, queryService, loadContextDescribable);
+
+		try {
+			client = ClientBuilder.newBuilder().register(SseFeature.class).register(JsonMessageBodyProvider.class)
+					.build();
+
+			endpoint = client.target(url).path("events");
+
+			Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> reconnect(), 10, 10, TimeUnit.SECONDS);
+		} catch (Exception e) {
+			throw new NotificationException("Could not create " + PeakNotificationManager.class.getName() + "!", e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.mdm.api.base.notification.NotificationManager#register(java.
+	 * lang.String, org.eclipse.mdm.api.base.notification.NotificationFilter,
+	 * org.eclipse.mdm.api.base.notification.NotificationListener)
+	 */
+	@Override
+	public void register(String registration, NotificationFilter filter, NotificationListener listener)
+			throws NotificationException {
+		LOGGER.info("Starting registration for with name: {}", registration);
+
+		Response response = endpoint.path(registration).request().post(
+				javax.ws.rs.client.Entity.entity(ProtobufConverter.from(filter), MediaType.APPLICATION_JSON_TYPE));
+
+		if (response.getStatusInfo().getStatusCode() == Status.CONFLICT.getStatusCode()) {
+			if (LOGGER.isInfoEnabled()) {
+				LOGGER.info("A registration with the name already exists: {}", response.readEntity(String.class));
+				LOGGER.info("Trying to reregister...");
+			}
+			deregister(registration);
+			LOGGER.info("Deregisteration successful.");
+			register(registration, filter, listener);
+			return;
+		}
+
+		if (response.getStatusInfo().getStatusCode() != Status.OK.getStatusCode()) {
+			throw new NotificationException(
+					"Could not create registration at notification service: " + response.readEntity(String.class));
+		}
+
+		recreateEventStream(registration, listener);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.mdm.api.base.notification.NotificationManager#deregister(java
+	 * .lang.String)
+	 */
+	@Override
+	public void deregister(String registration) {
+		if (processors.containsKey(registration)) {
+			close(registration);
+		}
+
+		endpoint.path(registration).request().delete();
+	}
+
+	@Override
+	public void close(boolean isDeregisterAll) throws NotificationException {
+		LOGGER.info("Closing NotificationManager...");
+
+		for (String registration : processors.keySet()) {
+			if (isDeregisterAll) {
+				LOGGER.debug("Deregistering '{}'.", registration);
+				deregister(registration);
+			} else {
+				LOGGER.debug("Disconnecting '{}'.", registration);
+				close(registration);
+			}
+		}
+	}
+
+	/**
+	 * Recreates the {@link EventInput}, attaches an {@link EventProcessor} to it
+	 * and stores the {@link EventProcessor} in the processors map.
+	 * 
+	 * @param registration
+	 * @param listener
+	 * @throws NotificationException
+	 */
+	private void recreateEventStream(String registration, NotificationListener listener) throws NotificationException {
+		try {
+			LOGGER.info("Requesting event input for {}", registration);
+			EventInput eventInput = endpoint.path(registration).request(SseFeature.SERVER_SENT_EVENTS_TYPE)
+					.get(EventInput.class);
+
+			LOGGER.info("Received event input, starting event processor.");
+			EventProcessor processor = new EventProcessor(eventInput, listener, this, MediaType.APPLICATION_JSON_TYPE);
+
+			executor.submit(processor);
+
+			processors.put(registration, processor);
+			LOGGER.info("Event processor started.");
+		} catch (Exception e) {
+			try {
+				deregister(registration);
+			} catch (Exception ex) {
+				LOGGER.error("Exception upon deregistering!");
+			}
+			throw new NotificationException("Could not create event input stream!", e);
+		}
+	}
+
+	/**
+	 * Checks if any registered event processor got disconnected and tries to
+	 * recreate the event stream, if necessary.
+	 */
+	private void reconnect() {
+
+		for (Map.Entry<String, EventProcessor> entry : processors.entrySet()) {
+			if (entry.getValue().isDisconnected()) {
+				try {
+					LOGGER.trace("Registration '{}' was disconnected and will be recreated.", entry.getKey());
+					recreateEventStream(entry.getKey(), entry.getValue().getListener());
+				} catch (NotificationException e) {
+					LOGGER.warn("Cannot recreate event stream for registration " + entry.getKey(), e);
+				}
+			}
+		}
+	}
+
+	private void close(String registration) {
+		if (processors.containsKey(registration)) {
+			EventProcessor processor = processors.get(registration);
+			processor.stop();
+			processors.remove(registration);
+		}
+	}
+
+	/**
+	 * Handler for Exceptions during event processing.
+	 * 
+	 * @param e Exception which occured during event processing.
+	 */
+	void processException(Exception e) {
+		LOGGER.error("Exception during notification processing!", e);
+	}
+
+	/**
+	 * Handler for notifications.
+	 * 
+	 * @param n                    notification to process.
+	 * @param notificationListener notification listener for handling the
+	 *                             notification.
+	 */
+	void processNotification(Notification n, NotificationListener notificationListener) {
+		if (LOGGER.isDebugEnabled()) {
+			LOGGER.debug("Processing notification event: " + n);
+		}
+
+		try {
+			User user = loader.load(new Key<>(User.class), Long.toString(n.getUserId()));
+
+			EntityType entityType = modelManager.getEntityTypeById(Long.toString(n.getAid()));
+
+			if (LOGGER.isTraceEnabled()) {
+				LOGGER.trace("Notification event with: entityType=" + entityType + ", user=" + user);
+			}
+			switch (n.getType()) {
+			case NEW:
+				notificationListener.instanceCreated(loader.loadEntities(entityType, n.getIidList().stream()
+						.map(id -> id.toString()).filter(ODSUtils::isValidID).collect(Collectors.toList())), user);
+				break;
+			case MODIFY:
+				notificationListener.instanceModified(loader.loadEntities(entityType, n.getIidList().stream()
+						.map(id -> id.toString()).filter(ODSUtils::isValidID).collect(Collectors.toList())), user);
+				break;
+			case DELETE:
+				notificationListener.instanceDeleted(entityType, n.getIidList().stream().map(id -> id.toString())
+						.filter(ODSUtils::isValidID).collect(Collectors.toList()), user);
+				break;
+			case MODEL:
+				notificationListener.modelModified(entityType, user);
+				break;
+			case SECURITY:
+				notificationListener.securityModified(entityType, n.getIidList().stream().map(id -> id.toString())
+						.filter(ODSUtils::isValidID).collect(Collectors.toList()), user);
+				break;
+			default:
+				processException(new NotificationException("Invalid notification type!"));
+			}
+		} catch (Exception e) {
+			processException(new NotificationException("Could not process notification!", e));
+		}
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/ProtobufConverter.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/ProtobufConverter.java
new file mode 100644
index 0000000..509a6a8
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/ProtobufConverter.java
@@ -0,0 +1,91 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.peak;
+
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.notification.NotificationFilter;
+import org.eclipse.mdm.api.base.notification.NotificationFilter.ModificationType;
+
+import com.peaksolution.ods.notification.protobuf.NotificationProtos.Registration;
+import com.peaksolution.ods.notification.protobuf.NotificationProtos.Registration.NotificationMode;
+
+/**
+ * Helper class for converting between protobuf and mdm types.
+ * 
+ * @since 1.0.0
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+public class ProtobufConverter {
+
+	/**
+	 * Convert a notification filter to a registration.
+	 * 
+	 * @param filter notification filter.
+	 * @return registration corresponding to the given filter.
+	 */
+	public static Registration from(NotificationFilter filter) {
+		return Registration.newBuilder().setMode(NotificationMode.PUSH)
+				.addAllAid(
+						filter.getEntityTypes().stream().map(e -> Long.valueOf(e.getId())).collect(Collectors.toList()))
+				.addAllType(filter.getTypes().stream().map(t -> ProtobufConverter.from(t)).collect(Collectors.toList()))
+				.build();
+	}
+
+	/**
+	 * @param t mdm modification type.
+	 * @return protobuf notification type.
+	 */
+	public static com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType from(
+			ModificationType t) {
+		switch (t) {
+		case INSTANCE_CREATED:
+			return com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType.NEW;
+		case INSTANCE_MODIFIED:
+			return com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType.MODIFY;
+		case INSTANCE_DELETED:
+			return com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType.DELETE;
+		case MODEL_MODIFIED:
+			return com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType.MODEL;
+		case SECURITY_MODIFIED:
+			return com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType.SECURITY;
+		default:
+			throw new IllegalArgumentException("Invalid enum value!"); // TODO
+		}
+	}
+
+	/**
+	 * @param t protobuf notification type
+	 * @return mdm notification type
+	 */
+	public static ModificationType to(
+			com.peaksolution.ods.notification.protobuf.NotificationProtos.ModificationType t) {
+		switch (t) {
+		case NEW:
+			return ModificationType.INSTANCE_CREATED;
+		case MODIFY:
+			return ModificationType.INSTANCE_MODIFIED;
+		case DELETE:
+			return ModificationType.INSTANCE_DELETED;
+		case MODEL:
+			return ModificationType.MODEL_MODIFIED;
+		case SECURITY:
+			return ModificationType.SECURITY_MODIFIED;
+		default:
+			throw new IllegalArgumentException("Invalid enum value!"); // TODO
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSAttribute.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSAttribute.java
new file mode 100644
index 0000000..abe4edf
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSAttribute.java
@@ -0,0 +1,201 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import java.util.Objects;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+
+import org.asam.ods.ApplAttr;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+
+/**
+ * ODS implementation of the {@link Attribute} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class ODSAttribute implements Attribute {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Enumeration<?> enumObj;
+	private final String name;
+	private final String unit;
+	private final EntityType entityType;
+	private final ValueType<?> valueType;
+	private final boolean isIdAttribute;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param entityType The parent {@link EntityType}.
+	 * @param applAttr   The ODS meta data for this attribute.
+	 * @param unit       The unit name.
+	 * @param enumObj    The enumeration class, may be null.
+	 */
+	ODSAttribute(EntityType entityType, ApplAttr applAttr, String unit, Enumeration<?> enumObj) {
+		this.entityType = entityType;
+		name = applAttr.aaName;
+		this.unit = unit == null ? "" : unit;
+
+		if (isIDAttribute(entityType, applAttr)) {
+			valueType = ValueType.STRING;
+			isIdAttribute = true;
+		} else {
+			valueType = ODSUtils.VALUETYPES.inverse().get(applAttr.dType);
+			isIdAttribute = false;
+		}
+
+		if (valueType.isEnumerationType() && enumObj == null) {
+			throw new IllegalStateException(
+					"A modeled attribute with an enumeration value type must have an " + "enumeration definition.");
+		}
+
+		this.enumObj = enumObj;
+	}
+
+	private boolean isIDAttribute(EntityType entityType, ApplAttr applAttr) {
+		for (Relation r : entityType.getRelations()) {
+			if (applAttr.aaName.equalsIgnoreCase(r.getName())) {
+				return true;
+			}
+		}
+		return "id".equalsIgnoreCase(applAttr.baName);
+	}
+
+	public boolean isIdAttribute() {
+		return isIdAttribute;
+	}
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getUnit() {
+		return unit;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getEntityType() {
+		return entityType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public ValueType<?> getValueType() {
+		return valueType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Enumeration<?> getEnumObj() {
+		if (getValueType().isEnumerationType()) {
+			return enumObj;
+		}
+
+		throw new IllegalStateException("The value type of this attribute is not an enumeration type.");
+	}
+
+	@Override
+	public Value createValue(String unit, boolean valid, Object input) {
+		return Attribute.super.createValue(unit, valid, convertInputForIdAttribute(input));
+	}
+
+	@Override
+	public Value createValueSeq(String unit, Object input) {
+		return Attribute.super.createValueSeq(unit, convertInputForIdAttribute(input));
+	}
+
+	/**
+	 * Converts the input object from long/long-array/int/int-array to a
+	 * String/String-array
+	 * 
+	 * @param input The input to convert
+	 * @return The converted input
+	 */
+	private Object convertInputForIdAttribute(Object input) {
+		if (isIdAttribute) {
+			if (input instanceof Long || input instanceof Integer) {
+				return input.toString();
+			} else if (input instanceof long[]) {
+				return LongStream.of((long[]) input).mapToObj(Long::toString).toArray(String[]::new);
+			} else if (input instanceof int[]) {
+				return IntStream.of((int[]) input).mapToObj(Integer::toString).toArray(String[]::new);
+			}
+		}
+
+		return input;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return Objects.hash(getEntityType(), getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object object) {
+		if (object instanceof ODSAttribute) {
+			Attribute attribute = (Attribute) object;
+			return getEntityType().equals(attribute.getEntityType()) && getName().equals(attribute.getName());
+		}
+
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java
new file mode 100644
index 0000000..41abfc2
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityFactory.java
@@ -0,0 +1,259 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_ENUMERATION_NAME;
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SCALAR_TYPE;
+import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SEQUENCE;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.mdm.api.base.adapter.ChildrenStore;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.DefaultCore;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
+import org.eclipse.mdm.api.base.model.AxisType;
+import org.eclipse.mdm.api.base.model.BaseEntity;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.EnumRegistry;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.base.model.EnumerationValue;
+import org.eclipse.mdm.api.base.model.Interpolation;
+import org.eclipse.mdm.api.base.model.ScalarType;
+import org.eclipse.mdm.api.base.model.SequenceRepresentation;
+import org.eclipse.mdm.api.base.model.TypeSpecification;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.model.VersionState;
+import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
+import org.eclipse.mdm.api.dflt.model.EntityFactory;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+
+/**
+ * ODS implementation of the {@link EntityFactory}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSEntityFactory extends EntityFactory {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Set<Class<? extends EnumerationValue>> ENUM_CLASSES = new HashSet<>();
+
+	static {
+		ENUM_CLASSES.add(ScalarType.class);
+		ENUM_CLASSES.add(VersionState.class);
+		ENUM_CLASSES.add(Interpolation.class);
+		ENUM_CLASSES.add(AxisType.class);
+		ENUM_CLASSES.add(SequenceRepresentation.class);
+		ENUM_CLASSES.add(TypeSpecification.class);
+	}
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ODSModelManager modelManager;
+	private final Optional<User> loggedInUser;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to create {@link Core}s.
+	 * @param loggedInUser The logged in {@link User}.
+	 */
+	public ODSEntityFactory(ODSModelManager modelManager, Optional<User> loggedInUser) {
+		this.modelManager = modelManager;
+		this.loggedInUser = loggedInUser;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Extracts the {@link Core} from an {@link Entity} instance. This method
+	 * effectively makes access to the Core of a BaseEntity publicly available (by
+	 * calling the corresponding protected method of BaseEntityFactory, which is
+	 * this class's superclass) to users of ODSEntityFactory.
+	 * 
+	 * @param entity The {@link Entity} from which to extract the {@link Core}.
+	 * @return The entity's {@link Core}.
+	 */
+	public static Core extract(Entity entity) {
+		if (entity instanceof BaseEntity) {
+			return getCore((BaseEntity) entity);
+		} else {
+			throw new IllegalArgumentException("Entity of type '" + entity.getClass().getSimpleName()
+					+ "' does not extend '" + BaseEntity.class.getName() + "'");
+		}
+	}
+
+	/**
+	 * Create an instance of a class implementing the {@link Entity} interface with
+	 * core as the instance's {@link Core}. This method effectively makes the
+	 * protected BaseEntity constructor publicly available (by calling the
+	 * corresponding protected method of BaseEntityFactory, which is this class's
+	 * superclass) to users of ODSEntityFactory.
+	 * 
+	 * @param clazz The class to instantiate, must implement the {@link Entity}
+	 *              interface.
+	 * @param core  The {@link Core} to use for the newly created instance.
+	 * @return The newly created instance.
+	 */
+	@SuppressWarnings("unchecked")
+	public <T extends Entity> T createEntity(Class<T> clazz, Core core) {
+		if (BaseEntity.class.isAssignableFrom(clazz)) {
+			return (T) createBaseEntity(clazz.asSubclass(BaseEntity.class), core);
+		} else {
+			throw new IllegalArgumentException(
+					"Class '" + clazz.getSimpleName() + "' does not extend '" + BaseEntity.class.getName() + "'");
+		}
+
+	}
+
+	// ======================================================================
+	// Protected methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected Optional<User> getLoggedInUser() {
+		return loggedInUser;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected <T extends Entity> Core createCore(Class<T> entityClass) {
+		return createCore(new Key<>(entityClass));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected <T extends Entity> Core createCore(Class<T> entityClass, ContextType contextType) {
+		return createCore(new Key<>(entityClass, contextType));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public static final EntityStore getMutableStore(BaseEntity entity) {
+		return EntityFactory.getMutableStore(entity);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public static final EntityStore getPermanentStore(BaseEntity entity) {
+		return EntityFactory.getPermanentStore(entity);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public static final ChildrenStore getChildrenStore(BaseEntity entity) {
+		return EntityFactory.getChildrenStore(entity);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected <T extends Entity> Core createCore(String name, Class<T> entityClass) {
+		EntityConfig<?> entityConfig = modelManager.getEntityConfig(modelManager.getEntityType(name));
+		if (!entityClass.equals(entityConfig.getEntityClass())) {
+			throw new IllegalArgumentException("Incompatible entity class expected '" + entityClass.getName()
+					+ "' but got '" + entityConfig.getEntityClass().getName() + "'");
+		}
+		Core core = new DefaultCore(entityConfig.getEntityType());
+		core.getValues().get(Entity.ATTR_MIMETYPE).set(entityConfig.getMimeType());
+
+		return core;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected void validateEnum(Enumeration<?> enumerationObj) {
+		EnumRegistry er = EnumRegistry.getInstance();
+		// check if enum is properly registered
+		if (er.get(enumerationObj.getName()) == null) {
+			throw new IllegalArgumentException("Given enum class '" + enumerationObj.getName() + "' is not supported.");
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected <T extends BaseEntity> T createBaseEntity(Class<T> clazz, Core core) {
+		try {
+			Constructor<T> constructor = clazz.getDeclaredConstructor(Core.class);
+			try {
+				return constructor.newInstance(core);
+			} catch (IllegalAccessException exc) {
+				return super.createBaseEntity(clazz, core);
+			}
+		} catch (NoSuchMethodException | InvocationTargetException | InstantiationException exc) {
+			throw new IllegalStateException(exc.getMessage(), exc);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Creates a configured {@link Core} for given {@link Key}.
+	 *
+	 * @param <T> The entity type.
+	 * @param key Used as identifier to resolve the {@link EntityConfig}.
+	 * @return The created {@code Core} is returned.
+	 */
+	private <T extends Entity> Core createCore(Key<T> key) {
+		EntityConfig<T> entityConfig = modelManager.findEntityConfig(key);
+		Core core = new DefaultCore(entityConfig.getEntityType());
+		core.getValues().get(Entity.ATTR_MIMETYPE).set(entityConfig.getMimeType());
+
+		if (CatalogAttribute.class.equals(entityConfig.getEntityClass())) {
+			core.getValues().put(VATTR_ENUMERATION_NAME, ValueType.STRING.create(VATTR_ENUMERATION_NAME));
+			core.getValues().put(VATTR_SCALAR_TYPE,
+					ValueType.ENUMERATION.create(EnumRegistry.getInstance().get("ScalarType"), VATTR_SCALAR_TYPE));
+			core.getValues().put(VATTR_SEQUENCE, ValueType.BOOLEAN.create(VATTR_SEQUENCE));
+		}
+
+		return core;
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityType.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityType.java
new file mode 100644
index 0000000..dee3a4c
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSEntityType.java
@@ -0,0 +1,320 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.toMap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.asam.ods.ApplElem;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.adapter.RelationType;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+
+/**
+ * ODS implementation of the {@link EntityType} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSEntityType implements EntityType {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<EntityType, Map<String, Relation>> relationsByEntityName = new HashMap<>();
+	private final Map<EntityType, Relation> relationsByEntity = new HashMap<>();
+
+	private final Map<RelationType, List<Relation>> relationsByType = new EnumMap<>(RelationType.class);
+	private final List<Relation> relations = new ArrayList<>();
+
+	private final Map<String, Attribute> attributeByName;
+
+	private final String sourceName;
+	private final T_LONGLONG odsID;
+	private final String baseName;
+	private final String name;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param sourceName  Name of the data source.
+	 * @param applElem    The ODS meta data for this entity type.
+	 * @param units       The unit {@code Map} for unit mapping of attributes.
+	 * @param enumClasses The enumeration class {@code Map} for enum mapping of
+	 *                    attributes.
+	 */
+
+	ODSEntityType(String sourceName, ApplElem applElem, Map<String, String> units,
+			Map<String, Enumeration<?>> enumObjs) {
+		this.sourceName = sourceName;
+		baseName = applElem.beName;
+		name = applElem.aeName;
+		odsID = applElem.aid;
+
+		attributeByName = Arrays
+				.stream(applElem.attributes).map(a -> new ODSAttribute(this, a,
+						units.get(Long.toString(ODSConverter.fromODSLong(a.unitId))), enumObjs.get(a.aaName)))
+				.collect(toMap(Attribute::getName, Function.identity()));
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getSourceName() {
+		return sourceName;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Returns the ODS base name this entity type is derived from.
+	 *
+	 * @return The base name is returned.
+	 */
+	public String getBaseName() {
+		return baseName;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Attribute> getAttributes() {
+		return new ArrayList<>(attributeByName.values());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Attribute getAttribute(String name) {
+		Attribute attribute = attributeByName.get(name);
+		if (attribute == null) {
+			Optional<Relation> relation = getRelations().stream().filter(r -> r.getName().equals(name)).findAny();
+			return relation.map(Relation::getAttribute).orElseThrow(() -> new IllegalArgumentException(
+					"Attribute with name '" + name + "' not found at entity type '" + getName() + "'."));
+		}
+		return attribute;
+	}
+
+	/**
+	 * Returns the ODS type ID of this entity type.
+	 *
+	 * @return The ODS type ID is returned.
+	 */
+	public T_LONGLONG getODSID() {
+		return odsID;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getId() {
+		return Long.toString(ODSConverter.fromODSLong(odsID));
+	}
+
+	@Override
+	public List<Relation> getRelations() {
+		return Collections.unmodifiableList(relations);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Relation> getParentRelations() {
+		return getRelations(RelationType.FATHER_CHILD).stream()
+				.filter(r -> ((ODSRelation) r).isOutgoing(RelationType.FATHER_CHILD)).collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Relation> getChildRelations() {
+		return getRelations(RelationType.FATHER_CHILD).stream()
+				.filter(r -> ((ODSRelation) r).isIncoming(RelationType.FATHER_CHILD)).collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Relation> getInfoRelations() {
+		return getRelations(RelationType.INFO).stream().filter(r -> ((ODSRelation) r).isOutgoing(RelationType.INFO))
+				.collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Relation> getRelations(RelationType relationType) {
+		List<Relation> result = relationsByType.get(relationType);
+		return result == null ? Collections.emptyList() : Collections.unmodifiableList(result);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Relation getRelation(EntityType target) {
+		Relation relation = relationsByEntity.get(target);
+		if (relation == null) {
+			// multiple relations to target exist, try to use a default
+			Map<String, Relation> relationsByName = relationsByEntityName.get(target);
+			if (relationsByName == null) {
+				throw new IllegalArgumentException("Relations to '" + target + "' not found!");
+			}
+
+			relation = relationsByName.get(target.getName());
+		}
+		return relation == null ? getParentRelation(target) : relation;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Relation getRelation(EntityType target, String name) {
+		Map<String, Relation> relationsByName = relationsByEntityName.get(target);
+		if (relationsByName == null) {
+			throw new IllegalArgumentException("Relations to '" + target + "' not found!");
+		}
+
+		Relation relation = relationsByName.get(name);
+		if (relation == null) {
+			throw new IllegalArgumentException("Relation to '" + target + "' with name '" + name + "' not found!");
+		}
+		return relation;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return getName().hashCode();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object object) {
+		if (object instanceof ODSEntityType) {
+			return getName().equals(((EntityType) object).getName());
+		}
+
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+	// ======================================================================
+	// Package methods
+	// ======================================================================
+
+	/**
+	 * Adds given {@link Relation}s.
+	 *
+	 * @param relations {@code Relation}s which will be added.
+	 */
+	void setRelations(List<Relation> relations) {
+		Map<EntityType, List<Relation>> entityRelationsByTarget = relations.stream().distinct()
+				.filter(r -> equals(r.getSource())).collect(groupingBy(Relation::getTarget));
+
+		for (Entry<EntityType, List<Relation>> entry : entityRelationsByTarget.entrySet()) {
+			List<Relation> entityTypeRelations = entry.getValue();
+			EntityType target = entry.getKey();
+
+			entityTypeRelations.forEach(this::addRelation);
+
+			if (entityTypeRelations.size() > 1) {
+				relationsByEntityName.put(target,
+						entityTypeRelations.stream().collect(toMap(Relation::getName, identity())));
+			} else {
+				relationsByEntity.put(target, entityTypeRelations.get(0));
+			}
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Tries to find a parent {@link Relation} to given target {@link EntityType}.
+	 *
+	 * @param target The target {@code EntityType}.
+	 * @return The requested parent {@code Relation} is returned.
+	 * @throws IllegalArgumentException Thrown if no such {@code Relation} exists.
+	 */
+	private Relation getParentRelation(EntityType target) {
+		return getParentRelations().stream().filter(et -> et.getTarget().equals(target)).findAny().orElseThrow(
+				() -> new IllegalArgumentException("Relation to entity type '" + target + "' does not exist."));
+	}
+
+	/**
+	 * Adds given {@link Relation}.
+	 *
+	 * @param relation {@code Relation} which will be added.
+	 */
+	private void addRelation(Relation relation) {
+		relationsByType.computeIfAbsent(relation.getRelationType(), k -> new ArrayList<>()).add(relation);
+		relations.add(relation);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
new file mode 100644
index 0000000..50f9917
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
@@ -0,0 +1,447 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import static java.util.stream.Collectors.groupingBy;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.Stream;
+
+import org.asam.ods.AIDName;
+import org.asam.ods.AggrFunc;
+import org.asam.ods.AoException;
+import org.asam.ods.AoSession;
+import org.asam.ods.ApplElem;
+import org.asam.ods.ApplElemAccess;
+import org.asam.ods.ApplRel;
+import org.asam.ods.ApplicationStructureValue;
+import org.asam.ods.ElemResultSetExt;
+import org.asam.ods.EnumerationAttributeStructure;
+import org.asam.ods.EnumerationItemStructure;
+import org.asam.ods.EnumerationStructure;
+import org.asam.ods.JoinDef;
+import org.asam.ods.QueryStructureExt;
+import org.asam.ods.SelAIDNameUnitId;
+import org.asam.ods.SelItem;
+import org.asam.ods.SelOrder;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.EnumRegistry;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.odsadapter.lookup.config.DefaultEntityConfigRepositoryLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfigRepository;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfigRepositoryLoader;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSEnum;
+import org.eclipse.mdm.api.odsadapter.utils.ODSEnumerations;
+import org.omg.CORBA.ORB;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ODS implementation of the {@link ModelManager} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class ODSModelManager implements ModelManager {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSModelManager.class);
+
+	private final Map<String, EntityType> entityTypesByName = new HashMap<>();
+
+	private final ORB orb;
+
+	private final Lock write;
+	private final Lock read;
+
+	private EntityConfigRepository entityConfigRepository;
+	private EntityConfigRepositoryLoader entityConfigRepositoryLoader;
+
+	private ApplElemAccess applElemAccess;
+	private AoSession aoSession;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param orb       Used to activate CORBA service objects.
+	 * @param aoSession The underlying ODS session.
+	 * @throws AoException Thrown on errors.
+	 */
+	public ODSModelManager(ORB orb, AoSession aoSession) throws AoException {
+		this(orb, aoSession, new DefaultEntityConfigRepositoryLoader());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param orb       Used to activate CORBA service objects.
+	 * @param aoSession The underlying ODS session.
+	 * @throws AoException Thrown on errors.
+	 */
+	public ODSModelManager(ORB orb, AoSession aoSession, EntityConfigRepositoryLoader entityConfigRepositoryLoader)
+			throws AoException {
+		this.aoSession = aoSession;
+		this.orb = orb;
+		applElemAccess = aoSession.getApplElemAccess();
+		this.entityConfigRepositoryLoader = entityConfigRepositoryLoader;
+
+		// setup locks
+		ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
+		write = reentrantReadWriteLock.writeLock();
+		read = reentrantReadWriteLock.readLock();
+
+		initialize();
+	}
+
+	/**
+	 * Returns the {@link ORB}.
+	 *
+	 * @return The {@code ORB} is returned.
+	 */
+	public ORB getORB() {
+		return orb;
+	}
+
+	/**
+	 * Returns the non root {@link EntityConfig} for given {@link Key}.
+	 *
+	 * @param <T> The concrete entity type.
+	 * @param key Used as identifier.
+	 * @return The non root {@code EntityConfig} is returned.
+	 */
+	public <T extends Entity> EntityConfig<T> findEntityConfig(Key<T> key) {
+		read.lock();
+
+		try {
+			return entityConfigRepository.find(key);
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * Returns the root {@link EntityConfig} for given {@link Key}.
+	 *
+	 * @param <T> The concrete entity type.
+	 * @param key Used as identifier.
+	 * @return The root {@code EntityConfig} is returned.
+	 */
+	public <T extends Entity> EntityConfig<T> getEntityConfig(Key<T> key) {
+		read.lock();
+
+		try {
+			return entityConfigRepository.findRoot(key);
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * Returns the {@link EntityConfig} associated with given {@link EntityType}.
+	 *
+	 * @param entityType Used as identifier.
+	 * @return The {@code EntityConfig} is returned.
+	 */
+	public EntityConfig<?> getEntityConfig(EntityType entityType) {
+		read.lock();
+
+		try {
+			return entityConfigRepository.find(entityType);
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<EntityType> listEntityTypes() {
+		read.lock();
+
+		try {
+			return Collections.unmodifiableList(new ArrayList<>(entityTypesByName.values()));
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getEntityType(Class<? extends Entity> entityClass) {
+		read.lock();
+
+		try {
+			return getEntityConfig(new Key<>(entityClass)).getEntityType();
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getEntityType(Class<? extends Entity> entityClass, ContextType contextType) {
+		read.lock();
+
+		try {
+			return getEntityConfig(new Key<>(entityClass, contextType)).getEntityType();
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getEntityType(String name) {
+		read.lock();
+
+		try {
+			EntityType entityType = entityTypesByName.get(name);
+			if (entityType == null) {
+				throw new IllegalArgumentException("Entity with name '" + name + "' not found.");
+			}
+
+			return entityType;
+		} finally {
+			read.unlock();
+		}
+	}
+
+	@Override
+	public EntityType getEntityTypeById(String id) {
+		Optional<EntityType> entityType = listEntityTypes().stream().filter(et -> et.getId().equals(id)).findFirst();
+		if (!entityType.isPresent()) {
+			throw new IllegalArgumentException("Entity with id '" + id + "' not found.");
+		}
+
+		return entityType.get();
+	}
+
+	/**
+	 * Returns the {@link AoSession} of this model manager.
+	 *
+	 * @return The {@code AoSession} is returned.
+	 */
+	public AoSession getAoSession() {
+		write.lock();
+
+		try {
+			return aoSession;
+		} finally {
+			write.unlock();
+		}
+	}
+
+	/**
+	 * Returns the {@link ApplElemAccess} of this model manager.
+	 *
+	 * @return The {@code ApplElemAccess} is returned.
+	 */
+	public ApplElemAccess getApplElemAccess() {
+		read.lock();
+
+		try {
+			return applElemAccess;
+		} finally {
+			read.unlock();
+		}
+	}
+
+	/**
+	 * Closes the ODS connection.
+	 *
+	 * @throws AoException Thrown on errors.
+	 */
+	public void close() throws AoException {
+		read.lock();
+
+		try {
+			applElemAccess._release();
+			aoSession.close();
+		} finally {
+			read.unlock();
+			aoSession._release();
+		}
+	}
+
+	/**
+	 * Reloads the complete session context.
+	 */
+	public void reloadApplicationModel() {
+		write.lock();
+
+		AoSession aoSessionOld = aoSession;
+		ApplElemAccess applElemAccessOld = applElemAccess;
+		try {
+			entityTypesByName.clear();
+
+			aoSession = aoSession.createCoSession();
+			applElemAccess = aoSession.getApplElemAccess();
+			initialize();
+		} catch (AoException e) {
+			LOGGER.error("Unable to reload the application model due to: " + e.reason, e);
+		} finally {
+			write.unlock();
+		}
+
+		try {
+			applElemAccessOld._release();
+			aoSessionOld.close();
+		} catch (AoException e) {
+			LOGGER.debug("Unable to close replaced session due to: " + e.reason, e);
+		} finally {
+			aoSessionOld._release();
+		}
+	}
+
+	/**
+	 * Initializes this model manager by caching the application model and loading
+	 * the {@link EntityConfig}s.
+	 *
+	 * @throws AoException Thrown on errors.
+	 */
+	private void initialize() throws AoException {
+		loadApplicationModel();
+		entityConfigRepository = entityConfigRepositoryLoader.loadEntityConfigurations(this);
+	}
+
+	/**
+	 * Caches the whole application model as provided by the ODS session.
+	 *
+	 * @throws AoException Thrown on errors.
+	 */
+	private void loadApplicationModel() throws AoException {
+		LOGGER.debug("Reading the application model...");
+
+		Map<String, Map<String, Enumeration<?>>> enumClassMap = loadODSEnumerations();
+
+		long start = System.currentTimeMillis();
+		ApplicationStructureValue applicationStructureValue = aoSession.getApplicationStructureValue();
+		Map<String, String> units = getUnitMapping(applicationStructureValue.applElems);
+
+		// create entity types (incl. attributes)
+		Map<String, ODSEntityType> entityTypesByID = new HashMap<>();
+		String sourceName = aoSession.getName();
+		for (ApplElem applElem : applicationStructureValue.applElems) {
+			String odsID = Long.toString(ODSConverter.fromODSLong(applElem.aid));
+			Map<String, Enumeration<?>> entityEnumMap = enumClassMap.getOrDefault(odsID, new HashMap<>());
+
+			ODSEntityType entityType = new ODSEntityType(sourceName, applElem, units, entityEnumMap);
+			entityTypesByName.put(applElem.aeName, entityType);
+			entityTypesByID.put(odsID, entityType);
+		}
+
+		// create relations
+		List<Relation> relations = new ArrayList<>();
+		for (ApplRel applRel : applicationStructureValue.applRels) {
+			EntityType source = entityTypesByID.get(Long.toString(ODSConverter.fromODSLong(applRel.elem1)));
+			EntityType target = entityTypesByID.get(Long.toString(ODSConverter.fromODSLong(applRel.elem2)));
+			relations.add(new ODSRelation(applRel, source, target));
+		}
+
+		// assign relations to their source entity types
+		relations.stream().collect(groupingBy(Relation::getSource))
+				.forEach((e, r) -> ((ODSEntityType) e).setRelations(r));
+
+		long stop = System.currentTimeMillis();
+		LOGGER.debug("{} entity types with {} relations found in {} ms.", entityTypesByName.size(), relations.size(),
+				stop - start);
+	}
+
+	private Map<String, Map<String, Enumeration<?>>> loadODSEnumerations() throws AoException {
+		LOGGER.debug("Loading ODS enumerations...");
+		long t1 = System.currentTimeMillis();
+
+		// enumeration mappings (aeID -> (aaName -> enumClass))
+		Map<String, Map<String, Enumeration<?>>> enumClassMap = new HashMap<>();
+		EnumRegistry er = EnumRegistry.getInstance();
+
+		Map<String, EnumerationItemStructure[]> map = new HashMap<>();
+		for (EnumerationStructure es : aoSession.getEnumerationStructure()) {
+			map.put(es.enumName, es.items);
+		}
+
+		for (EnumerationAttributeStructure eas : aoSession.getEnumerationAttributes()) {
+
+			// make sure the enumeration is found
+			if (ODSEnumerations.getEnumObj(eas.enumName) == null) {
+				Enumeration<ODSEnum> enumdyn = new Enumeration<>(ODSEnum.class, eas.enumName);
+				for (EnumerationItemStructure enumItemStruct : map.get(eas.enumName)) {
+					LOGGER.trace("{}:{}:{}", eas.enumName, enumItemStruct.itemName, enumItemStruct.index);
+					enumdyn.addValue(new ODSEnum(enumItemStruct.itemName, enumItemStruct.index));
+				}
+				er.add(eas.enumName, enumdyn);
+			}
+
+			enumClassMap.computeIfAbsent(Long.toString(ODSConverter.fromODSLong(eas.aid)), k -> new HashMap<>())
+					.put(eas.aaName, ODSEnumerations.getEnumObj(eas.enumName));
+		}
+		LOGGER.debug("Loading enumerations took {}ms", System.currentTimeMillis() - t1);
+		return enumClassMap;
+	}
+
+	/**
+	 * Loads all available {@link Unit} names mapped by their instance IDs.
+	 *
+	 * @param applElems The application element meta data instances.
+	 * @return The unit names mapped by the corresponding instance IDs.
+	 * @throws AoException Thrown if unable to load the unit mappings.
+	 */
+	private Map<String, String> getUnitMapping(ApplElem[] applElems) throws AoException {
+		ApplElem unitElem = Stream.of(applElems).filter(ae -> ae.beName.equals("AoUnit")).findAny()
+				.orElseThrow(() -> new IllegalStateException("Application element 'Unit' is not defined."));
+
+		QueryStructureExt qse = new QueryStructureExt();
+		qse.anuSeq = new SelAIDNameUnitId[] {
+				new SelAIDNameUnitId(new AIDName(unitElem.aid, "Id"), new T_LONGLONG(), AggrFunc.NONE),
+				new SelAIDNameUnitId(new AIDName(unitElem.aid, "Name"), new T_LONGLONG(), AggrFunc.NONE) };
+		qse.condSeq = new SelItem[0];
+		qse.groupBy = new AIDName[0];
+		qse.joinSeq = new JoinDef[0];
+		qse.orderBy = new SelOrder[0];
+
+		Map<String, String> units = new HashMap<>();
+		ElemResultSetExt unitResultSetExt = getApplElemAccess().getInstancesExt(qse, 0)[0].firstElems[0];
+		for (int i = 0; i < unitResultSetExt.values[0].value.flag.length; i++) {
+			String unitID = Long
+					.toString(ODSConverter.fromODSLong(unitResultSetExt.values[0].value.u.longlongVal()[i]));
+			String unitName = unitResultSetExt.values[1].value.u.stringVal()[i];
+			units.put(unitID, unitName);
+		}
+
+		return units;
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java
new file mode 100644
index 0000000..b2f5d03
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java
@@ -0,0 +1,558 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.asam.ods.AIDName;
+import org.asam.ods.AIDNameUnitId;
+import org.asam.ods.AoException;
+import org.asam.ods.ApplElemAccess;
+import org.asam.ods.ElemResultSetExt;
+import org.asam.ods.JoinDef;
+import org.asam.ods.NameValueSeqUnitId;
+import org.asam.ods.QueryStructureExt;
+import org.asam.ods.ResultSetExt;
+import org.asam.ods.SelAIDNameUnitId;
+import org.asam.ods.SelItem;
+import org.asam.ods.SelOrder;
+import org.asam.ods.SelValueExt;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.Condition;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.FilterItem;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Strings;
+
+/**
+ * ODS implementation of the {@link Query} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public class ODSQuery implements Query {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSQuery.class);
+
+	private static final String GROUP_NAME = "name";
+	private static final String GROUP_AGGRFUNC = "aggrfunc";
+	private static final Pattern AGGREGATION_NAME_PATTERN = Pattern
+			.compile("(?<" + GROUP_AGGRFUNC + ">\\S+)\\((?<" + GROUP_NAME + ">\\S+)\\)");
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<String, EntityType> entityTypesByID = new HashMap<>();
+	private final Set<EntityType> queriedEntityTypes = new HashSet<>();
+	private final List<SelAIDNameUnitId> anuSeq = new ArrayList<>();
+	private final List<JoinDef> joinSeq = new ArrayList<>();
+	private final List<AIDName> groupBy = new ArrayList<>();
+	private final List<SelOrder> orderBy = new ArrayList<>();
+
+	private final ApplElemAccess applElemAccess;
+
+	private int limit;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param applElemAccess Used to execute the query.
+	 */
+	ODSQuery(ApplElemAccess applElemAccess) {
+		this.applElemAccess = applElemAccess;
+		limit = 0;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isQueried(EntityType entityType) {
+		return queriedEntityTypes.contains(entityType);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query limit(int limit) {
+		this.limit = limit;
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query select(Attribute attribute, Aggregation aggregation) {
+		EntityType entityType = attribute.getEntityType();
+		entityTypesByID.put(Long.toString(ODSConverter.fromODSLong(((ODSEntityType) entityType).getODSID())),
+				entityType);
+		queriedEntityTypes.add(entityType);
+		anuSeq.add(createSelect(attribute, aggregation));
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query join(Relation relation, JoinType join) {
+		queriedEntityTypes.add(relation.getSource());
+		queriedEntityTypes.add(relation.getTarget());
+		joinSeq.add(createJoin(relation, join));
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query group(List<Attribute> attributes) {
+		for (Attribute attribute : attributes) {
+			group(attribute);
+		}
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query group(Attribute attribute) {
+		groupBy.add(createAIDName(attribute));
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query order(Attribute attribute, boolean ascending) {
+		orderBy.add(createOrderBy(attribute, ascending));
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<Result> fetchSingleton(Filter filter) throws DataAccessException {
+		List<Result> results = fetch(filter);
+		if (results.isEmpty()) {
+			return Optional.empty();
+		} else if (results.size() > 1) {
+			throw new DataAccessException("Multiple results found after executing the singleton query!");
+		}
+
+		return Optional.of(results.get(0));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Result> fetch(Filter filter) throws DataAccessException {
+		try {
+
+			List<SelItem> condSeq = new ArrayList<>();
+			int condCount = 0;
+			for (FilterItem conditionItem : filter) {
+				SelItem selItem = new SelItem();
+				if (conditionItem.isCondition()) {
+					selItem.value(createCondition(conditionItem.getCondition()));
+				} else if (conditionItem.isBracketOperator()) {
+					selItem._operator(ODSUtils.BRACKETOPERATORS.get(conditionItem.getBracketOperator()));
+				} else if (conditionItem.isBooleanOperator()) {
+					selItem._operator(ODSUtils.OPERATORS.get(conditionItem.getBooleanOperator()));
+					condCount++;
+				} else {
+					throw new IllegalArgumentException("Passed filter item is neither an operator nor a condition.");
+				}
+
+				condSeq.add(selItem);
+			}
+
+			QueryStructureExt qse = new QueryStructureExt();
+			qse.anuSeq = anuSeq.toArray(new SelAIDNameUnitId[anuSeq.size()]);
+			qse.condSeq = condSeq.toArray(new SelItem[condSeq.size()]);
+			qse.groupBy = groupBy.toArray(new AIDName[groupBy.size()]);
+			qse.joinSeq = joinSeq.toArray(new JoinDef[joinSeq.size()]);
+			qse.orderBy = orderBy.toArray(new SelOrder[orderBy.size()]);
+
+			List<Result> results = new ArrayList<>();
+			long start = System.currentTimeMillis();
+			for (Result result : new ResultFactory(entityTypesByID, applElemAccess.getInstancesExt(qse, limit)[0])) {
+				results.add(result);
+			}
+			long stop = System.currentTimeMillis();
+
+			LOGGER.debug("Query executed in {} ms and retrieved {} result rows ({} selections, {} conditions, "
+					+ "{} joins).", stop - start, results.size(), anuSeq.size(), condCount, joinSeq.size());
+			return results;
+		} catch (AoException aoe) {
+			throw new DataAccessException(aoe.reason, aoe);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Converts given {@link Attribute} and {@link Aggregation} to an ODS
+	 * {@link SelAIDNameUnitId}.
+	 *
+	 * @param attribute   The {@code Attribute}.
+	 * @param aggregation The {@code Aggregation}.
+	 * @return The corresponding {@code SelAIDNameUnitId} is returned.
+	 */
+	private SelAIDNameUnitId createSelect(Attribute attribute, Aggregation aggregation) {
+		SelAIDNameUnitId sanu = new SelAIDNameUnitId();
+
+		sanu.aggregate = ODSUtils.AGGREGATIONS.get(aggregation);
+		sanu.attr = createAIDName(attribute);
+		sanu.unitId = new T_LONGLONG();
+
+		return sanu;
+	}
+
+	/**
+	 * Converts given {@link Condition} to an ODS {@link SelValueExt}.
+	 *
+	 * @param condition The {@code Condition}.
+	 * @return The corresponding {@code SelValueExt} is returned.
+	 * @throws DataAccessException Thrown in case of errors.
+	 */
+	private SelValueExt createCondition(Condition condition) throws DataAccessException {
+		SelValueExt sve = new SelValueExt();
+
+		sve.oper = ODSUtils.OPERATIONS.get(condition.getComparisonOperator());
+		sve.attr = new AIDNameUnitId();
+		sve.attr.unitId = new T_LONGLONG();
+		sve.attr.attr = createAIDName(condition.getAttribute());
+		sve.value = ODSConverter.toODSValue(condition.getAttribute(), condition.getValue());
+
+		return sve;
+	}
+
+	/**
+	 * Converts given {@link Relation} and {@link JoinType} to an ODS
+	 * {@link JoinDef}.
+	 *
+	 * @param relation The {@code Relation}.
+	 * @param join     The {@code JoinType}.
+	 * @return The corresponding {@code JoinDef} is returned.
+	 */
+	private JoinDef createJoin(Relation relation, JoinType join) {
+		JoinDef joinDef = new JoinDef();
+
+		joinDef.fromAID = ((ODSEntityType) relation.getSource()).getODSID();
+		joinDef.toAID = ((ODSEntityType) relation.getTarget()).getODSID();
+		joinDef.refName = relation.getName();
+		joinDef.joiningType = ODSUtils.JOINS.get(join);
+
+		return joinDef;
+	}
+
+	/**
+	 * Converts given {@link Attribute} and sort order flag to an ODS
+	 * {@link SelOrder}.
+	 *
+	 * @param attribute The {@code Attribute}.
+	 * @param ascending The sort order.
+	 * @return The corresponding {@code SelOrder} is returned.
+	 */
+	private SelOrder createOrderBy(Attribute attribute, boolean ascending) {
+		SelOrder selOrder = new SelOrder();
+
+		selOrder.attr = createAIDName(attribute);
+		selOrder.ascending = ascending;
+
+		return selOrder;
+	}
+
+	/**
+	 * Converts given {@link Attribute} to an ODS {@link AIDName}.
+	 *
+	 * @param attribute The {@code Attribute}.
+	 * @return The corresponding {@code AIDName} is returned.
+	 */
+	private AIDName createAIDName(Attribute attribute) {
+		AIDName aidName = new AIDName();
+
+		aidName.aid = ((ODSEntityType) attribute.getEntityType()).getODSID();
+		aidName.aaName = attribute.getName();
+
+		return aidName;
+	}
+
+	private static Aggregation getAggregation(String odsAggrFunc) {
+		switch (Strings.nullToEmpty(odsAggrFunc).trim().toUpperCase()) {
+		case "COUNT":
+			return Aggregation.COUNT;
+		case "DCOUNT":
+			return Aggregation.DISTINCT_COUNT;
+		case "MIN":
+			return Aggregation.MINIMUM;
+		case "MAX":
+			return Aggregation.MAXIMUM;
+		case "AVG":
+			return Aggregation.AVERAGE;
+		case "STDDEV":
+			return Aggregation.DEVIATION;
+		case "SUM":
+			return Aggregation.SUM;
+		case "DISTINCT":
+			return Aggregation.DISTINCT;
+		default:
+			throw new IllegalArgumentException(
+					"Unsupported aggregate function '" + Strings.nullToEmpty(odsAggrFunc).trim().toUpperCase() + "'!");
+		}
+
+	}
+
+	// ======================================================================
+	// Inner classes
+	// ======================================================================
+
+	/**
+	 * Traverses the ODS {@link ResultSetExt} and creates a {@link Result} for each
+	 * row.
+	 */
+	private static final class ResultFactory implements Iterable<Result>, Iterator<Result> {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		private final List<RecordFactory> recordFactories = new ArrayList<>();
+		private final int length;
+		private int index;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param entityTypes  Used to access {@link EntityType} by its ODS ID.
+		 * @param resultSetExt The ODS values sequence containers.
+		 * @throws DataAccessException Thrown on conversion errors.
+		 */
+		public ResultFactory(Map<String, EntityType> entityTypes, ResultSetExt resultSetExt)
+				throws DataAccessException {
+			for (ElemResultSetExt elemResultSetExt : resultSetExt.firstElems) {
+				EntityType entityType = entityTypes.get(Long.toString(ODSConverter.fromODSLong(elemResultSetExt.aid)));
+				recordFactories.add(new RecordFactory(entityType, elemResultSetExt.values));
+			}
+
+			length = recordFactories.isEmpty() ? 0 : recordFactories.get(0).getLength();
+		}
+
+		// ======================================================================
+		// Public methods
+		// ======================================================================
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public boolean hasNext() {
+			return index < length;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public Result next() {
+			if (!hasNext()) {
+				throw new NoSuchElementException("No such element available.");
+			}
+			Result result = new Result();
+
+			for (RecordFactory recordFactory : recordFactories) {
+				result.addRecord(recordFactory.createRecord(index));
+			}
+
+			index++;
+			return result;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public Iterator<Result> iterator() {
+			return this;
+		}
+
+	}
+
+	/**
+	 * Creates a {@link Record} for given index from the original ODS values
+	 * sequence for a given {@link EntityType}.
+	 */
+	private static final class RecordFactory {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		private final List<ValueFactory> valueFactories = new ArrayList<>();
+		private final EntityType entityType;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param entityType The associated {@link EntityType}.
+		 * @param nvsuis     The ODS value sequence containers.
+		 * @throws DataAccessException Thrown on conversion errors.
+		 */
+		private RecordFactory(EntityType entityType, NameValueSeqUnitId[] nvsuis) throws DataAccessException {
+			this.entityType = entityType;
+			for (NameValueSeqUnitId nvsui : nvsuis) {
+				String attributeName = nvsui.valName;
+				Aggregation aggregation = Aggregation.NONE;
+				Matcher matcher = AGGREGATION_NAME_PATTERN.matcher(nvsui.valName);
+				if (matcher.matches()) {
+					attributeName = matcher.group(GROUP_NAME);
+					aggregation = ODSQuery.getAggregation(matcher.group(GROUP_AGGRFUNC));
+				}
+
+				valueFactories.add(new ValueFactory(entityType.getAttribute(attributeName), aggregation, nvsui));
+			}
+		}
+
+		// ======================================================================
+		// Private methods
+		// ======================================================================
+
+		private int getLength() {
+			return valueFactories.isEmpty() ? 0 : valueFactories.get(0).getLength();
+		}
+
+		private Record createRecord(int index) {
+			Record record = new Record(entityType);
+			for (ValueFactory valueFactory : valueFactories) {
+				record.addValue(valueFactory.createValue(index));
+			}
+
+			return record;
+		}
+
+	}
+
+	/**
+	 * Creates a {@link Value} container for given index from the original ODS value
+	 * sequence for a given {@link Attribute}.
+	 */
+	private static final class ValueFactory {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		private final List<Value> values;
+		private final String unit;
+		private final int length;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param attribute The associated {@link Attribute}.
+		 * @param nvsui     The ODS value sequence container.
+		 * @throws DataAccessException Thrown on conversion errors.
+		 */
+		private ValueFactory(Attribute attribute, Aggregation aggregation, NameValueSeqUnitId nvsui)
+				throws DataAccessException {
+			length = nvsui.value.flag.length;
+			unit = attribute.getUnit();
+			values = ODSConverter.fromODSValueSeq(attribute, aggregation, unit, nvsui.value);
+		}
+
+		// ======================================================================
+		// Private methods
+		// ======================================================================
+
+		/**
+		 * Returns the length of the sequence.
+		 *
+		 * @return Length of the sequence is returned.
+		 */
+		private int getLength() {
+			return length;
+		}
+
+		/**
+		 * Returns the {@link Value} for given index.
+		 *
+		 * @param index Index within the sequence.
+		 * @return The corresponding {@code Value} is returned.
+		 */
+		private Value createValue(int index) {
+			return values.get(index);
+		}
+
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQueryService.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQueryService.java
new file mode 100644
index 0000000..e226a3e
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQueryService.java
@@ -0,0 +1,35 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+
+public class ODSQueryService implements QueryService {
+
+	private ODSModelManager modelManager;
+
+	public ODSQueryService(ODSModelManager modelManager) {
+		this.modelManager = modelManager;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Query createQuery() {
+		return new ODSQuery(modelManager.getApplElemAccess());
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java
new file mode 100644
index 0000000..e57cb39
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSRelation.java
@@ -0,0 +1,169 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.query;
+
+import java.util.Objects;
+
+import org.asam.ods.ApplAttr;
+import org.asam.ods.ApplRel;
+import org.asam.ods.DataType;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.adapter.RelationType;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+
+/**
+ * ODS implementation of the {@link Relation} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSRelation implements Relation {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final RelationType relationType;
+	private final EntityType source;
+	private final EntityType target;
+	private final String name;
+
+	private final int rangeMax;
+	private final int invRangeMax;
+	private Attribute attribute;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param applRel The ODS meta data for this relation.
+	 * @param source  The source {@link EntityType}.
+	 * @param target  The target {@code EntityType}.
+	 */
+	ODSRelation(ApplRel applRel, EntityType source, EntityType target) {
+		this.source = source;
+		this.target = target;
+		name = applRel.arName;
+		relationType = ODSUtils.RELATIONSHIPS.inverse().get(applRel.arRelationType);
+		rangeMax = applRel.arRelationRange.max;
+		invRangeMax = applRel.invRelationRange.max;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getSource() {
+		return source;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getTarget() {
+		return target;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public RelationType getRelationType() {
+		return relationType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Attribute getAttribute() {
+		if (attribute == null) {
+			attribute = new ODSAttribute(getSource(),
+					new ApplAttr(getName(), "", DataType.DT_LONGLONG, 0, true, false, null), null, null);
+		}
+
+		return attribute;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return Objects.hash(getSource(), getTarget(), getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object object) {
+		if (object instanceof ODSRelation) {
+			Relation relation = (Relation) object;
+			return getSource().equals(relation.getSource()) && getTarget().equals(relation.getTarget())
+					&& getName().equals(relation.getName());
+		}
+
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isOutgoing(RelationType relationType) {
+		return relationType.equals(getRelationType()) && rangeMax == 1;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean isIncoming(RelationType relationType) {
+		return relationType.equals(getRelationType()) && rangeMax == -1;
+	}
+
+	@Override
+	public boolean isNtoM() {
+		return relationType == RelationType.INFO && rangeMax == -1 && invRangeMax == -1;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java
new file mode 100644
index 0000000..effa0dc
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java
@@ -0,0 +1,279 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.reducing;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.FilterItem;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.base.search.Searchable;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinNode;
+
+/**
+ * Base implementation for entity {@link SearchQuery}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+abstract class BaseEntitySearchQuery implements SearchQuery {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Class<? extends Entity> rootEntityClass;
+	private final JoinTree joinTree = new JoinTree();
+	private final Class<? extends Entity> entityClass;
+
+	private final ODSModelManager modelManager;
+	private final QueryService queryService;
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager    Used to load {@link EntityType}s.
+	 * @param entityClass     The source entity class of this search query.
+	 * @param rootEntityClass The root entity class of this search query.
+	 */
+	protected BaseEntitySearchQuery(ODSModelManager modelManager, QueryService queryService,
+			Class<? extends Entity> entityClass, Class<? extends Entity> rootEntityClass) {
+		this.modelManager = modelManager;
+		this.queryService = queryService;
+		this.entityClass = entityClass;
+		this.rootEntityClass = rootEntityClass;
+
+		EntityConfig<?> entityConfig = modelManager.getEntityConfig(new Key<>(entityClass));
+		EntityType source = entityConfig.getEntityType();
+
+		entityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType)
+				.filter(et -> !"Classification".equals(et.getName())).forEach(entityType -> {
+					joinTree.addNode(source, entityType, true, JoinType.OUTER);
+				});
+
+		entityConfig.getMandatoryConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
+			joinTree.addNode(source, entityType, true, JoinType.INNER);
+		});
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final List<EntityType> listEntityTypes() {
+		return joinTree.getNodeNames().stream().map(modelManager::getEntityType).collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final Searchable getSearchableRoot() {
+		Function<String, SearchableNode> factory = k -> {
+			return new SearchableNode(modelManager.getEntityType(k));
+		};
+
+		Map<String, SearchableNode> nodes = new HashMap<>();
+		for (Entry<String, List<String>> entry : joinTree.getTree().entrySet()) {
+			SearchableNode parent = nodes.computeIfAbsent(entry.getKey(), factory);
+
+			for (String childName : entry.getValue()) {
+				parent.addRelated(nodes.computeIfAbsent(childName, factory));
+			}
+		}
+
+		return nodes.get(modelManager.getEntityType(rootEntityClass).getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final List<Value> getFilterValues(Attribute attribute, Filter filter) throws DataAccessException {
+		Query query = queryService.createQuery().select(attribute, Aggregation.DISTINCT).group(attribute);
+
+		// add required joins
+		filter.stream().filter(FilterItem::isCondition).map(FilterItem::getCondition).forEach(c -> {
+			addJoins(query, c.getAttribute().getEntityType());
+		});
+
+		return query.fetch(filter).stream().map(r -> r.getValue(attribute)).collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final List<Result> fetchComplete(List<EntityType> entityTypes, Filter filter) throws DataAccessException {
+		Query query = queryService.createQuery().selectID(modelManager.getEntityType(entityClass));
+
+		// add required joins
+		entityTypes.stream().forEach(entityType -> {
+			addJoins(query, entityType);
+			query.selectAll(entityType);
+		});
+
+		return fetch(query, filter);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final List<Result> fetch(List<Attribute> attributes, Filter filter) throws DataAccessException {
+		Query query = queryService.createQuery().selectID(modelManager.getEntityType(entityClass));
+
+		// add required joins
+		attributes.stream().forEach(attribute -> {
+			addJoins(query, attribute.getEntityType());
+			query.select(attribute);
+		});
+
+		return fetch(query, filter);
+	}
+
+	// ======================================================================
+	// Protected methods
+	// ======================================================================
+
+	/**
+	 * Adds given {@link JoinConfig} to the internally managed {@link JoinTree}.
+	 *
+	 * @param joinConfig Will be added.
+	 */
+	protected final void addJoinConfig(JoinConfig joinConfig) {
+		EntityConfig<?> targetEntityConfig = modelManager.getEntityConfig(new Key<>(joinConfig.target));
+		EntityType target = targetEntityConfig.getEntityType();
+
+		// add dependency source to target
+		joinTree.addNode(modelManager.getEntityType(joinConfig.source), target, joinConfig.viaParent, JoinType.INNER);
+
+		// add target's optional dependencies
+		targetEntityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType)
+				.filter(et -> !"Classification".equals(et.getName())).forEach(entityType -> {
+					joinTree.addNode(target, entityType, true, JoinType.OUTER);
+				});
+
+		// add target's mandatory dependencies
+		targetEntityConfig.getMandatoryConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
+			joinTree.addNode(target, entityType, true, JoinType.INNER);
+		});
+	}
+
+	/**
+	 * Adds joins to context data according to the given {@link ContextState}.
+	 *
+	 * @param contextState The {@code ContextState}.
+	 */
+	protected final void addJoinConfig(ContextState contextState) {
+		if (contextState == null) {
+			// nothing to do
+			return;
+		}
+
+		Class<? extends Entity> source = contextState.isOrdered() ? TestStep.class : Measurement.class;
+		for (ContextType contextType : ContextType.values()) {
+			EntityType rootEntityType = modelManager.getEntityType(ContextRoot.class, contextType);
+			for (Relation componentRelation : rootEntityType.getChildRelations()) {
+				joinTree.addNode(componentRelation.getSource(), componentRelation.getTarget(), true, JoinType.OUTER);
+
+				for (Relation sensorRelation : componentRelation.getTarget().getChildRelations()) {
+					joinTree.addNode(sensorRelation.getSource(), sensorRelation.getTarget(), true, JoinType.OUTER);
+				}
+			}
+
+			joinTree.addNode(modelManager.getEntityType(source), rootEntityType, true, JoinType.OUTER);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Executes given {@link Query} using given {@link Filter}. Joins required for
+	 * the given {@code Filter} will be implicitly added as needed.
+	 *
+	 * @param query  Will be executed.
+	 * @param filter The query filtering sequence.
+	 * @return Returns the {@link Result}s in a {@code List}.
+	 * @throws DataAccessException Thrown if failed to execute given {@code Query}.
+	 */
+	private List<Result> fetch(Query query, Filter filter) throws DataAccessException {
+		filter.stream().filter(FilterItem::isCondition).map(FilterItem::getCondition)
+				.forEach(c -> addJoins(query, c.getAttribute().getEntityType()));
+
+		EntityType entityType = modelManager.getEntityType(entityClass);
+		return query.order(entityType.getIDAttribute()).fetch(filter).stream()
+				// group by instance ID and merge grouped results
+				.collect(groupingBy(r -> r.getRecord(entityType).getID(), reducing(Result::merge)))
+				// collect merged results
+				.values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
+	}
+
+	/**
+	 * Adds join statements to given target {@link EntityType} as needed to be able
+	 * to execute given {@code Query}.
+	 *
+	 * @param query      The {@link Query}.
+	 * @param entityType The target {@link EntityType}.
+	 */
+	private void addJoins(Query query, EntityType entityType) {
+		if (query.isQueried(entityType)) {
+			return;
+		}
+
+		JoinNode joinNode = joinTree.getJoinNode(entityType.getName());
+		EntityType sourceEntityType = modelManager.getEntityType(joinNode.source);
+		addJoins(query, sourceEntityType);
+		query.join(sourceEntityType.getRelation(entityType), joinNode.joinType);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelGroupSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelGroupSearchQuery.java
new file mode 100644
index 0000000..fbd9edf
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelGroupSearchQuery.java
@@ -0,0 +1,60 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link ChannelGroup} as source entity
+ * type.
+ *
+ * @since 1.0.0
+ * @author
+ */
+final class ChannelGroupSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	ChannelGroupSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, ChannelGroup.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+		addJoinConfig(JoinConfig.up(ChannelGroup.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelSearchQuery.java
new file mode 100644
index 0000000..27facac
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ChannelSearchQuery.java
@@ -0,0 +1,63 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link Channel} as source entity type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class ChannelSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	ChannelSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, Channel.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+		addJoinConfig(JoinConfig.up(Channel.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+
+		// context
+		addJoinConfig(contextState);
+
+		// TODO join to sensor tables.... || this will break the joins to
+		// context data
+		// multiple outer join to the same table...
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ContextState.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ContextState.java
new file mode 100644
index 0000000..d68dbe9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ContextState.java
@@ -0,0 +1,65 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.TestStep;
+
+/**
+ * Context state enumeration.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+enum ContextState {
+
+	// ======================================================================
+	// Enum constants
+	// ======================================================================
+
+	/**
+	 * References {@link ContextRoot}s of {@link TestStep}s.
+	 */
+	ORDERED,
+
+	/**
+	 * References {@link ContextRoot}s of {@link Measurement}s.
+	 */
+	MEASURED;
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Checks whether this context state is {@link #ORDERED}.
+	 *
+	 * @return Returns {@code true} if this instance is {@link #ORDERED}.
+	 */
+	public boolean isOrdered() {
+		return ORDERED == this;
+	}
+
+	/**
+	 * Checks whether this context state is {@link #MEASURED}.
+	 *
+	 * @return Returns {@code true} if this instance is {@link #MEASURED}.
+	 */
+	public boolean isMeasured() {
+		return MEASURED == this;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/JoinTree.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/JoinTree.java
new file mode 100644
index 0000000..e12b6f9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/JoinTree.java
@@ -0,0 +1,212 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+
+/**
+ * This class spans a dependency tree for conditional join statements is
+ * {@link SearchQuery}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class JoinTree {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<String, List<String>> tree = new HashMap<>();
+	private final Map<String, JoinNode> joinNodes = new HashMap<>();
+	private final Set<String> nodeNames = new HashSet<>();
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Returns the tree configuration. It mapps a source entity type names to
+	 * supported target entity type names.
+	 *
+	 * @return The returned {@code Map} is unmodifiable.
+	 */
+	public Map<String, List<String>> getTree() {
+		return Collections.unmodifiableMap(tree);
+	}
+
+	/**
+	 * Returns a {@code List} with distinct entity type names covered by this join
+	 * tree.
+	 *
+	 * @return Returned {@code List} is unmodifiable.
+	 */
+	public Set<String> getNodeNames() {
+		return Collections.unmodifiableSet(nodeNames);
+	}
+
+	/**
+	 * Returns the {@link JoinNode} for given target entity type name.
+	 *
+	 * @param target The target entity type name.
+	 * @return The {@code JoinNode} for given target entity type name is returned.
+	 * @throws IllegalArgumentException Thrown if no such {@code JoinNode} exists.
+	 */
+	public JoinNode getJoinNode(String target) {
+		JoinNode joinNode = joinNodes.get(target);
+		if (joinNode == null) {
+			throw new IllegalArgumentException("Relation to '" + target + "' not possible.");
+		}
+
+		return joinNode;
+	}
+
+	/**
+	 * Adds given dependency setup to this join tree.
+	 *
+	 * @param source    The source entity type name.
+	 * @param target    The target entity type name.
+	 * @param viaParent If true, then source is the considered parent of the target.
+	 * @param joinType  Either inner or outer joinType.
+	 * @throws IllegalArgumentException Thrown if given setup overrides an existing
+	 *                                  one (a target entity type is allowed to be
+	 *                                  joined only once).
+	 */
+	public void addNode(EntityType source, EntityType target, boolean viaParent, JoinType joinType) {
+		String sourceName = source.getName();
+		String targetName = target.getName();
+
+		if (joinNodes.put(targetName, new JoinNode(sourceName, targetName, joinType)) != null) {
+			throw new IllegalArgumentException("It is not allowed to override join nodes.");
+		}
+
+		if (viaParent) {
+			tree.computeIfAbsent(sourceName, k -> new ArrayList<>()).add(targetName);
+		} else {
+			tree.computeIfAbsent(targetName, k -> new ArrayList<>()).add(sourceName);
+		}
+
+		nodeNames.add(sourceName);
+		nodeNames.add(targetName);
+	}
+
+	// ======================================================================
+	// Inner classes
+	// ======================================================================
+
+	/**
+	 * A simple joinType node setup.
+	 */
+	static final class JoinNode {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		final String source;
+		final String target;
+		final JoinType joinType;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param source   The source entity type name.
+		 * @param target   The target entity type name.
+		 * @param joinType Either inner or outer {@link JoinType}.
+		 */
+		private JoinNode(String source, String target, JoinType joinType) {
+			this.source = source;
+			this.target = target;
+			this.joinType = joinType;
+		}
+
+	}
+
+	/**
+	 * A simple joinType configuration setup.
+	 */
+	static final class JoinConfig {
+
+		// ======================================================================
+		// Instance variables
+		// ======================================================================
+
+		final Class<? extends Entity> source;
+		final Class<? extends Entity> target;
+		final boolean viaParent;
+
+		// ======================================================================
+		// Constructors
+		// ======================================================================
+
+		/**
+		 * Constructor.
+		 *
+		 * @param source    The source entity type name.
+		 * @param target    The target entity type name.
+		 * @param viaParent If true, then source is the considered parent of the target.
+		 */
+		private JoinConfig(Class<? extends Entity> source, Class<? extends Entity> target, boolean viaParent) {
+			this.source = source;
+			this.target = target;
+			this.viaParent = viaParent;
+		}
+
+		// ======================================================================
+		// Package methods
+		// ======================================================================
+
+		/**
+		 * Creates a new {@link JoinConfig} where given source is considered as the
+		 * child of given target.
+		 *
+		 * @param source The source entity type name.
+		 * @param target The target entity type name.
+		 * @return The created {@code JoinConfig} is returned.
+		 */
+		static JoinConfig up(Class<? extends Entity> source, Class<? extends Entity> target) {
+			return new JoinConfig(source, target, false);
+		}
+
+		/**
+		 * Creates a new {@link JoinConfig} where given source is considered as the
+		 * parent of given target.
+		 *
+		 * @param source The source entity type name.
+		 * @param target The target entity type name.
+		 * @return The created {@code JoinConfig} is returned.
+		 */
+		static JoinConfig down(Class<? extends Entity> source, Class<? extends Entity> target) {
+			return new JoinConfig(source, target, true);
+		}
+
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MeasurementSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MeasurementSearchQuery.java
new file mode 100644
index 0000000..cb162e5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MeasurementSearchQuery.java
@@ -0,0 +1,60 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link Measurement} as source entity
+ * type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class MeasurementSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	MeasurementSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, Measurement.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MergedSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MergedSearchQuery.java
new file mode 100644
index 0000000..1505c50
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/MergedSearchQuery.java
@@ -0,0 +1,135 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.reducing;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.base.search.Searchable;
+
+/**
+ * Merges 2 distinct search queries, where one queries context data as ordered
+ * and the other context as measured.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class MergedSearchQuery implements SearchQuery {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final EntityType entityType;
+
+	private final BaseEntitySearchQuery byResult;
+	private final BaseEntitySearchQuery byOrder;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	MergedSearchQuery(EntityType entityType, Function<ContextState, BaseEntitySearchQuery> factory) {
+		this.entityType = entityType;
+
+		byResult = factory.apply(ContextState.MEASURED);
+		byOrder = factory.apply(ContextState.ORDERED);
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<EntityType> listEntityTypes() {
+		return byOrder.listEntityTypes();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Searchable getSearchableRoot() {
+		return byOrder.getSearchableRoot();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Value> getFilterValues(Attribute attribute, Filter filter) throws DataAccessException {
+		List<Value> orderValues = byOrder.getFilterValues(attribute, filter);
+		List<Value> resultValues = byResult.getFilterValues(attribute, filter);
+
+		return Stream.concat(orderValues.stream(), resultValues.stream())
+				// group by value and merge values
+				.collect(groupingBy(v -> v.extract(), reducing((v1, v2) -> v1)))
+				// collect merged results
+				.values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Result> fetchComplete(List<EntityType> entityTypes, Filter filter) throws DataAccessException {
+		return mergeResults(byOrder.fetchComplete(entityTypes, filter), byResult.fetchComplete(entityTypes, filter));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Result> fetch(List<Attribute> attributes, Filter filter) throws DataAccessException {
+		return mergeResults(byOrder.fetch(attributes, filter), byResult.fetch(attributes, filter));
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Merges given {@link Result}s to one using the root entity type of this search
+	 * query.
+	 *
+	 * @param results1 The first {@code Result}.
+	 * @param results2 The second {@code Result}.
+	 * @return The merged {@link Result} is returned.
+	 */
+	private List<Result> mergeResults(List<Result> results1, List<Result> results2) {
+		return Stream.concat(results1.stream(), results2.stream())
+				// group by instance ID and merge grouped results
+				.collect(groupingBy(r -> r.getRecord(entityType).getID(), reducing(Result::merge)))
+				// collect merged results
+				.values().stream().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearch.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearch.java
new file mode 100644
index 0000000..6a15f28
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearch.java
@@ -0,0 +1,287 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.text.StringEscapeUtils;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * This class handles the requests which are sent to the FreeTextSearch
+ * 
+ * @author Christian Weyermann
+ *
+ */
+public class ODSFreeTextSearch {
+
+	/**
+	 * This is the payload which needs to be added to the post to add a
+	 */
+	private static final String ES_POSTDATA = "{\"_source\": [\"source\", \"type\", \"id\"], \"query\":{\"simple_query_string\":{\"query\":\"%s\",\"default_operator\":\"or\",\"lenient\":\"true\"}}}";
+
+	/**
+	 * mainly logs requests on INFO
+	 */
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSFreeTextSearch.class);
+
+	/**
+	 * Used to finally load the Entites
+	 */
+	private EntityLoader loader;
+
+	/**
+	 * The URL is hard coded
+	 */
+	private URI url;
+
+	/**
+	 * The client is created once and reused
+	 */
+	private HttpClient client;
+
+	/**
+	 * This will start up the FreeText Search. No upfron querries are done. Thus
+	 * this can be called as often as desired without any major performance loss
+	 * 
+	 * @param entityLoader
+	 * @param sourceName
+	 * @throws DataAccessException
+	 */
+	public ODSFreeTextSearch(EntityLoader entityLoader, String sourceName, String host) throws DataAccessException {
+		this.loader = entityLoader;
+
+		url = URI.create(host).resolve(sourceName.toLowerCase()).resolve("/_search");
+
+		client = new HttpClient();
+	}
+
+	/**
+	 * A search which is compatible to the Search as defined in the rest of the API.
+	 * 
+	 * @param inputQuery
+	 * @return never null, but maybe empty
+	 */
+	public Map<Class<? extends Entity>, List<Entity>> search(String inputQuery) {
+		Map<Class<? extends Entity>, List<Entity>> result = new HashMap<>();
+
+		Map<Class<? extends Entity>, List<String>> instances = searchIds(inputQuery);
+		instances.keySet().forEach(type -> convertIds2Entities(result, instances, type));
+		return result;
+	}
+
+	/**
+	 * A search which is compatible to the Search as defined in the rest of the API.
+	 * 
+	 * @param inputQuery
+	 * @return never null, but maybe empty
+	 */
+	public Map<Class<? extends Entity>, List<String>> searchIds(String inputQuery) {
+		Map<Class<? extends Entity>, List<String>> instanceIds = new HashMap<>();
+
+		JsonElement root = queryElasticSearch(inputQuery);
+		if (root != null) {
+			JsonArray hits = root.getAsJsonObject().get("hits").getAsJsonObject().get("hits").getAsJsonArray();
+
+			hits.forEach(e -> put(e, instanceIds));
+
+		}
+		return instanceIds;
+	}
+
+	/**
+	 * Converts all instances to entities
+	 * 
+	 * @param convertedMap it will
+	 * @param map
+	 * @param type
+	 */
+	private void convertIds2Entities(Map<Class<? extends Entity>, List<Entity>> convertedMap,
+			Map<Class<? extends Entity>, List<String>> map, Class<? extends Entity> type) {
+		try {
+			List<Entity> list = new ArrayList<>();
+			list.addAll(loader.loadAll(new Key<>(type), map.get(type)));
+
+			convertedMap.put(type, list);
+		} catch (DataAccessException e) {
+			throw new IllegalStateException("Cannot load ids from ODS. This means no results are available", e);
+		}
+
+	}
+
+	/**
+	 * Puts all the hits in elasticsearch
+	 * 
+	 * @param hit a hit as given from ElasticSearch
+	 * @param map the map of all ids for the class of the entity
+	 */
+	private void put(JsonElement hit, Map<Class<? extends Entity>, List<String>> map) {
+		JsonObject object = hit.getAsJsonObject().get("_source").getAsJsonObject();
+
+		String type = object.get("type").getAsString();
+		Class<? extends Entity> clazz = getClass4Type(type);
+
+		if (clazz != null) {
+			if (!map.containsKey(clazz)) {
+				List<String> list = new ArrayList<>();
+				map.put(clazz, list);
+			}
+
+			List<String> list = map.get(clazz);
+			list.add((String) object.get("id").getAsString());
+		}
+	}
+
+	/**
+	 * 
+	 * @param type the type as given by elasticsearch
+	 * @return the class of each element
+	 */
+	private Class<? extends Entity> getClass4Type(String type) {
+		Class<? extends Entity> clazz;
+		switch (type) {
+		case "Project":
+			clazz = Project.class;
+			break;
+		case "Pool":
+			clazz = Pool.class;
+			break;
+		case "Test":
+			clazz = Test.class;
+			break;
+		case "TestStep":
+			clazz = TestStep.class;
+			break;
+		case "Measurement":
+			clazz = Measurement.class;
+			break;
+
+		default:
+			clazz = null;
+		}
+		return clazz;
+	}
+
+	/**
+	 * This method actually querries ElasticSearch.
+	 * 
+	 * @param inputQuery
+	 * @return
+	 */
+	private JsonElement queryElasticSearch(String inputQuery) {
+		PostMethod post = new PostMethod(url.toString());
+
+		String requestJson = buildRequestJson(inputQuery);
+
+		LOGGER.info("POST: " + url);
+		LOGGER.info("Asking: " + requestJson);
+		byte[] json = requestJson.getBytes();
+		post.setRequestEntity(new ByteArrayRequestEntity(json, "application/json"));
+
+		JsonElement result = execute(post);
+		LOGGER.info("Answered:" + result);
+
+		return result;
+	}
+
+	/**
+	 * Actually builds the json
+	 * 
+	 * @param inputQuery
+	 * @return
+	 */
+	private String buildRequestJson(String inputQuery) {
+		String query = StringEscapeUtils.escapeJson(inputQuery);
+		return String.format(ES_POSTDATA, query);
+	}
+
+	/**
+	 * Executes the HTTP method and expects a json in the return payload, which is
+	 * then returned
+	 * 
+	 * @param method
+	 * @return
+	 */
+	private JsonElement execute(HttpMethod method) {
+		try {
+			int status = client.executeMethod(method);
+			if (status == 404) {
+				return null;
+			}
+
+			checkError(status);
+			return buildResponseJson(method);
+		} catch (IOException e) {
+			throw new IllegalStateException("Problems querying ElasticSearch.", e);
+		}
+	}
+
+	/**
+	 * Reads out the http method and builds the JSON via GSON
+	 * 
+	 * @param method
+	 * @return
+	 * @throws IOException
+	 */
+	private JsonElement buildResponseJson(HttpMethod method) throws IOException {
+		JsonElement res = null;
+
+		InputStream in = method.getResponseBodyAsStream();
+		try (InputStreamReader reader = new InputStreamReader(in)) {
+			res = new JsonParser().parse(reader);
+		}
+
+		return res;
+	}
+
+	/**
+	 * If an error occured an appropriate exception is thrown.
+	 * 
+	 * @param status
+	 */
+	private void checkError(int status) {
+		String text = String.format("ElasticSearch answered %d. ", status);
+
+		if (status / 100 != 2) {
+			throw new IllegalStateException(text);
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java
new file mode 100644
index 0000000..64edfea
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java
@@ -0,0 +1,319 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Environment;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.base.search.Searchable;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+/**
+ * ODS implementation of the {@link SearchService} interface.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+public class ODSSearchService implements SearchService {
+
+	private final Map<Class<? extends Entity>, SearchQuery> searchQueries = new HashMap<>();
+
+	private final ODSContext context;
+	private final EntityLoader entityLoader;
+	private final String esHost;
+	private ODSFreeTextSearch freeTextSearch;
+
+	public static final String PARAM_ELASTIC_SEARCH_URL = "elasticsearch.url";
+
+	/**
+	 * Constructor.
+	 *
+	 * @param context      Used to retrieve {@link ODSModelManager}.
+	 * @param entityLoader Used to load complete {@link Entity}s.
+	 */
+	public ODSSearchService(ODSContext context, QueryService queryService, EntityLoader entityLoader) {
+		this.context = context;
+		this.entityLoader = entityLoader;
+		esHost = context.getParameters().get(PARAM_ELASTIC_SEARCH_URL);
+
+		registerMergedSearchQuery(Project.class,
+				c -> new ProjectSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(Pool.class, c -> new PoolSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(Test.class, c -> new TestSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(TestStep.class,
+				c -> new TestStepSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(Measurement.class,
+				c -> new MeasurementSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(ChannelGroup.class,
+				c -> new ChannelGroupSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(Channel.class,
+				c -> new ChannelSearchQuery(context.getODSModelManager(), queryService, c));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Class<? extends Entity>> listSearchableTypes() {
+		return new ArrayList<>(searchQueries.keySet());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<EntityType> listEntityTypes(Class<? extends Entity> entityClass) {
+		return findSearchQuery(entityClass).listEntityTypes();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Searchable getSearchableRoot(Class<? extends Entity> entityClass) {
+		return findSearchQuery(entityClass).getSearchableRoot();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Value> getFilterValues(Class<? extends Entity> entityClass, Attribute attribute, Filter filter)
+			throws DataAccessException {
+		return findSearchQuery(entityClass).getFilterValues(attribute, filter);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> fetchComplete(Class<T> entityClass, List<EntityType> entityTypes, Filter filter)
+			throws DataAccessException {
+		return createResult(entityClass, findSearchQuery(entityClass).fetchComplete(entityTypes, filter));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public <T extends Entity> List<T> fetch(Class<T> entityClass, List<Attribute> attributes, Filter filter)
+			throws DataAccessException {
+		return createResult(entityClass, findSearchQuery(entityClass).fetch(attributes, filter));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Result> fetchResults(Class<? extends Entity> entityClass, List<Attribute> attributes, Filter filter,
+			String query) throws DataAccessException {
+		Filter mergedFilter = getMergedFilter(filter, query);
+		if (mergedFilter.isEmtpty()) {
+			return Collections.emptyList();
+		}
+
+		EntityType entityType = context.getODSModelManager().getEntityType(entityClass);
+		Map<String, Result> recordsByEntityID = new HashMap<>();
+		for (Result result : findSearchQuery(entityClass).fetch(attributes, mergedFilter)) {
+			recordsByEntityID.put(result.getRecord(entityType).getID(), result);
+		}
+
+		return new ArrayList<>(recordsByEntityID.values());
+	}
+
+	@Override
+	public Map<Class<? extends Entity>, List<Entity>> fetch(String query) throws DataAccessException {
+		if (freeTextSearch == null) {
+			initFreetextSearch();
+		}
+
+		return freeTextSearch.search(query);
+	}
+
+	@Override
+	public boolean isTextSearchAvailable() {
+		return true;
+	}
+
+	/**
+	 * Returns a filter merged from an existing filter and a filter resulting from a
+	 * freetext search result.
+	 * 
+	 * @param filter first filter to merge
+	 * @param query  freetext query, which returns the ids to generate the second
+	 *               filter to merge
+	 * @return conjunction of the first and second filter
+	 * @throws DataAccessException Thrown if {@link ODSFreeTextSearch} is
+	 *                             unavailable or cannot execute the query.
+	 */
+	protected Filter getMergedFilter(Filter filter, String query) throws DataAccessException {
+		Preconditions.checkNotNull(filter, "Filter cannot be null!");
+
+		Filter freetextIdsFilter = getFilterForFreetextQuery(query);
+		// If freetext search query is provided but yields no results, return empty
+		// filter for compatibility with previous behaviour:
+		if (null == freetextIdsFilter) {
+			return Filter.or();
+		} else if (filter.isEmtpty()) {
+			return freetextIdsFilter;
+		} else if (Strings.isNullOrEmpty(query) && freetextIdsFilter.isEmtpty()) {
+			return filter;
+		} else {
+			return Filter.and().merge(filter, freetextIdsFilter);
+		}
+	}
+
+	/**
+	 * Executes a free text search and returns the IDs of the matching entities.
+	 * 
+	 * @param query search query
+	 * @return found entity IDs grouped by entity.
+	 * @throws DataAccessException Thrown if {@link ODSFreeTextSearch} is
+	 *                             unavailable or cannot execute the query.
+	 */
+	protected Map<Class<? extends Entity>, List<String>> fetchIds(String query) throws DataAccessException {
+		if (Strings.isNullOrEmpty(query)) {
+			return Collections.emptyMap();
+		}
+
+		if (freeTextSearch == null) {
+			initFreetextSearch();
+		}
+
+		return freeTextSearch.searchIds(query);
+	}
+
+	/**
+	 * Delegates to {@link ODSFreeTextSearch} to retrieve a map of all entity IDs
+	 * found by the given query. With the results a filter is generated, which can
+	 * be used to query the entity instances of result of the free text query.
+	 * 
+	 * @param query fulltext search query
+	 * @return A map with the found entity IDs grouped by {@link Entity} class or
+	 *         null if a query was provided but yielded no results.
+	 * @throws DataAccessException Thrown if {@link ODSFreeTextSearch} is
+	 *                             unavailable or cannot execute the query.
+	 */
+	protected Filter getFilterForFreetextQuery(String query) throws DataAccessException {
+
+		if (Strings.isNullOrEmpty(query)) {
+			// No query provided => return empty filter for merging with other filters:
+			return Filter.or();
+		}
+
+		Filter freeTextResultsFilter = null;
+		for (Map.Entry<Class<? extends Entity>, List<String>> entry : fetchIds(query).entrySet()) {
+			if (!entry.getValue().isEmpty()) {
+				if (null == freeTextResultsFilter) {
+					freeTextResultsFilter = Filter.or();
+				}
+
+				freeTextResultsFilter.ids(context.getODSModelManager().getEntityType(entry.getKey()), entry.getValue());
+			}
+		}
+
+		return freeTextResultsFilter; // null if query yielded no results
+	}
+
+	/**
+	 * Loads {@link Entity}s of given entity class for given {@link Result}s.
+	 *
+	 * @param <T>         The entity type.
+	 * @param entityClass Entity class of the loaded {@code Entity}s.
+	 * @param results     The queried {@code Result}s.
+	 * @return All loaded entities are returned as a {@link List}.
+	 * @throws DataAccessException Thrown if unable to load the {@code Entity}s.
+	 */
+	private <T extends Entity> List<T> createResult(Class<T> entityClass, List<Result> results)
+			throws DataAccessException {
+		EntityType entityType = context.getODSModelManager().getEntityType(entityClass);
+		Map<String, Result> recordsByEntityID = new HashMap<>();
+		for (Result result : results) {
+			recordsByEntityID.put(result.getRecord(entityType).getID(), result);
+		}
+
+		Map<T, Result> resultsByEntity = new HashMap<>();
+		for (T entity : entityLoader.loadAll(new Key<>(entityClass), recordsByEntityID.keySet())) {
+			resultsByEntity.put(entity, recordsByEntityID.get(entity.getID()));
+		}
+
+		return new ArrayList<>(resultsByEntity.keySet());
+	}
+
+	/**
+	 * Returns the {@link SearchQuery} for given entity class.
+	 *
+	 * @param entityClass Used as identifier.
+	 * @return The {@link SearchQuery}
+	 */
+	private SearchQuery findSearchQuery(Class<? extends Entity> entityClass) {
+		SearchQuery searchQuery = searchQueries.get(entityClass);
+		if (searchQuery == null) {
+			throw new IllegalArgumentException(
+					"Search query for type '" + entityClass.getSimpleName() + "' not found.");
+		}
+
+		return searchQuery;
+	}
+
+	/**
+	 * Registers a {@link SearchQuery} for given entity class.
+	 *
+	 * @param entityClass The entity class produced by using this query.
+	 * @param factory     The {@code SearchQuery} factory.
+	 */
+	private void registerMergedSearchQuery(Class<? extends Entity> entityClass,
+			Function<ContextState, BaseEntitySearchQuery> factory) {
+		searchQueries.put(entityClass,
+				new MergedSearchQuery(context.getODSModelManager().getEntityType(entityClass), factory));
+	}
+
+	private void initFreetextSearch() throws DataAccessException {
+		List<Environment> all = entityLoader.loadAll(new Key<>(Environment.class), "*");
+		if (all.isEmpty()) {
+			throw new DataAccessException("No environment loaded. So the Search does not know where to search");
+		}
+		String sourceName = all.get(0).getSourceName();
+		freeTextSearch = new ODSFreeTextSearch(entityLoader, sourceName, esHost);
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/PoolSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/PoolSearchQuery.java
new file mode 100644
index 0000000..b8a8d03
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/PoolSearchQuery.java
@@ -0,0 +1,59 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link Pool} as source entity type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class PoolSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	PoolSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, Pool.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.down(Pool.class, Test.class));
+		addJoinConfig(JoinConfig.down(Test.class, TestStep.class));
+		addJoinConfig(JoinConfig.down(TestStep.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ProjectSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ProjectSearchQuery.java
new file mode 100644
index 0000000..e5b79d1
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ProjectSearchQuery.java
@@ -0,0 +1,59 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link Project} as source entity type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class ProjectSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	ProjectSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, Project.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.down(Project.class, Pool.class));
+		addJoinConfig(JoinConfig.down(Pool.class, Test.class));
+		addJoinConfig(JoinConfig.down(Test.class, TestStep.class));
+		addJoinConfig(JoinConfig.down(TestStep.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/SearchableNode.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/SearchableNode.java
new file mode 100644
index 0000000..6c8b452
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/SearchableNode.java
@@ -0,0 +1,102 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.search.Searchable;
+
+/**
+ * Implementation of the {@link Searchable} interface for use in search queries
+ * derived from {@link BaseEntitySearchQuery}.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class SearchableNode implements Searchable {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final List<Searchable> relatedSearchables = new ArrayList<>();
+	private final EntityType entityType;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param entityType The associated {@link EntityType}.
+	 */
+	SearchableNode(EntityType entityType) {
+		this.entityType = entityType;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public List<Searchable> getRelatedSearchables() {
+		return Collections.unmodifiableList(relatedSearchables);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public EntityType getEntityType() {
+		return entityType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder("Searchable(").append("EntityType = ").append(entityType);
+
+		if (!isLeaf()) {
+			sb.append(", relatedSearchables = ")
+					.append(relatedSearchables.stream().map(Searchable::getEntityType).collect(Collectors.toList()));
+		}
+
+		return sb.append(')').toString();
+	}
+
+	// ======================================================================
+	// Package methods
+	// ======================================================================
+
+	/**
+	 * Adds given {@link Searchable} as a child to this searchable.
+	 *
+	 * @param searchable Will be added a child.
+	 */
+	void addRelated(Searchable searchable) {
+		relatedSearchables.add(searchable);
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestSearchQuery.java
new file mode 100644
index 0000000..fbc2feb
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestSearchQuery.java
@@ -0,0 +1,59 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link Test} as source entity type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class TestSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	TestSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, Test.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.down(Test.class, TestStep.class));
+		addJoinConfig(JoinConfig.down(TestStep.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestStepSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestStepSearchQuery.java
new file mode 100644
index 0000000..0f632d9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/TestStepSearchQuery.java
@@ -0,0 +1,60 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link TestStep} as source entity
+ * type.
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+final class TestStepSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	TestStepSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, TestStep.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.down(TestStep.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/BaseStatement.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/BaseStatement.java
new file mode 100644
index 0000000..3d9326a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/BaseStatement.java
@@ -0,0 +1,125 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.asam.ods.AoException;
+import org.asam.ods.ApplElemAccess;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+
+/**
+ * A base implementation for execution statements (CREATE, UPDATE, DELETE).
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+abstract class BaseStatement {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ODSTransaction transaction;
+	private final ODSEntityType entityType;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction The owning {@link ODSTransaction}.
+	 * @param entityType  The associated {@link EntityType}.
+	 */
+	protected BaseStatement(ODSTransaction transaction, EntityType entityType) {
+		this.transaction = transaction;
+		this.entityType = (ODSEntityType) entityType;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Executes this statement for given {@link Entity}s.
+	 *
+	 * @param entities The processed {@code Entity}s.
+	 * @throws AoException         Thrown if the execution fails.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 * @throws IOException         Thrown if a file transfer operation fails.
+	 */
+	public abstract void execute(Collection<Entity> entities) throws AoException, DataAccessException, IOException;
+
+	// ======================================================================
+	// Protected methods
+	// ======================================================================
+
+	/**
+	 * Returns the {@link ODSTransaction}.
+	 *
+	 * @return The {@code ODSTransaction} is returned.
+	 */
+	protected ODSTransaction getTransaction() {
+		return transaction;
+	}
+
+	/**
+	 * Returns the {@link ODSModelManager}.
+	 *
+	 * @return The {@code ODSModelManager} is returned.
+	 */
+	protected ODSModelManager getModelManager() {
+		return transaction.getModelManager();
+	}
+
+	/**
+	 * Returns the {@link QueryService}.
+	 *
+	 * @return The {@code QueryService} is returned.
+	 */
+	protected QueryService getQueryService() {
+		return transaction.getContext().getQueryService()
+				.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
+	}
+
+	/**
+	 * Returns the {@link ApplElemAccess}.
+	 *
+	 * @return The {@code ApplElemAccess} is returned.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	protected ApplElemAccess getApplElemAccess() throws AoException {
+		return transaction.getContext().getODSModelManager().getApplElemAccess();
+	}
+
+	/**
+	 * Returns the associated {@link EntityType}.
+	 *
+	 * @return The associated {@code EntityType} is returned.
+	 */
+	protected ODSEntityType getEntityType() {
+		return entityType;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/CatalogManager.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/CatalogManager.java
new file mode 100644
index 0000000..8421b6a
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/CatalogManager.java
@@ -0,0 +1,565 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.asam.ods.AoException;
+import org.asam.ods.ApplicationAttribute;
+import org.asam.ods.ApplicationElement;
+import org.asam.ods.ApplicationRelation;
+import org.asam.ods.ApplicationStructure;
+import org.asam.ods.BaseAttribute;
+import org.asam.ods.BaseElement;
+import org.asam.ods.BaseStructure;
+import org.asam.ods.DataType;
+import org.asam.ods.RelationRange;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
+import org.eclipse.mdm.api.dflt.model.CatalogComponent;
+import org.eclipse.mdm.api.dflt.model.CatalogSensor;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSEnumerations;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+
+/**
+ * Used to create, update or delete {@link CatalogComponent},
+ * {@link CatalogSensor} and {@link CatalogAttribute} entities. Modifications of
+ * the listed types results in modifications of the application model.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class CatalogManager {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ODSTransaction transaction;
+
+	private ApplicationStructure applicationStructure;
+	private BaseStructure baseStructure;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction The {@link ODSTransaction}.
+	 */
+	CatalogManager(ODSTransaction transaction) {
+		this.transaction = transaction;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Creates for each given {@link CatalogComponent} a corresponding application
+	 * element including all required application relations.
+	 *
+	 * @param catalogComponents The {@code CatalogComponent}s.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	public void createCatalogComponents(Collection<CatalogComponent> catalogComponents) throws AoException {
+		Map<ContextType, List<CatalogComponent>> catalogComponentsByContextType = catalogComponents.stream()
+				.collect(Collectors.groupingBy(CatalogComponent::getContextType));
+
+		for (Entry<ContextType, List<CatalogComponent>> entry : catalogComponentsByContextType.entrySet()) {
+			String odsContextTypeName = ODSUtils.CONTEXTTYPES.get(entry.getKey());
+			ApplicationElement contextRootApplicationElement = getApplicationStructure()
+					.getElementByName(odsContextTypeName);
+			BaseElement contextRootBaseElement = contextRootApplicationElement.getBaseElement();
+			ApplicationElement contextTemplateComponentApplicationElement = getApplicationStructure()
+					.getElementByName("Tpl" + odsContextTypeName + "Comp");
+			BaseElement baseElement = getBaseStructure().getElementByType("Ao" + odsContextTypeName + "Part");
+
+			for (CatalogComponent catalogComponent : entry.getValue()) {
+				ApplicationElement applicationElement = createApplicationElement(catalogComponent.getName(),
+						baseElement);
+
+				// relation context root to context component
+				ApplicationRelation applicationRelation = getApplicationStructure().createRelation();
+				applicationRelation.setElem1(contextRootApplicationElement);
+				applicationRelation.setElem2(applicationElement);
+				applicationRelation.setRelationName(catalogComponent.getName());
+				applicationRelation.setInverseRelationName(odsContextTypeName);
+				applicationRelation
+						.setBaseRelation(getBaseStructure().getRelation(contextRootBaseElement, baseElement));
+				applicationRelation._release();
+
+				// relation template component to context component
+				applicationRelation = getApplicationStructure().createRelation();
+				applicationRelation.setElem1(contextTemplateComponentApplicationElement);
+				applicationRelation.setElem2(applicationElement);
+				applicationRelation.setRelationName(catalogComponent.getName());
+				applicationRelation.setInverseRelationName("Tpl" + odsContextTypeName + "Comp");
+				applicationRelation.setRelationRange(new RelationRange((short) 0, (short) -1));
+				applicationRelation.setInverseRelationRange(new RelationRange((short) 1, (short) 1));
+
+				// release resources
+				applicationElement._release();
+				applicationRelation._release();
+			}
+
+			// release resources
+			contextTemplateComponentApplicationElement._release();
+			contextRootApplicationElement._release();
+			contextRootBaseElement._release();
+			baseElement._release();
+		}
+	}
+
+	/**
+	 * Creates for each given {@link CatalogSensor} a corresponding application
+	 * element including all required application relations.
+	 *
+	 * @param catalogSensors The {@code CatalogSensor}s.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	public void createCatalogSensors(Collection<CatalogSensor> catalogSensors) throws AoException {
+		Map<String, List<CatalogSensor>> catalogSensorsByCatalogComponent = catalogSensors.stream()
+				.collect(Collectors.groupingBy(cs -> cs.getCatalogComponent().getName()));
+
+		ApplicationElement channelApplicationElement = getApplicationStructure().getElementByName("MeaQuantity");
+		BaseElement channelBaseElement = channelApplicationElement.getBaseElement();
+
+		for (Entry<String, List<CatalogSensor>> entry : catalogSensorsByCatalogComponent.entrySet()) {
+			ApplicationElement contextComponentApplicationElement = getApplicationStructure()
+					.getElementByName(entry.getKey());
+			BaseElement contextComponentBaseElement = contextComponentApplicationElement.getBaseElement();
+			ApplicationElement contextTemplateSensorApplicationElement = getApplicationStructure()
+					.getElementByName("TplSensor");
+			BaseElement baseElement = getBaseStructure().getElementByType("AoTestEquipmentPart");
+
+			for (CatalogSensor catalogSensor : entry.getValue()) {
+				ApplicationElement applicationElement = createApplicationElement(catalogSensor.getName(), baseElement);
+
+				// relation context component to context sensor
+				ApplicationRelation applicationRelation = getApplicationStructure().createRelation();
+				applicationRelation.setElem1(contextComponentApplicationElement);
+				applicationRelation.setElem2(applicationElement);
+				applicationRelation.setRelationName(catalogSensor.getName());
+				applicationRelation.setInverseRelationName(entry.getKey());
+				applicationRelation
+						.setBaseRelation(getBaseStructure().getRelation(contextComponentBaseElement, baseElement));
+				applicationRelation._release();
+
+				// relation template sensor to context sensor
+				applicationRelation = getApplicationStructure().createRelation();
+				applicationRelation.setElem1(contextTemplateSensorApplicationElement);
+				applicationRelation.setElem2(applicationElement);
+				applicationRelation.setRelationName(catalogSensor.getName());
+				applicationRelation.setInverseRelationName("TplSensor");
+				applicationRelation.setRelationRange(new RelationRange((short) 0, (short) -1));
+				applicationRelation.setInverseRelationRange(new RelationRange((short) 1, (short) 1));
+				applicationRelation._release();
+
+				// relation channel to context sensor
+				applicationRelation = getApplicationStructure().createRelation();
+				applicationRelation.setElem1(channelApplicationElement);
+				applicationRelation.setElem2(applicationElement);
+				applicationRelation.setRelationName(catalogSensor.getName());
+				applicationRelation.setInverseRelationName("MeaQuantity");
+				applicationRelation.setBaseRelation(getBaseStructure().getRelation(channelBaseElement, baseElement));
+
+				// release resources
+				applicationElement._release();
+				applicationRelation._release();
+			}
+
+			// release resources
+			contextComponentApplicationElement._release();
+			contextTemplateSensorApplicationElement._release();
+			contextComponentBaseElement._release();
+			baseElement._release();
+		}
+
+		// release resources
+		channelApplicationElement._release();
+		channelBaseElement._release();
+	}
+
+	/**
+	 * Creates for each given {@link CatalogAttribute} a corresponding application
+	 * attribute.
+	 *
+	 * @param catalogAttributes The {@code CatalogAttribute}s.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	public void createCatalogAttributes(Collection<CatalogAttribute> catalogAttributes) throws AoException {
+		Map<String, List<CatalogAttribute>> catalogAttributesByCatalogComponent = catalogAttributes.stream()
+				.collect(Collectors.groupingBy(CatalogManager::getParentName));
+
+		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByCatalogComponent.entrySet()) {
+			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());
+
+			for (CatalogAttribute catalogAttribute : entry.getValue()) {
+
+				ApplicationAttribute applicationAttribute = applicationElement.createAttribute();
+				DataType dataType = ODSUtils.VALUETYPES.get(catalogAttribute.getValueType());
+				applicationAttribute.setDataType(dataType);
+				applicationAttribute.setName(catalogAttribute.getName());
+				if (dataType == DataType.DT_ENUM) {
+					applicationAttribute.setEnumerationDefinition(getApplicationStructure().getEnumerationDefinition(
+							ODSEnumerations.getEnumName(catalogAttribute.getEnumerationObject())));
+				}
+				Optional<Unit> unit = catalogAttribute.getUnit();
+				if (unit.isPresent()) {
+					applicationAttribute.setUnit(ODSConverter.toODSID(unit.get().getID()));
+				}
+
+				// release resources
+				applicationAttribute._release();
+			}
+
+			// release resources
+			applicationElement._release();
+		}
+	}
+
+	/**
+	 * Updates the application attribute for each given {@link CatalogAttribute}.
+	 *
+	 * @param catalogAttributes The {@code CatalogAttribute}s.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	public void updateCatalogAttributes(List<CatalogAttribute> catalogAttributes) throws AoException {
+		Map<String, List<CatalogAttribute>> catalogAttributesByCatalogComponent = catalogAttributes.stream()
+				.collect(Collectors.groupingBy(CatalogManager::getParentName));
+
+		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByCatalogComponent.entrySet()) {
+			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());
+
+			for (CatalogAttribute catalogAttribute : entry.getValue()) {
+
+				ApplicationAttribute applicationAttribute = applicationElement
+						.getAttributeByName(catalogAttribute.getName());
+
+				Optional<Unit> unit = catalogAttribute.getUnit();
+				if (unit.isPresent()) {
+					applicationAttribute.setUnit(ODSConverter.toODSID(unit.get().getID()));
+				}
+
+				// release resources
+				applicationAttribute._release();
+			}
+
+			// release resources
+			applicationElement._release();
+		}
+	}
+
+	/**
+	 * Deletes the corresponding application element for each given
+	 * {@link CatalogComponent}. Deleting a {@code CatalogComponent} is only allowed
+	 * if it is not used in templates and all of its children could be deleted. So
+	 * at first it is tried to delete its {@link CatalogAttribute}s and
+	 * {@link CatalogSensor}s. On success it is ensured none of the given {@code
+	 * CatalogComponent}s is used in templates. Finally the corresponding
+	 * application elements are deleted.
+	 *
+	 * @param catalogComponents The {@code CatalogComponent}s.
+	 * @throws AoException         Thrown in case of errors.
+	 * @throws DataAccessException Thrown in case of errors.
+	 */
+	public void deleteCatalogComponents(Collection<CatalogComponent> catalogComponents)
+			throws AoException, DataAccessException {
+		List<CatalogAttribute> attributes = new ArrayList<>();
+		List<CatalogSensor> sensors = new ArrayList<>();
+		for (CatalogComponent catalogComponent : catalogComponents) {
+			attributes.addAll(catalogComponent.getCatalogAttributes());
+			sensors.addAll(catalogComponent.getCatalogSensors());
+		}
+		transaction.delete(sensors);
+		transaction.delete(attributes);
+
+		if (areReferencedInTemplates(catalogComponents)) {
+			throw new DataAccessException(
+					"Unable to delete given catalog components since at least " + "one is used in templates.");
+		}
+
+		for (CatalogComponent catalogComponent : catalogComponents) {
+			ApplicationElement applicationElement = getApplicationStructure()
+					.getElementByName(catalogComponent.getName());
+			for (ApplicationRelation applicationRelation : applicationElement.getAllRelations()) {
+				getApplicationStructure().removeRelation(applicationRelation);
+
+				// release resources
+				applicationRelation._release();
+			}
+			getApplicationStructure().removeElement(applicationElement);
+
+			// release resources
+			applicationElement._release();
+		}
+	}
+
+	/**
+	 * Deletes the corresponding application element for each given
+	 * {@link CatalogSensor}. Deleting a {@code CatalogSensor} is only allowed if it
+	 * is not used in templates and all of its children could be deleted. So at
+	 * first it is tried to delete its {@link CatalogAttribute}s. On success it is
+	 * ensured none of the given {@code CatalogSensor}s is used in templates.
+	 * Finally the corresponding application elements are deleted.
+	 *
+	 * @param catalogSensors The {@code CatalogSensor}s.
+	 * @throws AoException         Thrown in case of errors.
+	 * @throws DataAccessException Thrown in case of errors.
+	 */
+	public void deleteCatalogSensors(Collection<CatalogSensor> catalogSensors) throws AoException, DataAccessException {
+		List<CatalogAttribute> attributes = new ArrayList<>();
+		for (CatalogSensor catalogSensor : catalogSensors) {
+			attributes.addAll(catalogSensor.getCatalogAttributes());
+		}
+		transaction.delete(attributes);
+
+		if (areReferencedInTemplates(catalogSensors)) {
+			throw new DataAccessException(
+					"Unable to delete given catalog sensors since at " + "least one is used in templates.");
+		}
+
+		for (CatalogSensor catalogSensor : catalogSensors) {
+			ApplicationElement applicationElement = getApplicationStructure().getElementByName(catalogSensor.getName());
+			for (ApplicationRelation applicationRelation : applicationElement.getAllRelations()) {
+				getApplicationStructure().removeRelation(applicationRelation);
+
+				// release resources
+				applicationRelation._release();
+			}
+			getApplicationStructure().removeElement(applicationElement);
+
+			// release resources
+			applicationElement._release();
+		}
+
+	}
+
+	/**
+	 * Deletes the corresponding application attributes for each given
+	 * {@link CatalogAttribute}. Deleting a {@code CatalogAttribute} is only allowed
+	 * if it is not used in templates. So at first it is ensured none of the given
+	 * {@code CatalogAttribute}s is used in templates and finally the corresponding
+	 * application attributes are deleted.
+	 *
+	 * @param catalogAttributes The {@code CatalogAttribute}s.
+	 * @throws AoException         Thrown in case of errors.
+	 * @throws DataAccessException Thrown in case of errors.
+	 */
+	public void deleteCatalogAttributes(Collection<CatalogAttribute> catalogAttributes)
+			throws AoException, DataAccessException {
+		if (areReferencedInTemplates(catalogAttributes)) {
+			throw new DataAccessException(
+					"Unable to delete given catalog attributes since at least " + "one is used in templates.");
+		}
+
+		Map<String, List<CatalogAttribute>> catalogAttributesByParent = catalogAttributes.stream()
+				.collect(Collectors.groupingBy(CatalogManager::getParentName));
+
+		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByParent.entrySet()) {
+			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());
+
+			for (CatalogAttribute catalogAttribute : entry.getValue()) {
+				ApplicationAttribute applicationAttribute = applicationElement
+						.getAttributeByName(catalogAttribute.getName());
+				applicationElement.removeAttribute(applicationAttribute);
+
+				// release resources
+				applicationAttribute._release();
+			}
+
+			// release resources
+			applicationElement._release();
+		}
+	}
+
+	/**
+	 * Releases cached resources.
+	 */
+	public void clear() {
+		if (applicationStructure != null) {
+			applicationStructure._release();
+		}
+
+		if (baseStructure != null) {
+			baseStructure._release();
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Creates a new {@link ApplicationElement} with given name and
+	 * {@link BaseElement}. The returned {@code ApplicationElement} will be created
+	 * with the three mandatory {@link ApplicationAttribute}s for 'Id', 'Name' and
+	 * 'MimeType'.
+	 *
+	 * @param name        The name of the application element.
+	 * @param baseElement The {@code BaseElement} the created {@code
+	 * 		ApplicationElement} will be derived from.
+	 * @return The created {@code ApplicationElement} is returned.
+	 * @throws AoException Thrown in case of errors.
+	 */
+	private ApplicationElement createApplicationElement(String name, BaseElement baseElement) throws AoException {
+		ApplicationElement applicationElement = getApplicationStructure().createElement(baseElement);
+		applicationElement.setName(name);
+
+		// Id
+		ApplicationAttribute idApplicationAttribute = applicationElement.getAttributeByBaseName("id");
+		idApplicationAttribute.setName("Id");
+		idApplicationAttribute.setDataType(DataType.DT_LONGLONG);
+		idApplicationAttribute.setIsAutogenerated(true);
+
+		// Name
+		ApplicationAttribute nameApplicationAttribute = applicationElement.getAttributeByBaseName("name");
+		nameApplicationAttribute.setName("Name");
+		nameApplicationAttribute.setLength(50);
+
+		// MimeType
+		BaseAttribute mimeTypeBaseAttribute = baseElement.getAttributes("mime_type")[0];
+		ApplicationAttribute mimeTypeApplicationAttribute = applicationElement.createAttribute();
+		mimeTypeApplicationAttribute.setBaseAttribute(mimeTypeBaseAttribute);
+		mimeTypeApplicationAttribute.setName("MimeType");
+		mimeTypeApplicationAttribute.setDataType(DataType.DT_STRING);
+		mimeTypeApplicationAttribute.setLength(256);
+		mimeTypeApplicationAttribute.setIsObligatory(true);
+
+		// release resources
+		idApplicationAttribute._release();
+		nameApplicationAttribute._release();
+		mimeTypeApplicationAttribute._release();
+		mimeTypeBaseAttribute._release();
+
+		return applicationElement;
+	}
+
+	/**
+	 * Returns the cached {@link ApplicationStructure}.
+	 *
+	 * @return The {@code ApplicationStructure} is returned.
+	 * @throws AoException Thrown if unable to access the {@code
+	 * 		ApplicationStructure}.
+	 */
+	private ApplicationStructure getApplicationStructure() throws AoException {
+		if (applicationStructure == null) {
+			applicationStructure = transaction.getModelManager().getAoSession().getApplicationStructure();
+		}
+
+		return applicationStructure;
+	}
+
+	/**
+	 * Returns the cached {@link BaseStructure}.
+	 *
+	 * @return The {@code BaseStructure} is returned.
+	 * @throws AoException Thrown if unable to access the {@code
+	 * 		BaseStructure}.
+	 */
+	private BaseStructure getBaseStructure() throws AoException {
+		if (baseStructure == null) {
+			baseStructure = transaction.getModelManager().getAoSession().getBaseStructure();
+		}
+
+		return baseStructure;
+	}
+
+	/**
+	 * Checks whether given {@link Entity}s are referenced in templates.
+	 *
+	 * @param entities The checked entities ({@link CatalogComponent},
+	 *                 {@link CatalogSensor} or {@link CatalogAttribute}).
+	 * @return Returns {@code true} if at least one entity is referenced in a
+	 *         template.
+	 * @throws AoException         Thrown on errors.
+	 * @throws DataAccessException Thrown on errors.
+	 */
+	private boolean areReferencedInTemplates(Collection<? extends Entity> entities)
+			throws AoException, DataAccessException {
+		Map<EntityType, List<Entity>> entitiesByEntityType = entities.stream()
+				.collect(Collectors.groupingBy(transaction.getModelManager()::getEntityType));
+
+		for (Entry<EntityType, List<Entity>> entry : entitiesByEntityType.entrySet()) {
+			EntityType source = entry.getKey();
+			EntityType target = transaction.getModelManager().getEntityType(source.getName().replace("Cat", "Tpl"));
+
+			Query query = transaction.getContext().getQueryService()
+					.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class)).createQuery()
+					.selectID(target).join(source, target);
+
+			List<Result> results = query.fetch(Filter.and().add(
+					ComparisonOperator.IN_SET.create(source.getIDAttribute(), collectInstanceIDs(entry.getValue()))));
+			if (results.size() > 0) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * Collect the instance IDs of all given {@link Entity}s.
+	 *
+	 * @param entities The {@link Entity}s.
+	 * @return The instance IDs a {@code String[]} are turned.
+	 */
+	private static String[] collectInstanceIDs(List<Entity> entities) {
+		String[] ids = new String[entities.size()];
+
+		for (int i = 0; i < ids.length; i++) {
+			ids[i] = entities.get(i).getID();
+		}
+
+		return ids;
+	}
+
+	/**
+	 * Returns the parent name for given {@link CatalogAttribute}.
+	 *
+	 * @param catalogAttribute The {@code CatalogAttribute}.
+	 * @return The parent name is returned.
+	 */
+	private static String getParentName(CatalogAttribute catalogAttribute) {
+		Optional<CatalogComponent> catalogComponent = catalogAttribute.getCatalogComponent();
+		if (catalogComponent.isPresent()) {
+			return catalogComponent.get().getName();
+		}
+
+		return catalogAttribute.getCatalogSensor()
+				.orElseThrow(() -> new IllegalStateException("Parent entity is unknown.")).getName();
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/DeleteStatement.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/DeleteStatement.java
new file mode 100644
index 0000000..f521967
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/DeleteStatement.java
@@ -0,0 +1,260 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.asam.ods.AoException;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.FilesAttachable;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.ParameterSet;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.JoinType;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delete statement is used to delete entities with their children.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class DeleteStatement extends BaseStatement {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final List<String> AUTO_DELETABLE = Arrays.asList("MeaQuantity", "SubMatrix", "LocalColumn",
+			"ExternalComponent");
+	private static final Logger LOGGER = LoggerFactory.getLogger(DeleteStatement.class);
+
+	private final boolean useAutoDelete;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction   The owning {@link ODSTransaction}.
+	 * @param entityType    The associated {@link EntityType}.
+	 * @param useAutoDelete If {@code true} child relations of {@link Measurement}
+	 *                      entities are not followed.
+	 */
+	DeleteStatement(ODSTransaction transaction, EntityType entityType, boolean useAutoDelete) {
+		super(transaction, entityType);
+		this.useAutoDelete = useAutoDelete;
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void execute(Collection<Entity> entities) throws AoException, DataAccessException {
+		if (entities.stream().filter(e -> !e.getTypeName().equals(getEntityType().getName())).findAny().isPresent()) {
+			throw new IllegalArgumentException("At least one given entity is of incompatible type.");
+		}
+
+		long start = System.currentTimeMillis();
+		int amount = delete(getEntityType(), entities.stream().map(Entity::getID).collect(Collectors.toSet()), false);
+		LOGGER.debug("{} instances deleted in {} ms.", amount, System.currentTimeMillis() - start);
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Recursively follows child relations of given entities and deletes all child
+	 * entities before deleting parent entities.
+	 *
+	 * @param entityType     {@link EntityType} of the deleted entities.
+	 * @param instanceIDs    Instance IDs of entities which have to be deleted.
+	 * @param ignoreSiblings Is it required to check whether {@link Measurement}
+	 *                       siblings share a common {@link ContextRoot}s.
+	 * @return Returns the total number of deleted instances.
+	 * @throws AoException         Thrown if unable to delete entities.
+	 * @throws DataAccessException Thrown if unable to query child entities.
+	 */
+	private int delete(EntityType entityType, Collection<String> instanceIDs, boolean ignoreSiblings)
+			throws AoException, DataAccessException {
+		if (instanceIDs.isEmpty()) {
+			return 0;
+		}
+
+		Query query = getQueryService().createQuery().selectID(entityType);
+		for (Relation relation : entityType.getChildRelations()) {
+			if (useAutoDelete && AUTO_DELETABLE.contains(relation.getTarget().getName())) {
+				continue;
+			}
+
+			if (!relation.getTarget().equals(relation.getSource())) {
+				query.join(relation, JoinType.OUTER).selectID(relation.getTarget());
+			}
+		}
+
+		// select attributes containing file links only for entity types
+		// implementing FilesAttachable
+		EntityConfig<?> entityConfig = getModelManager().getEntityConfig(entityType);
+		if (FilesAttachable.class.isAssignableFrom(entityConfig.getEntityClass())) {
+			entityType.getAttributes().stream().filter(a -> a.getValueType().isFileLinkType()).forEach(query::select);
+		}
+
+		EntityType testStep = getModelManager().getEntityType(TestStep.class);
+		EntityType measurement = getModelManager().getEntityType(Measurement.class);
+		EntityType channel = getModelManager().getEntityType(Channel.class);
+
+		EntityType unitUnderTest = getModelManager().getEntityType(ContextRoot.class, ContextType.UNITUNDERTEST);
+		EntityType testSequence = getModelManager().getEntityType(ContextRoot.class, ContextType.TESTSEQUENCE);
+		EntityType testEquipment = getModelManager().getEntityType(ContextRoot.class, ContextType.TESTEQUIPMENT);
+
+		// type in this list must be deleted AFTER this this instances have been
+		// deleted
+		// informative relation is considered as a child relation
+		List<EntityType> delayedDelete = new ArrayList<>();
+
+		// join context roots
+		if (measurement.equals(entityType) || testStep.equals(entityType)) {
+			query.join(entityType.getRelation(unitUnderTest), JoinType.OUTER).selectID(unitUnderTest);
+			query.join(entityType.getRelation(testSequence), JoinType.OUTER).selectID(testSequence);
+			query.join(entityType.getRelation(testEquipment), JoinType.OUTER).selectID(testEquipment);
+			delayedDelete.addAll(Arrays.asList(unitUnderTest, testSequence, testEquipment));
+		}
+
+		// join parameter sets
+		if (measurement.equals(entityType) || channel.equals(entityType)) {
+			EntityType parameterSet = getModelManager().getEntityType(ParameterSet.class);
+			query.join(entityType.getRelation(parameterSet), JoinType.OUTER).selectID(parameterSet);
+		}
+
+		Filter filter = Filter.or().ids(entityType, instanceIDs);
+		entityType.getParentRelations().stream().filter(r -> r.getTarget().equals(entityType))
+				.forEach(relation -> filter.ids(relation, instanceIDs));
+
+		// query child IDs
+		Map<EntityType, Set<String>> children = new HashMap<>();
+		for (Result result : query.fetch(filter)) {
+			// load children of other types
+			result.stream().filter(r -> r.getID() != null && r.getID().length() > 0).forEach(r -> {
+				children.computeIfAbsent(r.getEntityType(), k -> new HashSet<>()).add(r.getID());
+			});
+
+			// collect file links to remove
+			List<FileLink> fileLinks = new ArrayList<>();
+			for (Value value : result.getRecord(entityType).getValues().values()) {
+				if (value.getValueType().isFileLink()) {
+					fileLinks.add(value.extract());
+				} else if (value.getValueType().isFileLinkSequence()) {
+					fileLinks.addAll(Arrays.asList((FileLink[]) value.extract()));
+				}
+			}
+
+			if (!fileLinks.isEmpty()) {
+				getTransaction().getUploadService().addToRemove(fileLinks);
+			}
+		}
+
+		// omit context roots with references to not removed measurements
+		if (!ignoreSiblings && measurement.equals(entityType)) {
+			for (EntityType contextRoot : Arrays.asList(unitUnderTest, testSequence, testEquipment)) {
+				Set<String> contextRootIDs = children.getOrDefault(contextRoot, Collections.emptySet());
+				if (contextRootIDs.isEmpty()) {
+					continue;
+				}
+
+				Query contextQuery = getQueryService().createQuery();
+				contextQuery.selectID(contextRoot, measurement);
+				contextQuery.join(contextRoot, measurement);
+
+				for (Result result : contextQuery.fetch(Filter.idsOnly(contextRoot, contextRootIDs))) {
+					if (instanceIDs.contains(result.getRecord(measurement).getID())) {
+						continue;
+					}
+
+					// context root references a not removed measurement
+					contextRootIDs.remove(result.getRecord(contextRoot).getID());
+				}
+			}
+		}
+
+		int amount = 0;
+		// delete real children
+		List<Entry<EntityType, Set<String>>> consideredChildren = new ArrayList<>();
+		for (Entry<EntityType, Set<String>> entry : children.entrySet()) {
+			EntityType childType = entry.getKey();
+			Set<String> childInstanceIDs = entry.getValue();
+			if (entityType.equals(childType)) {
+				childInstanceIDs.removeAll(instanceIDs);
+			} else if (delayedDelete.contains(entry.getKey())) {
+				consideredChildren.add(entry);
+				continue;
+			}
+			amount += delete(entry.getKey(), childInstanceIDs, true);
+		}
+
+		getApplElemAccess().deleteInstances(((ODSEntityType) entityType).getODSID(), toODSIDs(instanceIDs));
+
+		// delete considered children (informative relation)
+		for (Entry<EntityType, Set<String>> entry : consideredChildren) {
+			amount += delete(entry.getKey(), entry.getValue(), true);
+		}
+
+		return amount + instanceIDs.size();
+	}
+
+	/**
+	 * Converts given {@code Collection} of instance IDs to ODS a {@link T_LONGLONG}
+	 * array.
+	 *
+	 * @param instanceIDs The instance IDs.
+	 * @return The corresponding ODS {@code T_LONGLONG[]} is returned.
+	 */
+	private T_LONGLONG[] toODSIDs(Collection<String> instanceIDs) {
+		return instanceIDs.stream().map(ODSConverter::toODSID).toArray(T_LONGLONG[]::new);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java
new file mode 100644
index 0000000..2a54ac5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/InsertStatement.java
@@ -0,0 +1,282 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.asam.ods.AIDName;
+import org.asam.ods.AIDNameValueSeqUnitId;
+import org.asam.ods.AoException;
+import org.asam.ods.ElemId;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.Sortable;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Insert statement is used to write new entities and their children.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class InsertStatement extends BaseStatement {
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(InsertStatement.class);
+
+	private final Map<Class<? extends Entity>, List<Entity>> childrenMap = new HashMap<>();
+	private final List<Core> cores = new ArrayList<>();
+	private final Map<String, List<Value>> insertMap = new HashMap<>();
+
+	private final List<FileLink> fileLinkToUpload = new ArrayList<>();
+
+	private final Map<String, SortIndexTestSteps> sortIndexTestSteps = new HashMap<>();
+	private boolean loadSortIndex;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction The owning {@link ODSTransaction}.
+	 * @param entityType  The associated {@link EntityType}.
+	 */
+	InsertStatement(ODSTransaction transaction, EntityType entityType) {
+		super(transaction, entityType);
+
+		loadSortIndex = getModelManager().getEntityType(TestStep.class).equals(getEntityType());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void execute(Collection<Entity> entities) throws AoException, DataAccessException, IOException {
+		entities.stream().map(ODSEntityFactory::extract).forEach(this::readEntityCore);
+		execute();
+	}
+
+	/**
+	 * Executes this statement for given {@link Core}s.
+	 *
+	 * @param cores The processed {@code Core}s.
+	 * @throws AoException         Thrown if the execution fails.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 * @throws IOException         Thrown if a file transfer operation fails.
+	 */
+	public void executeWithCores(Collection<Core> cores) throws AoException, DataAccessException, IOException {
+		cores.forEach(this::readEntityCore);
+		execute();
+	}
+
+	/**
+	 * Uploads new {@link FileLink}s, adjusts sort indices for new {@link TestStep}
+	 * entities and writes collected insertion data at once. Once new entities are
+	 * written their children are created by delegation to the
+	 * {@link ODSTransaction}.
+	 *
+	 * @throws AoException         Thrown if the execution fails.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 * @throws IOException         Thrown if a file transfer operation fails.
+	 */
+	private void execute() throws AoException, DataAccessException, IOException {
+		List<AIDNameValueSeqUnitId> anvsuList = new ArrayList<>();
+		T_LONGLONG aID = getEntityType().getODSID();
+
+		// TODO tracing progress in this method...
+
+		if (loadSortIndex && !sortIndexTestSteps.isEmpty()) {
+			adjustMissingSortIndices();
+		}
+
+		if (!fileLinkToUpload.isEmpty()) {
+			getTransaction().getUploadService().uploadParallel(fileLinkToUpload, null);
+		}
+
+		for (Entry<String, List<Value>> entry : insertMap.entrySet()) {
+			Attribute attribute = getEntityType().getAttribute(entry.getKey());
+
+			AIDNameValueSeqUnitId anvsu = new AIDNameValueSeqUnitId();
+			anvsu.attr = new AIDName(aID, entry.getKey());
+			anvsu.unitId = ODSConverter.toODSLong(0);
+			anvsu.values = ODSConverter.toODSValueSeq(attribute, entry.getValue());
+			anvsuList.add(anvsu);
+		}
+
+		long start = System.currentTimeMillis();
+		ElemId[] elemIds = getApplElemAccess()
+				.insertInstances(anvsuList.toArray(new AIDNameValueSeqUnitId[anvsuList.size()]));
+		for (int i = 0; i < elemIds.length; i++) {
+			cores.get(i).setID(Long.toString(ODSConverter.fromODSLong(elemIds[i].iid)));
+		}
+		long stop = System.currentTimeMillis();
+
+		LOGGER.debug("{} " + getEntityType() + " instances created in {} ms.", elemIds.length, stop - start);
+
+		for (List<Entity> children : childrenMap.values()) {
+			getTransaction().create(children);
+		}
+	}
+
+	/**
+	 * Reads given {@link Core} and prepares its data to be written:
+	 *
+	 * <ul>
+	 * <li>collect new {@link FileLink}s</li>
+	 * <li>trace missing sort indices of TestSteps</li>
+	 * <li>collect property {@link Value}s</li>
+	 * <li>collect foreign key {@code Value}s</li>
+	 * <li>collect child entities for recursive creation</li>
+	 * </ul>
+	 *
+	 * @param core The {@code Core}.
+	 */
+	private void readEntityCore(Core core) {
+		if (!core.getTypeName().equals(getEntityType().getName())) {
+			throw new IllegalArgumentException("Entity core '" + core.getTypeName()
+					+ "' is incompatible with current insert statement for entity type '" + getEntityType() + "'.");
+		}
+
+		cores.add(core);
+
+		if (loadSortIndex) {
+			if ((Integer) core.getValues().get(Sortable.ATTR_SORT_INDEX).extract() < 0) {
+				sortIndexTestSteps.computeIfAbsent(core.getPermanentStore().get(Test.class).getID(),
+						k -> new SortIndexTestSteps()).testStepCores.add(core);
+			}
+		}
+
+		// add all entity values
+		for (Value value : core.getAllValues().values()) {
+			insertMap.computeIfAbsent(value.getName(), k -> new ArrayList<>()).add(value);
+		}
+
+		// collect file links
+		fileLinkToUpload.addAll(core.getAddedFileLinks());
+
+		// define "empty" values for informative relations
+		for (Relation relation : getEntityType().getInfoRelations()) {
+			insertMap.computeIfAbsent(relation.getName(), k -> new ArrayList<>()).add(relation.createValue());
+		}
+
+		// define "empty" values for parent relations
+		for (Relation relation : getEntityType().getParentRelations()) {
+			insertMap.computeIfAbsent(relation.getName(), k -> new ArrayList<>()).add(relation.createValue());
+		}
+
+		// replace "empty" relation values with corresponding instance IDs
+		setRelationIDs(core.getMutableStore().getCurrent());
+		setRelationIDs(core.getPermanentStore().getCurrent());
+
+		for (Entry<Class<? extends Deletable>, List<? extends Deletable>> entry : core.getChildrenStore().getCurrent()
+				.entrySet()) {
+			childrenMap.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(entry.getValue());
+		}
+
+		getTransaction().addModified(core);
+		getTransaction().addCreated(core);
+	}
+
+	/**
+	 * Overwrites empty foreign key {@link Value} containers.
+	 *
+	 * @param relatedEntities The related {@link Entity}s.
+	 */
+	private void setRelationIDs(Collection<Entity> relatedEntities) {
+		for (Entity relatedEntity : relatedEntities) {
+			if (!ODSUtils.isValidID(relatedEntity.getID())) {
+				throw new IllegalArgumentException("Related entity must be a persited entity.");
+			}
+
+			Relation relation = getEntityType().getRelation(getModelManager().getEntityType(relatedEntity));
+			List<Value> relationValues = insertMap.get(relation.getName());
+			if (relationValues == null) {
+				throw new IllegalStateException("Relation '" + relation + "' is incompatible with insert statement "
+						+ "for entity type '" + getEntityType() + "'");
+			}
+			relationValues.get(relationValues.size() - 1).set(relatedEntity.getID());
+		}
+	}
+
+	/**
+	 * Adjusts missing sort indices for {@link TestStep}s by querying last used max
+	 * sort index.
+	 *
+	 * @throws DataAccessException Thrown if unable to query used sort indices.
+	 */
+	private void adjustMissingSortIndices() throws DataAccessException {
+		EntityType testStep = getEntityType();
+		EntityType test = getModelManager().getEntityType(Test.class);
+		Relation parentRelation = testStep.getRelation(test);
+
+		Attribute attrSortIndex = testStep.getAttribute(Sortable.ATTR_SORT_INDEX);
+		Query query = getQueryService().createQuery().select(parentRelation.getAttribute())
+				.select(attrSortIndex, Aggregation.MAXIMUM).group(parentRelation.getAttribute());
+
+		Filter filter = Filter.idsOnly(parentRelation, sortIndexTestSteps.keySet());
+		for (Result result : query.fetch(filter)) {
+			Record record = result.getRecord(testStep);
+			int sortIndex = result.getValue(attrSortIndex, Aggregation.MAXIMUM).extract();
+			sortIndexTestSteps.remove(record.getID(parentRelation).get()).setIndices(sortIndex + 1);
+		}
+
+		// start at 1 for all remaining
+		sortIndexTestSteps.values().forEach(tss -> tss.setIndices(0));
+	}
+
+	/**
+	 * Utility class to write missing sort index of new {@link TestStep}s.
+	 */
+	private static final class SortIndexTestSteps {
+
+		private List<Core> testStepCores = new ArrayList<>();
+
+		/**
+		 * Assigns sort indices to {@link Core}s starting at given index.
+		 *
+		 * @param startIndex The start index.
+		 */
+		private void setIndices(int startIndex) {
+			int index = startIndex;
+			for (Core core : testStepCores) {
+				core.getValues().get(Sortable.ATTR_SORT_INDEX).set(index++);
+			}
+		}
+
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java
new file mode 100644
index 0000000..94825b7
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/ODSTransaction.java
@@ -0,0 +1,548 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.asam.ods.AoException;
+import org.asam.ods.ElemId;
+import org.asam.ods.SetType;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.massdata.WriteRequest;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.ScalarType;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
+import org.eclipse.mdm.api.dflt.model.CatalogComponent;
+import org.eclipse.mdm.api.dflt.model.CatalogSensor;
+import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ODS implementation of the {@link Transaction} interface.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSTransaction implements Transaction {
+
+	// TODO: it should be possible to a attach a progress listener
+	// -> progress notification updates while uploading files
+	// -> any other useful informations?!
+	// -> splitting of tasks into subtasks may be required...
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSTransaction.class);
+
+	// this one is stored in case of application model modifications
+	private final ODSContext parentContext;
+
+	// this one is used to access the application model and execute queries
+	// instance is decoupled from its parent
+	private final ODSContext context;
+
+	// only for logging
+	private final String id = UUID.randomUUID().toString();
+
+	// need to write version == instanceID -> update after create
+	private final List<ContextRoot> contextRoots = new ArrayList<>();
+
+	// reset instance IDs on abort
+	private final List<Core> created = new ArrayList<>();
+
+	// apply changes
+	private final List<Core> modified = new ArrayList<>();
+
+	private final Entity entity;
+	private final Transfer transfer;
+
+	private UploadService uploadService;
+
+	private CatalogManager catalogManager;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param parentModelManager Used to access the persistence.
+	 * @param entity             Used for security checks
+	 * @param transfer           The file transfer type.
+	 * @throws AoException Thrown if unable to start a co-session.
+	 */
+	public ODSTransaction(ODSContext parentContext, Entity entity, Transfer transfer) throws AoException {
+		this.parentContext = parentContext;
+		this.entity = entity;
+		this.transfer = transfer;
+		context = parentContext.newContext();
+		context.getAoSession().startTransaction();
+		LOGGER.debug("Transaction '{}' started.", id);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	@SuppressWarnings("unchecked")
+	public <T extends Entity> void create(Collection<T> entities) throws DataAccessException {
+		if (entities.isEmpty()) {
+			return;
+		} else if (entities.stream().filter(e -> ODSUtils.isValidID(e.getID())).findAny().isPresent()) {
+			throw new IllegalArgumentException("At least one given entity is already persisted.");
+		}
+
+		try {
+			Map<Class<?>, List<T>> entitiesByClassType = entities.stream()
+					.collect(Collectors.groupingBy(e -> e.getClass()));
+
+			List<CatalogComponent> catalogComponents = (List<CatalogComponent>) entitiesByClassType
+					.get(CatalogComponent.class);
+			if (catalogComponents != null) {
+				getCatalogManager().createCatalogComponents(catalogComponents);
+			}
+
+			List<CatalogSensor> catalogSensors = (List<CatalogSensor>) entitiesByClassType.get(CatalogSensor.class);
+			if (catalogSensors != null) {
+				// TODO anehmer on 2017-11-16: avalon 4.3b throws an exception in
+				// AoSession.commitTransaction() if multiple
+				// catalog sensors have been deleted and leaves the application
+				// model in a broken state. This is also stated in the documentation. This
+				// comment should be removed later.
+				getCatalogManager().createCatalogSensors(catalogSensors);
+			}
+
+			List<CatalogAttribute> catalogAttributes = (List<CatalogAttribute>) entitiesByClassType
+					.get(CatalogAttribute.class);
+			if (catalogAttributes != null) {
+				getCatalogManager().createCatalogAttributes(catalogAttributes);
+			}
+
+			List<TemplateAttribute> templateAttributes = (List<TemplateAttribute>) entitiesByClassType
+					.get(TemplateAttribute.class);
+			if (templateAttributes != null) {
+				List<TemplateAttribute> filtered = getFileLinkTemplateAttributes(templateAttributes);
+				if (!filtered.isEmpty()) {
+					getUploadService().upload(filtered, null);
+				}
+			}
+
+			List<TestStep> testSteps = (List<TestStep>) entitiesByClassType.get(TestStep.class);
+			if (testSteps != null) {
+				create(testSteps.stream().map(ContextRoot::of).collect(ArrayList::new, List::addAll, List::addAll));
+			}
+
+			List<Measurement> measurements = (List<Measurement>) entitiesByClassType.get(Measurement.class);
+			if (measurements != null) {
+				// Use set here, since measurement siblings point to the same
+				// context roots. Only create those ContextRoots that haven't been created yet:
+				create(measurements.stream().map(ContextRoot::of)
+						.collect(HashSet<ContextRoot>::new, Set<ContextRoot>::addAll, Set<ContextRoot>::addAll).stream()
+						.filter(cr -> !ODSUtils.isValidID(cr.getID())).collect(Collectors.toSet()));
+			}
+
+			executeStatements(et -> new InsertStatement(this, et), entities);
+			processNtoMRelations(entities);
+
+			List<ContextRoot> roots = (List<ContextRoot>) entitiesByClassType.get(ContextRoot.class);
+			if (roots != null) {
+				roots.forEach(contextRoot -> {
+					contextRoot.setVersion(contextRoot.getID().toString());
+				});
+
+				// this will restore the ASAM path of each context root
+				executeStatements(et -> new UpdateStatement(this, et, true), roots);
+				contextRoots.addAll(roots);
+			}
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to write new entities due to: " + e.reason, e);
+		} catch (IOException e) {
+			throw new DataAccessException("Unable to write new entities due to: " + e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	@SuppressWarnings("unchecked")
+	public <T extends Entity> void update(Collection<T> entities) throws DataAccessException {
+		if (entities.isEmpty()) {
+			return;
+		} else if (entities.stream().filter(e -> !ODSUtils.isValidID(e.getID())).findAny().isPresent()) {
+			throw new IllegalArgumentException("At least one given entity is not yet persisted.");
+		}
+
+		try {
+			Map<Class<?>, List<T>> entitiesByClassType = entities.stream()
+					.collect(Collectors.groupingBy(e -> e.getClass()));
+			List<CatalogAttribute> catalogAttributes = (List<CatalogAttribute>) entitiesByClassType
+					.get(CatalogAttribute.class);
+			if (catalogAttributes != null) {
+				getCatalogManager().updateCatalogAttributes(catalogAttributes);
+			}
+
+			List<TemplateAttribute> templateAttributes = (List<TemplateAttribute>) entitiesByClassType
+					.get(TemplateAttribute.class);
+			if (templateAttributes != null) {
+				List<TemplateAttribute> filtered = getFileLinkTemplateAttributes(templateAttributes);
+				if (!filtered.isEmpty()) {
+					getUploadService().upload(filtered, null);
+				}
+			}
+			executeStatements(et -> new UpdateStatement(this, et, false), entities);
+			processNtoMRelations(entities);
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to update entities due to: " + e.reason, e);
+		} catch (IOException e) {
+			throw new DataAccessException("Unable to update entities due to: " + e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	@SuppressWarnings("unchecked")
+	public <T extends Deletable> void delete(Collection<T> entities) throws DataAccessException {
+		if (entities.isEmpty()) {
+			return;
+		}
+
+		List<T> filteredEntities = entities.stream().filter(e -> ODSUtils.isValidID(e.getID()))
+				.collect(Collectors.toList());
+
+		try {
+			Map<Class<?>, List<T>> entitiesByClassType = filteredEntities.stream()
+					.collect(Collectors.groupingBy(e -> e.getClass()));
+
+			List<CatalogComponent> catalogComponents = (List<CatalogComponent>) entitiesByClassType
+					.get(CatalogComponent.class);
+			if (catalogComponents != null) {
+				getCatalogManager().deleteCatalogComponents(catalogComponents);
+			}
+
+			List<CatalogSensor> catalogSensors = (List<CatalogSensor>) entitiesByClassType.get(CatalogSensor.class);
+			if (catalogSensors != null) {
+				// TODO anehmer on 2017-11-16: avalon 4.3b throws an exception in
+				// AoSession.commitTransaction() if multiple
+				// catalog sensors have been deleted and leaves the application
+				// model in a broken state. This is also stated in the documentation. This
+				// comment should be removed later.
+				getCatalogManager().deleteCatalogSensors(catalogSensors);
+			}
+
+			List<CatalogAttribute> catalogAttributes = (List<CatalogAttribute>) entitiesByClassType
+					.get(CatalogAttribute.class);
+			if (catalogAttributes != null) {
+				getCatalogManager().deleteCatalogAttributes(catalogAttributes);
+			}
+
+			/*
+			 * TODO: for any template that has to be deleted it is required to ensure there
+			 * are no links to it...
+			 */
+
+			executeStatements(et -> new DeleteStatement(this, et, true), filteredEntities);
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to delete entities due to: " + e.reason, e);
+		} catch (IOException e) {
+			throw new DataAccessException("Unable to delete entities due to: " + e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void writeMeasuredValues(Collection<WriteRequest> writeRequests) throws DataAccessException {
+		if (writeRequests.isEmpty()) {
+			return;
+		}
+
+		try {
+			Map<ScalarType, List<WriteRequest>> writeRequestsByRawType = writeRequests.stream()
+					.collect(Collectors.groupingBy(WriteRequest::getRawScalarType));
+
+			for (List<WriteRequest> writeRequestGroup : writeRequestsByRawType.values()) {
+				WriteRequestHandler writeRequestHandler = new WriteRequestHandler(this);
+				List<Channel> channels = new ArrayList<>();
+
+				for (WriteRequest writeRequest : writeRequestGroup) {
+					Channel channel = writeRequest.getChannel();
+					channel.setScalarType(writeRequest.getCalculatedScalarType());
+					// TODO it might be required to change relation to another
+					// unit?!??
+					channels.add(channel);
+					writeRequestHandler.addRequest(writeRequest);
+				}
+
+				update(channels);
+				writeRequestHandler.execute();
+			}
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to write measured values due to: " + e.reason, e);
+		} catch (IOException e) {
+			throw new DataAccessException("Unable to write measured values due to: " + e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void commit() throws DataAccessException {
+		try {
+			context.getAoSession().commitTransaction();
+
+			// commit succeed -> apply changes in entity cores
+			modified.forEach(Core::apply);
+
+			// remove deleted remote files
+			if (uploadService != null) {
+				uploadService.commit();
+			}
+
+			if (catalogManager != null) {
+				// application model has been modified -> reload
+				parentContext.getODSModelManager().reloadApplicationModel();
+			}
+
+			LOGGER.debug("Transaction '{}' committed.", id);
+			closeSession();
+		} catch (AoException e) {
+			throw new DataAccessException("Unable to commit transaction '" + id + "' due to: " + e.reason, e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void abort() {
+		try {
+			if (uploadService != null) {
+				uploadService.abort();
+			}
+
+			// reset version, since creation failed or was aborted
+			contextRoots.forEach(cr -> cr.setVersion(null));
+
+			// reset instance IDs
+			String virtualID = "0";
+			created.forEach(c -> c.setID(virtualID));
+
+			context.getAoSession().abortTransaction();
+
+			LOGGER.debug("Transaction '{}' aborted.", id);
+		} catch (AoException e) {
+			LOGGER.error("Unable to abort transaction '" + id + "' due to: " + e.reason, e);
+		} finally {
+			closeSession();
+		}
+	}
+
+	/**
+	 * Once {@link #abort()} is called instance ID of given {@link Core} will be
+	 * reset to {@code 0} which indicates a virtual {@link Entity}, not yet
+	 * persisted, entity.
+	 *
+	 * @param core The {@code Core} of a newly written {@code Entity}.
+	 */
+	void addCreated(Core core) {
+		created.add(core);
+	}
+
+	/**
+	 * Once {@link #commit()} is {@link Core#apply()} will be called to apply
+	 * modified {@link Value} contents and removed related entities.
+	 *
+	 * @param core The {@code Core} of an updated {@code Entity}.
+	 */
+	void addModified(Core core) {
+		modified.add(core);
+	}
+
+	/**
+	 * Returns the {@link ODSContext}.
+	 *
+	 * @return The {@code ODSContext} is returned.
+	 */
+	ODSContext getContext() {
+		return context;
+	}
+
+	/**
+	 * Returns the {@link ODSModelManager}.
+	 *
+	 * @return The {@code ODSModelManager} is returned.
+	 */
+	ODSModelManager getModelManager() {
+		return context.getODSModelManager();
+	}
+
+	/**
+	 * Returns the {@link UploadService}.
+	 *
+	 * @return The {@code UploadService} is returned.
+	 * @throws DataAccessException Thrown if file transfer is not possible.
+	 */
+	UploadService getUploadService() throws DataAccessException {
+		if (uploadService == null) {
+			if (context.getFileServer() == null) {
+				throw new DataAccessException("CORBA file server is not available.");
+			}
+
+			// upload service starts a periodic session refresh task -> lazy
+			// instantiation
+			uploadService = new UploadService(context, entity, transfer);
+		}
+
+		return uploadService;
+	}
+
+	/**
+	 * Returns the {@link CatalogManager}.
+	 *
+	 * @return The {@code CatalogManager} is returned.
+	 */
+	private CatalogManager getCatalogManager() {
+		if (catalogManager == null) {
+			catalogManager = new CatalogManager(this);
+		}
+
+		return catalogManager;
+	}
+
+	/**
+	 * Collects {@link TemplateAttribute}s with a valid default {@link Value} of
+	 * type {@link ValueType#FILE_LINK} or {@link ValueType#FILE_LINK_SEQUENCE}.
+	 *
+	 * @param templateAttributes The processed {@code TemplateAttribute}s.
+	 * @return Returns {@link TemplateAttribute} which have {@link FileLink}s stored
+	 *         as default {@code Value}.
+	 */
+	private List<TemplateAttribute> getFileLinkTemplateAttributes(List<TemplateAttribute> templateAttributes) {
+		return templateAttributes.stream().filter(ta -> {
+			Value value = ta.getDefaultValue();
+			return value.getValueType().isFileLinkType() && value.isValid();
+		}).collect(Collectors.toList());
+	}
+
+	/**
+	 * Executes statements for given entities by using given statement factory.
+	 *
+	 * @param <T>              The entity type.
+	 * @param statementFactory Used to create a new statement for a given
+	 *                         {@link EntityType}.
+	 * @param entities         The processed {@code Entity}s.
+	 * @throws AoException         Thrown if the execution fails.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 * @throws IOException         Thrown if a file transfer operation fails.
+	 */
+	private <T extends Entity> void executeStatements(Function<EntityType, BaseStatement> statementFactory,
+			Collection<T> entities) throws AoException, DataAccessException, IOException {
+		Map<EntityType, List<Entity>> entitiesByType = entities.stream()
+				.collect(Collectors.groupingBy(context.getODSModelManager()::getEntityType));
+		for (Entry<EntityType, List<Entity>> entry : entitiesByType.entrySet()) {
+			statementFactory.apply(entry.getKey()).execute(entry.getValue());
+		}
+	}
+
+	/**
+	 * Processes N-to-M relations for the given entities
+	 * 
+	 * @param entities The processed {@code Entity}s.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 */
+	private <T extends Entity> void processNtoMRelations(Collection<T> entities) {
+		for (Entity e : entities) {
+			context.getODSModelManager().getEntityType(e).getRelations().stream().filter(Relation::isNtoM)
+					.forEach(r -> processMtoMRelation(e, r));
+		}
+	}
+
+	private void processMtoMRelation(Entity entity, Relation relation) {
+
+		List<? extends Deletable> removedRelatedEntities = ODSEntityFactory.extract(entity).getNtoMStore().getRemoved()
+				.getOrDefault(relation.getName(), Collections.emptyList());
+		List<? extends Deletable> addedRelatedEntities = ODSEntityFactory.extract(entity).getNtoMStore().getAdded()
+				.getOrDefault(relation.getName(), Collections.emptyList());
+
+		T_LONGLONG[] removedInstIds = removedRelatedEntities.stream().map(Entity::getID).map(ODSConverter::toODSID)
+				.toArray(T_LONGLONG[]::new);
+
+		T_LONGLONG[] addedInstIds = addedRelatedEntities.stream().map(Entity::getID).map(ODSConverter::toODSID)
+				.toArray(T_LONGLONG[]::new);
+
+		try {
+			if (removedInstIds.length > 0) {
+				ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity));
+				ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID()));
+				context.getAoSession().getApplElemAccess().setRelInst(elemId, relation.getName(), removedInstIds,
+						SetType.REMOVE);
+			}
+
+			if (addedInstIds.length > 0) {
+				ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity));
+				ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID()));
+				context.getAoSession().getApplElemAccess().setRelInst(elemId, relation.getName(), addedInstIds,
+						SetType.APPEND);
+			}
+		} catch (AoException e) {
+			throw new DataAccessException("" + e.reason, e); // TODO
+		}
+	}
+
+	/**
+	 * Closes the co-session of this transaction.
+	 */
+	private void closeSession() {
+		if (catalogManager != null) {
+			catalogManager.clear();
+		}
+
+		context.close();
+		LOGGER.debug("Transaction '{}' closed.", id);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java
new file mode 100644
index 0000000..85622b5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UpdateStatement.java
@@ -0,0 +1,269 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+import org.asam.ods.AIDName;
+import org.asam.ods.AIDNameValueSeqUnitId;
+import org.asam.ods.AoException;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.Relation;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.FilesAttachable;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.dflt.model.Role;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Insert statement is used to update entities and their children.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class UpdateStatement extends BaseStatement {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(UpdateStatement.class);
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final Map<Class<? extends Entity>, List<Entity>> childrenToCreate = new HashMap<>();
+	private final Map<Class<? extends Entity>, List<Entity>> childrenToUpdate = new HashMap<>();
+	private final Map<Class<? extends Deletable>, List<Deletable>> childrenToRemove = new HashMap<>();
+	private Map<String, List<Value>> updateMap = new HashMap<>();
+
+	private final List<FileLink> fileLinkToUpload = new ArrayList<>();
+	private final List<String> nonUpdatableRelationNames;
+	private final boolean ignoreChildren;
+	private final boolean isFilesAttachable;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction    The owning {@link ODSTransaction}.
+	 * @param entityType     The associated {@link EntityType}.
+	 * @param ignoreChildren If {@code true}, then child entities won't be
+	 *                       processed.
+	 */
+	UpdateStatement(ODSTransaction transaction, EntityType entityType, boolean ignoreChildren) {
+		super(transaction, entityType);
+
+		nonUpdatableRelationNames = entityType.getInfoRelations().stream().map(Relation::getName)
+				.collect(Collectors.toList());
+		this.ignoreChildren = ignoreChildren;
+
+		EntityConfig<?> entityConfig = getModelManager().getEntityConfig(getEntityType());
+		isFilesAttachable = FilesAttachable.class.isAssignableFrom(entityConfig.getEntityClass());
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void execute(Collection<Entity> entities) throws AoException, DataAccessException, IOException {
+		for (Entity entity : entities) {
+			readEntityCore(ODSEntityFactory.extract(entity));
+		}
+
+		// TODO tracing progress in this method...
+
+		List<AIDNameValueSeqUnitId> anvsuList = new ArrayList<>();
+		T_LONGLONG aID = getEntityType().getODSID();
+
+		if (!fileLinkToUpload.isEmpty()) {
+			getTransaction().getUploadService().uploadParallel(fileLinkToUpload, null);
+		}
+
+		for (Entry<String, List<Value>> entry : updateMap.entrySet()) {
+			if (nonUpdatableRelationNames.contains(entry.getKey())) {
+				// skip "empty" informative relation sequence
+				continue;
+			}
+			if (entry.getKey().equalsIgnoreCase(Role.ATTR_SUPERUSER_FLAG)) {
+				// skip superuser flag as it cannot be written through the ODS API
+				continue;
+			}
+
+			Attribute attribute = getEntityType().getAttribute(entry.getKey());
+
+			AIDNameValueSeqUnitId anvsu = new AIDNameValueSeqUnitId();
+			anvsu.attr = new AIDName(aID, entry.getKey());
+			anvsu.unitId = ODSConverter.toODSLong(0);
+			anvsu.values = ODSConverter.toODSValueSeq(attribute, entry.getValue());
+			anvsuList.add(anvsu);
+		}
+
+		long start = System.currentTimeMillis();
+		getApplElemAccess().updateInstances(anvsuList.toArray(new AIDNameValueSeqUnitId[anvsuList.size()]));
+		long stop = System.currentTimeMillis();
+
+		LOGGER.debug("{} " + getEntityType() + " instances updated in {} ms.", entities.size(), stop - start);
+
+		// delete first to make sure naming collisions do not occur!
+		for (List<Deletable> children : childrenToRemove.values()) {
+			getTransaction().delete(children);
+		}
+		for (List<Entity> children : childrenToCreate.values()) {
+			getTransaction().create(children);
+		}
+		for (List<Entity> children : childrenToUpdate.values()) {
+			getTransaction().update(children);
+		}
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Reads given {@link Core} and prepares its data to be written:
+	 *
+	 * <ul>
+	 * <li>collect new and removed {@link FileLink}s</li>
+	 * <li>collect property {@link Value}s</li>
+	 * <li>collect foreign key {@code Value}s</li>
+	 * <li>collect child entities for recursive create/update/delete</li>
+	 * </ul>
+	 *
+	 * @param core The {@code Core}.
+	 * @throws DataAccessException Thrown in case of errors.
+	 */
+	private void readEntityCore(Core core) throws DataAccessException {
+		if (!core.getTypeName().equals(getEntityType().getName())) {
+			throw new IllegalArgumentException("Entity core '" + core.getTypeName()
+					+ "' is incompatible with current update statement for entity type '" + getEntityType() + "'.");
+		}
+
+		// add all entity values
+		for (Value value : core.getAllValues().values()) {
+			updateMap.computeIfAbsent(value.getName(), k -> new ArrayList<>()).add(value);
+		}
+
+		// collect file links
+		fileLinkToUpload.addAll(core.getAddedFileLinks());
+		List<FileLink> fileLinksToRemove = core.getRemovedFileLinks();
+		if (isFilesAttachable && !fileLinksToRemove.isEmpty()) {
+			getTransaction().getUploadService().addToRemove(fileLinksToRemove);
+		}
+
+		updateMap.computeIfAbsent(getEntityType().getIDAttribute().getName(), k -> new ArrayList<>())
+				.add(getEntityType().getIDAttribute().createValue(core.getID()));
+
+		// define "empty" values for ALL informative relations
+		for (Relation relation : getEntityType().getInfoRelations()) {
+			updateMap.computeIfAbsent(relation.getName(), k -> new ArrayList<>()).add(relation.createValue());
+		}
+
+		// preserve "empty" relation values for removed related entities
+		EntityStore mutableStore = core.getMutableStore();
+		mutableStore.getRemoved().stream().map(e -> getModelManager().getEntityType(e))
+				.map(getEntityType()::getRelation).map(Relation::getName).forEach(nonUpdatableRelationNames::remove);
+
+		// replace "empty" relation values with corresponding instance IDs
+		setRelationIDs(mutableStore.getCurrent());
+
+		collectChildEntities(core);
+
+		getTransaction().addModified(core);
+	}
+
+	/**
+	 * Collects child entities for recursive processing.
+	 *
+	 * @param core The {@link Core}.
+	 */
+	private void collectChildEntities(Core core) {
+		if (ignoreChildren) {
+			return;
+		}
+
+		for (Entry<Class<? extends Deletable>, List<? extends Deletable>> entry : core.getChildrenStore().getCurrent()
+				.entrySet()) {
+			Map<Boolean, List<Entity>> partition = entry.getValue().stream()
+					.collect(Collectors.partitioningBy(e -> ODSUtils.isValidID(e.getID())));
+			List<Entity> virtualEntities = partition.get(Boolean.FALSE);
+			if (virtualEntities != null && !virtualEntities.isEmpty()) {
+				childrenToCreate.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(virtualEntities);
+			}
+			List<Entity> existingEntities = partition.get(Boolean.TRUE);
+			if (existingEntities != null && !existingEntities.isEmpty()) {
+				childrenToUpdate.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(existingEntities);
+			}
+		}
+
+		for (Entry<Class<? extends Deletable>, List<? extends Deletable>> entry : core.getChildrenStore().getRemoved()
+				.entrySet()) {
+			List<Deletable> toDelete = entry.getValue().stream().filter(e -> ODSUtils.isValidID(e.getID()))
+					.collect(Collectors.toList());
+			childrenToRemove.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(toDelete);
+		}
+	}
+
+	/**
+	 * Overwrites empty foreign key {@link Value} containers.
+	 *
+	 * @param relatedEntities The related {@link Entity}s.
+	 */
+	private void setRelationIDs(Collection<Entity> relatedEntities) {
+		for (Entity relatedEntity : relatedEntities) {
+			if (!ODSUtils.isValidID(relatedEntity.getID())) {
+				throw new IllegalArgumentException("Related entity must be a persited entity.");
+			}
+
+			Relation relation = getEntityType().getRelation(getModelManager().getEntityType(relatedEntity));
+			List<Value> relationValues = updateMap.get(relation.getName());
+			if (relationValues == null) {
+				throw new IllegalStateException("Relation '" + relation
+						+ "' is incompatible with update statement for entity type '" + getEntityType() + "'");
+			}
+			relationValues.get(relationValues.size() - 1).set(relatedEntity.getID());
+			nonUpdatableRelationNames.remove(relation.getName());
+		}
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UploadService.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UploadService.java
new file mode 100644
index 0000000..5748049
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/UploadService.java
@@ -0,0 +1,204 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.asam.ods.AoException;
+import org.eclipse.mdm.api.base.file.FileService.ProgressListener;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.filetransfer.CORBAFileService;
+import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
+
+/**
+ * Manages new or removed externally linked files.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+final class UploadService {
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+
+	private final Map<TemplateAttribute, Value> templateAttributeFileLinks = new HashMap<>();
+	private final List<FileLink> uploaded = new ArrayList<>();
+	private final Map<InputStream, String> remotePaths = new HashMap<>();
+	private final List<FileLink> toRemove = new ArrayList<>();
+
+	private final CORBAFileService fileService;
+	private final Entity entity;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param context  Used for setup.
+	 * @param entity   Used for security checks.
+	 * @param transfer The transfer type.
+	 */
+	UploadService(ODSContext context, Entity entity, Transfer transfer) {
+		fileService = new CORBAFileService(context, transfer);
+		this.entity = entity;
+
+		scheduler.scheduleAtFixedRate(() -> {
+			try {
+				context.getAoSession().getName();
+			} catch (AoException e) {
+				/*
+				 * NOTE: This is done to keep the parent transaction's session alive till its
+				 * commit or abort method is called. If this session refresh results in an
+				 * error, then any running file transfer will abort with a proper error,
+				 * therefore any exception here is completely ignored and explicitly NOT logged!
+				 */
+			}
+		}, 5, 5, TimeUnit.MINUTES);
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Uploads new externally linked files stored in given
+	 * {@link TemplateAttribute}s. The upload progress may be traced with a progress
+	 * listener.
+	 *
+	 * @param templateAttributes The {@link TemplateAttribute}s.
+	 * @param progressListener   The progress listener.
+	 * @throws IOException Thrown if unable to upload files.
+	 */
+	public void upload(Collection<TemplateAttribute> templateAttributes, ProgressListener progressListener)
+			throws IOException {
+		List<FileLink> fileLinks = new ArrayList<>();
+		for (TemplateAttribute templateAttribute : templateAttributes) {
+			Value defaultValue = templateAttribute.getDefaultValue();
+			if (!defaultValue.isValid()) {
+				continue;
+			}
+
+			if (defaultValue.getValueType().isFileLink()) {
+				fileLinks.add(defaultValue.extract());
+			} else if (defaultValue.getValueType().isFileLinkSequence()) {
+				fileLinks.addAll(Arrays.asList((FileLink[]) defaultValue.extract()));
+			} else {
+				throw new IllegalStateException("Template attribute's value type is not of type file link.");
+			}
+
+			templateAttributeFileLinks.put(templateAttribute, defaultValue);
+		}
+
+		if (!fileLinks.isEmpty()) {
+			uploadParallel(fileLinks, progressListener);
+			// remote paths available -> update template attribute
+			templateAttributeFileLinks.forEach((ta, v) -> ta.setDefaultValue(v.extract()));
+		}
+	}
+
+	/**
+	 * Parallel upload of given {@link FileLink}s. Local {@link Path}s linked
+	 * multiple times are uploaded only once. The upload progress may be traced with
+	 * a progress listener.
+	 *
+	 * @param fileLinks        Collection of {@code FileLink}s to upload.
+	 * @param progressListener The progress listener.
+	 * @throws IOException Thrown if unable to upload files.
+	 */
+	public void uploadParallel(Collection<FileLink> fileLinks, ProgressListener progressListener) throws IOException {
+		List<FileLink> filtered = retainForUpload(fileLinks);
+		try {
+			fileService.uploadParallel(entity, filtered, progressListener);
+		} finally {
+			filtered.stream().filter(FileLink::isRemote).forEach(fl -> {
+				remotePaths.put(fl.getLocalStream(), fl.getRemotePath());
+				uploaded.add(fl);
+			});
+		}
+	}
+
+	/**
+	 * Once {@link #commit()} is called given {@link FileLink}s will be deleted from
+	 * the remote storage.
+	 *
+	 * @param fileLinks Collection of {@code FileLink}s to delete.
+	 */
+	public void addToRemove(Collection<FileLink> fileLinks) {
+		toRemove.addAll(fileLinks);
+	}
+
+	/**
+	 * Commits modifications of externally linked files.
+	 */
+	public void commit() {
+		fileService.delete(entity, toRemove);
+		scheduler.shutdown();
+	}
+
+	/**
+	 * Aborts modifications of externally linked files.
+	 */
+	public void abort() {
+		fileService.delete(entity, uploaded);
+		uploaded.forEach(fl -> fl.setRemotePath(null));
+		templateAttributeFileLinks.forEach((ta, v) -> ta.setDefaultValue(v.extract()));
+		scheduler.shutdown();
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Filters given {@link FileLink}s by removing already uploaded ones.
+	 *
+	 * @param fileLinks Will be filtered.
+	 * @return Returns {@code FileLink}s which have to be uploaded.
+	 */
+	private List<FileLink> retainForUpload(Collection<FileLink> fileLinks) {
+		List<FileLink> filtered = new ArrayList<>(fileLinks);
+		for (FileLink fileLink : fileLinks) {
+			String remotePath = remotePaths.get(fileLink.getLocalStream());
+			if (remotePath != null && !remotePath.isEmpty()) {
+				fileLink.setRemotePath(remotePath);
+				filtered.remove(fileLink);
+				uploaded.add(fileLink);
+			}
+		}
+
+		return filtered;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java
new file mode 100644
index 0000000..912af56
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java
@@ -0,0 +1,168 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.transaction;
+
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+
+import org.asam.ods.AoException;
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.adapter.DefaultCore;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.massdata.WriteRequest;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+
+/**
+ * Writes mass data specified in {@link WriteRequest}s.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class WriteRequestHandler {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final String AE_LC_ATTR_INDEPENDENT = "IndependentFlag";
+	private static final String AE_LC_ATTR_REPRESENTATION = "SequenceRepresentation";
+	private static final String AE_LC_ATTR_PARAMETERS = "GenerationParameters";
+	private static final String AE_LC_ATTR_RAWDATATYPE = "RawDatatype";
+	private static final String AE_LC_ATTR_AXISTYPE = "axistype";
+	private static final String AE_LC_ATTR_VALUES = "Values";
+	private static final String AE_LC_ATTR_FLAGS = "Flags";
+	private static final String AE_LC_ATTR_GLOBAL_FLAG = "GlobalFlag";
+
+	// ======================================================================
+	// Instance variables
+	// ======================================================================
+
+	private final List<Core> cores = new ArrayList<>();
+	private final EntityType localColumnEntityType;
+	private final InsertStatement insertStatement;
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 *
+	 * @param transaction The owning {@link ODSTransaction}.
+	 */
+	public WriteRequestHandler(ODSTransaction transaction) {
+		localColumnEntityType = transaction.getModelManager().getEntityType("LocalColumn");
+		insertStatement = new InsertStatement(transaction, localColumnEntityType);
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Adds given {@link WriteRequest} to be processed.
+	 *
+	 * @param writeRequest The {@code WriteRequest}.
+	 */
+	public void addRequest(WriteRequest writeRequest) {
+		cores.add(createCore(writeRequest));
+	}
+
+	/**
+	 * Imports given mass data configurations.
+	 *
+	 * @throws AoException         Thrown if the execution fails.
+	 * @throws DataAccessException Thrown if the execution fails.
+	 * @throws IOException         Thrown if a file transfer operation fails.
+	 */
+	public void execute() throws AoException, DataAccessException, IOException {
+		insertStatement.executeWithCores(cores);
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Reads given {@link WriteRequest} and prepares a corresponding {@link Core}
+	 * for import.
+	 *
+	 * @param writeRequest The mass data configuration.
+	 * @return The created {@code Core} is returned.
+	 */
+	private Core createCore(WriteRequest writeRequest) {
+		Core core = new DefaultCore(localColumnEntityType);
+
+		core.getPermanentStore().set(writeRequest.getChannelGroup());
+		core.getMutableStore().set(writeRequest.getChannel());
+
+		Map<String, Value> values = core.getValues();
+		values.get(Entity.ATTR_NAME).set(writeRequest.getChannel().getName());
+		values.get(Entity.ATTR_MIMETYPE).set("application/x-asam.aolocalcolumn");
+		values.get(AE_LC_ATTR_INDEPENDENT).set((short) (writeRequest.isIndependent() ? 1 : 0));
+		values.get(AE_LC_ATTR_RAWDATATYPE).set(writeRequest.getRawScalarType());
+		values.get(AE_LC_ATTR_REPRESENTATION).set(writeRequest.getSequenceRepresentation());
+		values.get(AE_LC_ATTR_AXISTYPE).set(writeRequest.getAxisType());
+		values.get(AE_LC_ATTR_PARAMETERS).set(writeRequest.getGenerationParameters());
+
+		if (writeRequest.hasValues()) {
+			ValueType<?> valueType = writeRequest.getRawScalarType().toValueType();
+			String unitName = writeRequest.getChannel().getUnit().getName();
+			values.put(AE_LC_ATTR_VALUES,
+					valueType.create(AE_LC_ATTR_VALUES, unitName, true, writeRequest.getValues()));
+
+			// OpenATFX issue: For "implicit" columns, if no value for the
+			// GenerationParameters attribute is present,
+			// it is attempted to transfer the local column values (through which the
+			// generation parameters are
+			// available in these cases) to the GenerationParameters attribute without
+			// converting them to the
+			// correct DS_DOUBLE data type first (unless it is a DOUBLE or LONG column),
+			// resulting in an exception.
+			// Hence, supply correctly converted generation parameters as a workaround:
+			if (writeRequest.getSequenceRepresentation().isImplicit()) {
+				Object genParamValues = writeRequest.getValues();
+				double[] genParamD = new double[Array.getLength(genParamValues)];
+				IntStream.range(0, genParamD.length)
+						.forEach(i -> genParamD[i] = ((Number) Array.get(genParamValues, i)).doubleValue());
+				values.get(AE_LC_ATTR_PARAMETERS).set(genParamD);
+			}
+
+			// flags
+			if (writeRequest.areAllValid()) {
+				values.get(AE_LC_ATTR_GLOBAL_FLAG).set((short) 15);
+			} else {
+				short[] flags = ODSConverter.toODSValidFlagSeq(writeRequest.getFlags());
+				values.get(AE_LC_ATTR_FLAGS).set(flags);
+			}
+		} else if (writeRequest.hasExternalComponents()) {
+			// TODO
+			throw new UnsupportedOperationException("NOT YET IMPLEMENTED.");
+		} else {
+			throw new IllegalStateException("Given write request neither has measured values nor external components");
+		}
+
+		return core;
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java
new file mode 100644
index 0000000..53273e9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java
@@ -0,0 +1,1207 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.utils;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.asam.ods.Blob;
+import org.asam.ods.DataType;
+import org.asam.ods.NameValueSeqUnit;
+import org.asam.ods.TS_Union;
+import org.asam.ods.TS_UnionSeq;
+import org.asam.ods.TS_Value;
+import org.asam.ods.TS_ValueSeq;
+import org.asam.ods.T_COMPLEX;
+import org.asam.ods.T_DCOMPLEX;
+import org.asam.ods.T_ExternalReference;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.model.DoubleComplex;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.FloatComplex;
+import org.eclipse.mdm.api.base.model.MeasuredValues;
+import org.eclipse.mdm.api.base.model.MimeType;
+import org.eclipse.mdm.api.base.model.ScalarType;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.odsadapter.ReadRequestHandler;
+import org.eclipse.mdm.api.odsadapter.query.ODSAttribute;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Utility class for value conversions from/to ODS types.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSConverter {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final Map<Integer, DateTimeFormatter> ODS_DATE_FORMATTERS = new HashMap<>();
+
+	static {
+		ODS_DATE_FORMATTERS.put(4,
+				new DateTimeFormatterBuilder().appendPattern("yyyy").parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
+						.parseDefaulting(ChronoField.DAY_OF_MONTH, 1).toFormatter());
+		ODS_DATE_FORMATTERS.put(6, new DateTimeFormatterBuilder().appendPattern("yyyyMM")
+				.parseDefaulting(ChronoField.DAY_OF_MONTH, 1).toFormatter());
+		ODS_DATE_FORMATTERS.put(8, DateTimeFormatter.ofPattern("yyyyMMdd"));
+		ODS_DATE_FORMATTERS.put(10, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+		ODS_DATE_FORMATTERS.put(12, DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
+		ODS_DATE_FORMATTERS.put(14, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
+		/*
+		 * JDK-8031085: DateTimeFormatter won't parse dates with custom format
+		 * "yyyyMMddHHmmssSSS"
+		 * 
+		 * @see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8031085
+		 */
+		ODS_DATE_FORMATTERS.put(17, new DateTimeFormatterBuilder().appendPattern("yyyyMMddHHmmss")
+				.appendValue(ChronoField.MILLI_OF_SECOND, 3).toFormatter());
+	}
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 */
+	private ODSConverter() {
+	}
+
+	// ======================================================================
+	// Conversion methods
+	// ======================================================================
+
+	/**
+	 * Converts given {@link TS_ValueSeq} to {@link Value}s.
+	 *
+	 * @param attribute   The {@link Attribute}.
+	 * @param aggregation The {@link Aggregation} used when the values were
+	 *                    obtained.
+	 * @param unit        The unit name.
+	 * @param odsValueSeq The {@code TS_ValueSeq}.
+	 * @return The converted {@code Value}s are returned.
+	 * @throws DataAccessException Thrown on conversion errors.
+	 */
+	public static List<Value> fromODSValueSeq(Attribute attribute, Aggregation aggregation, String unit,
+			TS_ValueSeq odsValueSeq) throws DataAccessException {
+		DataType dataType = odsValueSeq.u.discriminator();
+		short[] flags = odsValueSeq.flag;
+		List<Value> values = new ArrayList<>(flags.length);
+
+		if (((ODSAttribute) attribute).isIdAttribute() && Sets
+				.immutableEnumSet(Aggregation.MINIMUM, Aggregation.MAXIMUM, Aggregation.DISTINCT, Aggregation.NONE)
+				.contains(aggregation)) {
+			if (DataType.DT_LONGLONG == dataType) {
+				T_LONGLONG[] odsValues = odsValueSeq.u.longlongVal();
+				for (int i = 0; i < flags.length; i++) {
+					values.add(createValue(attribute, aggregation, DataType.DT_STRING, unit, flags[i] == 15,
+							Long.toString(fromODSLong(odsValues[i]))));
+				}
+				return values;
+			} else if (DataType.DS_LONGLONG == dataType) {
+				T_LONGLONG[][] odsValues = odsValueSeq.u.longlongSeq();
+				for (int i = 0; i < flags.length; i++) {
+					values.add(createValue(attribute, aggregation, DataType.DS_STRING, unit, flags[i] == 15,
+							toString(odsValues[i])));
+				}
+				return values;
+			} else if (DataType.DT_LONG == dataType) {
+				int[] odsValues = odsValueSeq.u.longVal();
+				for (int i = 0; i < flags.length; i++) {
+					values.add(createValue(attribute, aggregation, DataType.DT_STRING, unit, flags[i] == 15,
+							Integer.toString(odsValues[i])));
+				}
+				return values;
+			} else if (DataType.DS_LONG == dataType) {
+				int[][] odsValues = odsValueSeq.u.longSeq();
+				for (int i = 0; i < flags.length; i++) {
+					values.add(createValue(attribute, aggregation, DataType.DS_STRING, unit, flags[i] == 15,
+							toString(odsValues[i])));
+				}
+				return values;
+			}
+		}
+
+		if (DataType.DT_STRING == dataType) {
+			String[] odsValues = odsValueSeq.u.stringVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_STRING == dataType) {
+			String[][] odsValues = odsValueSeq.u.stringSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_DATE == dataType) {
+			String[] odsValues = odsValueSeq.u.dateVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(
+						createValue(attribute, aggregation, dataType, unit, flags[i] == 15, fromODSDate(odsValues[i])));
+			}
+		} else if (DataType.DS_DATE == dataType) {
+			String[][] odsValues = odsValueSeq.u.dateSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSDateSeq(odsValues[i])));
+			}
+		} else if (DataType.DT_BOOLEAN == dataType) {
+			boolean[] odsValues = odsValueSeq.u.booleanVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_BOOLEAN == dataType) {
+			boolean[][] odsValues = odsValueSeq.u.booleanSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_BYTE == dataType) {
+			byte[] odsValues = odsValueSeq.u.byteVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_BYTE == dataType) {
+			byte[][] odsValues = odsValueSeq.u.byteSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_SHORT == dataType) {
+			short[] odsValues = odsValueSeq.u.shortVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_SHORT == dataType) {
+			short[][] odsValues = odsValueSeq.u.shortSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_LONG == dataType) {
+			int[] odsValues = odsValueSeq.u.longVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_LONG == dataType) {
+			int[][] odsValues = odsValueSeq.u.longSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_LONGLONG == dataType) {
+			T_LONGLONG[] odsValues = odsValueSeq.u.longlongVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(
+						createValue(attribute, aggregation, dataType, unit, flags[i] == 15, fromODSLong(odsValues[i])));
+			}
+		} else if (DataType.DS_LONGLONG == dataType) {
+			T_LONGLONG[][] odsValues = odsValueSeq.u.longlongSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSLongSeq(odsValues[i])));
+			}
+		} else if (DataType.DT_FLOAT == dataType) {
+			float[] odsValues = odsValueSeq.u.floatVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_FLOAT == dataType) {
+			float[][] odsValues = odsValueSeq.u.floatSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_DOUBLE == dataType) {
+			double[] odsValues = odsValueSeq.u.doubleVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_DOUBLE == dataType) {
+			double[][] odsValues = odsValueSeq.u.doubleSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_BYTESTR == dataType) {
+			byte[][] odsValues = odsValueSeq.u.bytestrVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DS_BYTESTR == dataType) {
+			byte[][][] odsValues = odsValueSeq.u.bytestrSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15, odsValues[i]));
+			}
+		} else if (DataType.DT_COMPLEX == dataType) {
+			T_COMPLEX[] odsValues = odsValueSeq.u.complexVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSFloatComplex(odsValues[i])));
+			}
+		} else if (DataType.DS_COMPLEX == dataType) {
+			T_COMPLEX[][] odsValues = odsValueSeq.u.complexSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSFloatComplexSeq(odsValues[i])));
+			}
+		} else if (DataType.DT_DCOMPLEX == dataType) {
+			T_DCOMPLEX[] odsValues = odsValueSeq.u.dcomplexVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSDoubleComplex(odsValues[i])));
+			}
+		} else if (DataType.DS_DCOMPLEX == dataType) {
+			T_DCOMPLEX[][] odsValues = odsValueSeq.u.dcomplexSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSDoubleComplexSeq(odsValues[i])));
+			}
+		} else if (DataType.DT_ENUM == dataType) {
+			int[] odsValues = odsValueSeq.u.enumVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						ODSEnumerations.fromODSEnum(attribute.getEnumObj(), odsValues[i])));
+			}
+		} else if (DataType.DS_ENUM == dataType) {
+			int[][] odsValues = odsValueSeq.u.enumSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						ODSEnumerations.fromODSEnumSeq(attribute.getEnumObj(), odsValues[i])));
+			}
+		} else if (DataType.DT_EXTERNALREFERENCE == dataType) {
+			T_ExternalReference[] odsValues = odsValueSeq.u.extRefVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSExternalReference(odsValues[i])));
+			}
+		} else if (DataType.DS_EXTERNALREFERENCE == dataType) {
+			T_ExternalReference[][] odsValues = odsValueSeq.u.extRefSeq();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(createValue(attribute, aggregation, dataType, unit, flags[i] == 15,
+						fromODSExternalReferenceSeq(odsValues[i])));
+			}
+		} else if (DataType.DT_BLOB == dataType) {
+			Blob[] odsValues = odsValueSeq.u.blobVal();
+			for (int i = 0; i < flags.length; i++) {
+				values.add(
+						createValue(attribute, aggregation, dataType, unit, flags[i] == 15, fromODSBlob(odsValues[i])));
+			}
+		} else {
+			throw new DataAccessException("Conversion for ODS data type '" + dataType.toString() + "' does not exist.");
+		}
+
+		return values;
+	}
+
+	/**
+	 * Creates a {@link Value} from the input.
+	 * 
+	 * @param attribute   The {@link Attribute}
+	 * @param aggregation The {@link Aggregation} used when the input values were
+	 *                    obtained
+	 * @param dataType    The {@link DataType} associated with the input value,
+	 *                    evaluated only if aggregation != {@code Aggregation.NONE},
+	 *                    otherwise that of the attribute is used
+	 * @param unit        The unit of the input value
+	 * @param valid       The validity flag of the input value
+	 * @param input       The input value
+	 * @return The {@link Value} created.
+	 */
+	private static Value createValue(Attribute attribute, Aggregation aggregation, DataType dataType, String unit,
+			boolean valid, Object input) {
+		if (Aggregation.NONE == aggregation) {
+			return attribute.createValue(unit, valid, input);
+		} else {
+			ValueType<?> valueType = ODSUtils.VALUETYPES.inverse().get(dataType);
+			if (valueType.isEnumerationType() && attribute.getValueType().isEnumerationType()
+					&& Sets.immutableEnumSet(Aggregation.MINIMUM, Aggregation.MAXIMUM, Aggregation.DISTINCT)
+							.contains(aggregation)) {
+				return valueType.create(getColumnName(attribute, aggregation), unit, valid, input,
+						attribute.getEnumObj().getName());
+			} else {
+				return valueType.create(getColumnName(attribute, aggregation), unit, valid, input);
+			}
+		}
+	}
+
+	/**
+	 * Returns the name of the attribute with its applied aggregation as returned by
+	 * the ODS Server, for example: MAXIMUM(sortIndex)
+	 * 
+	 * @param attribute
+	 * @param aggregation
+	 * @return the name of the attribute with the applied aggragation
+	 */
+	public static String getColumnName(Attribute attribute, Aggregation aggregation) {
+		return String.format("%s(%s)", aggregation.name(), attribute.getName());
+	}
+
+	private static String[] toString(int[] odsValues) {
+		return IntStream.of(odsValues).mapToObj(Integer::toString).toArray(String[]::new);
+	}
+
+	private static String[] toString(T_LONGLONG[] odsValues) {
+		return Stream.of(odsValues).map(l -> Long.toString(fromODSLong(l))).toArray(String[]::new);
+	}
+
+	/**
+	 * Converts given {@link Value}s to {@link TS_ValueSeq}.
+	 *
+	 * @param values The {@code Value}s.
+	 * @return The converted {@code TS_ValueSeq} is returned.
+	 * @throws DataAccessException Thrown on conversion errors.
+	 */
+	public static TS_ValueSeq toODSValueSeq(Attribute attribute, List<Value> values) throws DataAccessException {
+		int size = values == null ? 0 : values.size();
+		short[] flags = new short[size];
+
+		TS_ValueSeq odsValueSeq = new TS_ValueSeq(new TS_UnionSeq(), flags);
+		if (values == null || size < 1) {
+			odsValueSeq.u._default();
+			return odsValueSeq;
+		}
+
+		ValueType<?> type = values.get(0).getValueType();
+		if (ValueType.STRING == type) {
+			String[] odsValues = new String[size];
+			for (int i = 0; i < size; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			if (((ODSAttribute) attribute).isIdAttribute()) {
+				odsValueSeq.u.longlongVal(toLongLong(odsValues));
+			} else {
+				odsValueSeq.u.stringVal(odsValues);
+			}
+		} else if (ValueType.STRING_SEQUENCE == type) {
+			String[][] odsValues = new String[size][];
+			for (int i = 0; i < size; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			if (((ODSAttribute) attribute).isIdAttribute()) {
+				odsValueSeq.u.longlongSeq(toLongLongSeq(odsValues));
+			} else {
+				odsValueSeq.u.stringSeq(odsValues);
+			}
+
+		} else if (ValueType.DATE == type) {
+			String[] odsValues = new String[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSDate(value.extract());
+			}
+			odsValueSeq.u.dateVal(odsValues);
+		} else if (ValueType.DATE_SEQUENCE == type) {
+			String[][] odsValues = new String[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSDateSeq(value.extract());
+			}
+			odsValueSeq.u.dateSeq(odsValues);
+		} else if (ValueType.BOOLEAN == type) {
+			boolean[] odsValues = new boolean[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.booleanVal(odsValues);
+		} else if (ValueType.BOOLEAN_SEQUENCE == type) {
+			boolean[][] odsValues = new boolean[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.booleanSeq(odsValues);
+		} else if (ValueType.BYTE == type) {
+			byte[] odsValues = new byte[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.byteVal(odsValues);
+		} else if (ValueType.BYTE_SEQUENCE == type) {
+			byte[][] odsValues = new byte[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.byteSeq(odsValues);
+		} else if (ValueType.SHORT == type) {
+			short[] odsValues = new short[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.shortVal(odsValues);
+		} else if (ValueType.SHORT_SEQUENCE == type) {
+			short[][] odsValues = new short[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.shortSeq(odsValues);
+		} else if (ValueType.INTEGER == type) {
+			int[] odsValues = new int[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.longVal(odsValues);
+		} else if (ValueType.INTEGER_SEQUENCE == type) {
+			int[][] odsValues = new int[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.longSeq(odsValues);
+		} else if (ValueType.LONG == type) {
+			T_LONGLONG[] odsValues = new T_LONGLONG[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSLong(value.extract());
+			}
+			odsValueSeq.u.longlongVal(odsValues);
+		} else if (ValueType.LONG_SEQUENCE == type) {
+			T_LONGLONG[][] odsValues = new T_LONGLONG[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSLongSeq(value.extract());
+			}
+			odsValueSeq.u.longlongSeq(odsValues);
+		} else if (ValueType.FLOAT == type) {
+			float[] odsValues = new float[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.floatVal(odsValues);
+		} else if (ValueType.FLOAT_SEQUENCE == type) {
+			float[][] odsValues = new float[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.floatSeq(odsValues);
+		} else if (ValueType.DOUBLE == type) {
+			double[] odsValues = new double[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.doubleVal(odsValues);
+		} else if (ValueType.DOUBLE_SEQUENCE == type) {
+			double[][] odsValues = new double[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.doubleSeq(odsValues);
+		} else if (ValueType.BYTE_STREAM == type) {
+			byte[][] odsValues = new byte[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.bytestrVal(odsValues);
+		} else if (ValueType.BYTE_STREAM_SEQUENCE == type) {
+			byte[][][] odsValues = new byte[size][][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = value.extract();
+			}
+			odsValueSeq.u.bytestrSeq(odsValues);
+		} else if (ValueType.FLOAT_COMPLEX == type) {
+			T_COMPLEX[] odsValues = new T_COMPLEX[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSFloatComplex(value.extract());
+			}
+			odsValueSeq.u.complexVal(odsValues);
+		} else if (ValueType.FLOAT_COMPLEX_SEQUENCE == type) {
+			T_COMPLEX[][] odsValues = new T_COMPLEX[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSFloatComplexSeq(value.extract());
+			}
+			odsValueSeq.u.complexSeq(odsValues);
+		} else if (ValueType.DOUBLE_COMPLEX == type) {
+			T_DCOMPLEX[] odsValues = new T_DCOMPLEX[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSDoubleComplex(value.extract());
+			}
+			odsValueSeq.u.dcomplexVal(odsValues);
+		} else if (ValueType.DOUBLE_COMPLEX_SEQUENCE == type) {
+			T_DCOMPLEX[][] odsValues = new T_DCOMPLEX[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSDoubleComplexSeq(value.extract());
+			}
+			odsValueSeq.u.dcomplexSeq(odsValues);
+		} else if (ValueType.ENUMERATION == type) {
+			int[] odsValues = new int[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = ODSEnumerations.toODSEnum(value.extract());
+			}
+			odsValueSeq.u.enumVal(odsValues);
+		} else if (ValueType.ENUMERATION_SEQUENCE == type) {
+			int[][] odsValues = new int[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = ODSEnumerations.toODSEnumSeq(value.extract());
+			}
+			odsValueSeq.u.enumSeq(odsValues);
+		} else if (ValueType.FILE_LINK == type) {
+			T_ExternalReference[] odsValues = new T_ExternalReference[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSExternalReference(value.extract());
+			}
+			odsValueSeq.u.extRefVal(odsValues);
+		} else if (ValueType.FILE_LINK_SEQUENCE == type) {
+			T_ExternalReference[][] odsValues = new T_ExternalReference[size][];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSExternalReferenceSeq(value.extract());
+			}
+			odsValueSeq.u.extRefSeq(odsValues);
+		} else if (ValueType.BLOB == type) {
+			Blob[] odsValues = new Blob[size];
+			for (int i = 0; i < flags.length; i++) {
+				Value value = values.get(i);
+				flags[i] = toODSValidFlag(value.isValid());
+				odsValues[i] = toODSBlob(value.extract());
+			}
+			odsValueSeq.u.blobVal(odsValues);
+		} else {
+			throw new DataAccessException("Mapping for value type '" + type + "' does not exist.");
+		}
+
+		return odsValueSeq;
+	}
+
+	/**
+	 * Converts given two dimensional String array to two dimensional
+	 * {@link T_LONGLONG} array.
+	 * 
+	 * @param value The String array.
+	 * @return The converted {@link T_LONGLONG} array.
+	 */
+	private static T_LONGLONG[][] toLongLongSeq(String[][] value) {
+
+		return Stream.of(value).map(ODSConverter::toLongLong).toArray(T_LONGLONG[][]::new);
+	}
+
+	/**
+	 * Converts given String array to {@link T_LONGLONG} array.
+	 * 
+	 * @param value The String array.
+	 * @return The converted {@link T_LONGLONG} array.
+	 */
+	private static T_LONGLONG[] toLongLong(String[] value) {
+		return Stream.of(value).map(s -> toODSID(s)).toArray(T_LONGLONG[]::new);
+	}
+
+	/**
+	 * Converts given {@link NameValueSeqUnit[]} to {@link MeasuredValues}s.
+	 *
+	 * @param odsMeasuredValuesSeq The {@code NameValueSeqUnit}s.
+	 * @return The converted {@code MeasuredValues}s are returned.
+	 * @throws DataAccessException Thrown on conversion errors.
+	 */
+	public static List<MeasuredValues> fromODSMeasuredValuesSeq(NameValueSeqUnit[] odsMeasuredValuesSeq,
+			ReadRequestHandler.ColumnAttributes[] columnAttributesArray) throws DataAccessException {
+		List<MeasuredValues> measuredValues = new ArrayList<>(odsMeasuredValuesSeq.length);
+
+		Map<String, ReadRequestHandler.ColumnAttributes> mapColumnAttributes = new HashMap<>();
+		if (null != columnAttributesArray) {
+			Arrays.stream(columnAttributesArray).forEach(ca -> mapColumnAttributes.put(ca.getName(), ca));
+		}
+
+		for (NameValueSeqUnit odsMeasuredValues : odsMeasuredValuesSeq) {
+			measuredValues
+					.add(fromODSMeasuredValues(odsMeasuredValues, mapColumnAttributes.get(odsMeasuredValues.valName)));
+		}
+
+		return measuredValues;
+	}
+
+	/**
+	 * Converts given {@link NameValueSeqUnit} to {@link MeasuredValues}.
+	 *
+	 * @param odsMeasuredValues The {@code NameValueSeqUnit}.
+	 * @return The converted {@code MeasuredValues} is returned.
+	 * @throws DataAccessException Thrown on conversion errors.
+	 */
+	private static MeasuredValues fromODSMeasuredValues(NameValueSeqUnit odsMeasuredValues,
+			ReadRequestHandler.ColumnAttributes columnAttributes) throws DataAccessException {
+		TS_ValueSeq odsValueSeq = odsMeasuredValues.value;
+		DataType dataType = odsValueSeq.u.discriminator();
+		ScalarType scalarType;
+		Object values;
+
+		if (DataType.DT_STRING == dataType) {
+			scalarType = ScalarType.STRING;
+			values = odsValueSeq.u.stringVal();
+		} else if (DataType.DT_DATE == dataType) {
+			scalarType = ScalarType.DATE;
+			values = fromODSDateSeq(odsValueSeq.u.dateVal());
+		} else if (DataType.DT_BOOLEAN == dataType) {
+			scalarType = ScalarType.BOOLEAN;
+			values = odsValueSeq.u.booleanVal();
+		} else if (DataType.DT_BYTE == dataType) {
+			scalarType = ScalarType.BYTE;
+			values = odsValueSeq.u.byteVal();
+		} else if (DataType.DT_SHORT == dataType) {
+			scalarType = ScalarType.SHORT;
+			values = odsValueSeq.u.shortVal();
+		} else if (DataType.DT_LONG == dataType) {
+			scalarType = ScalarType.INTEGER;
+			values = odsValueSeq.u.longVal();
+		} else if (DataType.DT_LONGLONG == dataType) {
+			scalarType = ScalarType.LONG;
+			values = fromODSLongSeq(odsValueSeq.u.longlongVal());
+		} else if (DataType.DT_FLOAT == dataType) {
+			scalarType = ScalarType.FLOAT;
+			values = odsValueSeq.u.floatVal();
+		} else if (DataType.DT_DOUBLE == dataType) {
+			scalarType = ScalarType.DOUBLE;
+			values = odsValueSeq.u.doubleVal();
+		} else if (DataType.DT_BYTESTR == dataType) {
+			scalarType = ScalarType.BYTE_STREAM;
+			values = odsValueSeq.u.bytestrVal();
+		} else if (DataType.DT_COMPLEX == dataType) {
+			scalarType = ScalarType.FLOAT_COMPLEX;
+			values = fromODSFloatComplexSeq(odsValueSeq.u.complexVal());
+		} else if (DataType.DT_DCOMPLEX == dataType) {
+			scalarType = ScalarType.DOUBLE_COMPLEX;
+			values = fromODSDoubleComplexSeq(odsValueSeq.u.dcomplexVal());
+		} else if (DataType.DT_EXTERNALREFERENCE == dataType) {
+			scalarType = ScalarType.FILE_LINK;
+			values = fromODSExternalReferenceSeq(odsValueSeq.u.extRefVal());
+		} else {
+			throw new DataAccessException(
+					"Conversion for ODS measured points of type '" + dataType.toString() + "' does not exist.");
+		}
+
+		if (null == columnAttributes) {
+			columnAttributes = new ReadRequestHandler.ColumnAttributes("", null, new double[0], false, null);
+		}
+
+		return scalarType.createMeasuredValues(odsMeasuredValues.valName, odsMeasuredValues.unit,
+				columnAttributes.getSequenceRepresentation(), columnAttributes.getGenerationParameters(),
+				columnAttributes.isIndependentColumn(), columnAttributes.getAxisType(), values,
+				fromODSValidFlagSeq(odsValueSeq.flag));
+	}
+
+	/**
+	 * Converts given {@link Value} to {@link TS_Value}.
+	 *
+	 * @param value The {@code Value}.
+	 * @return The converted {@code TS_Value} is returned.
+	 * @throws DataAccessException Thrown on conversion errors.
+	 */
+	public static TS_Value toODSValue(Attribute attribute, Value value) throws DataAccessException {
+		TS_Value odsValue = new TS_Value(new TS_Union(), toODSValidFlag(value.isValid()));
+		ValueType<?> type = value.getValueType();
+
+		if (ValueType.STRING == type) {
+			if (((ODSAttribute) attribute).isIdAttribute()) {
+				odsValue.u.longlongVal(ODSConverter.toODSID(value.extract()));
+			} else {
+				odsValue.u.stringVal(value.extract());
+			}
+		} else if (ValueType.STRING_SEQUENCE == type) {
+			if (((ODSAttribute) attribute).isIdAttribute()) {
+				odsValue.u.longlongSeq(
+						Stream.of((String[]) value.extract()).map(ODSConverter::toODSID).toArray(T_LONGLONG[]::new));
+			} else {
+				odsValue.u.stringSeq(value.extract());
+			}
+		} else if (ValueType.DATE == type) {
+			odsValue.u.dateVal(toODSDate(value.extract()));
+		} else if (ValueType.DATE_SEQUENCE == type) {
+			odsValue.u.dateSeq(toODSDateSeq(value.extract()));
+		} else if (ValueType.BOOLEAN == type) {
+			odsValue.u.booleanVal(value.extract());
+		} else if (ValueType.BOOLEAN_SEQUENCE == type) {
+			odsValue.u.booleanVal(value.extract());
+		} else if (ValueType.BYTE == type) {
+			odsValue.u.byteVal(value.extract());
+		} else if (ValueType.BYTE_SEQUENCE == type) {
+			odsValue.u.byteSeq(value.extract());
+		} else if (ValueType.SHORT == type) {
+			odsValue.u.shortVal(value.extract());
+		} else if (ValueType.SHORT_SEQUENCE == type) {
+			odsValue.u.shortSeq(value.extract());
+		} else if (ValueType.INTEGER == type) {
+			odsValue.u.longVal(value.extract());
+		} else if (ValueType.INTEGER_SEQUENCE == type) {
+			odsValue.u.longSeq(value.extract());
+		} else if (ValueType.LONG == type) {
+			odsValue.u.longlongVal(toODSLong(value.extract()));
+		} else if (ValueType.LONG_SEQUENCE == type) {
+			odsValue.u.longlongSeq(toODSLongSeq(value.extract()));
+		} else if (ValueType.FLOAT == type) {
+			odsValue.u.floatVal(value.extract());
+		} else if (ValueType.FLOAT_SEQUENCE == type) {
+			odsValue.u.floatSeq(value.extract());
+		} else if (ValueType.DOUBLE == type) {
+			odsValue.u.doubleVal(value.extract());
+		} else if (ValueType.DOUBLE_SEQUENCE == type) {
+			odsValue.u.doubleSeq(value.extract());
+		} else if (ValueType.BYTE_STREAM == type) {
+			odsValue.u.bytestrVal(value.extract());
+		} else if (ValueType.BYTE_STREAM_SEQUENCE == type) {
+			odsValue.u.bytestrSeq(value.extract());
+		} else if (ValueType.FLOAT_COMPLEX == type) {
+			odsValue.u.complexVal(toODSFloatComplex(value.extract()));
+		} else if (ValueType.FLOAT_COMPLEX_SEQUENCE == type) {
+			odsValue.u.complexSeq(toODSFloatComplexSeq(value.extract()));
+		} else if (ValueType.DOUBLE_COMPLEX == type) {
+			odsValue.u.dcomplexVal(toODSDoubleComplex(value.extract()));
+		} else if (ValueType.DOUBLE_COMPLEX_SEQUENCE == type) {
+			odsValue.u.dcomplexSeq(toODSDoubleComplexSeq(value.extract()));
+		} else if (ValueType.ENUMERATION == type) {
+			odsValue.u.enumVal(ODSEnumerations.toODSEnum(value.extract()));
+		} else if (ValueType.ENUMERATION_SEQUENCE == type) {
+			odsValue.u.enumSeq(ODSEnumerations.toODSEnumSeq(value.extract()));
+		} else if (ValueType.FILE_LINK == type) {
+			odsValue.u.extRefVal(toODSExternalReference(value.extract()));
+		} else if (ValueType.FILE_LINK_SEQUENCE == type) {
+			odsValue.u.extRefSeq(toODSExternalReferenceSeq(value.extract()));
+		} else if (ValueType.BLOB == type) {
+			odsValue.u.blobVal(toODSBlob(value.extract()));
+		} else {
+			throw new DataAccessException("Mapping for value type '" + type + "' does not exist.");
+		}
+
+		return odsValue;
+	}
+
+	/**
+	 * Converts given {@link short[]} to {@link boolean[]}.
+	 *
+	 * @param input The {@code short}s.
+	 * @return The converted {@code boolean}s are returned.
+	 */
+	private static boolean[] fromODSValidFlagSeq(short[] input) {
+		boolean[] result = new boolean[input.length];
+		for (int i = 0; i < result.length; i++) {
+			result[i] = fromODSValidFlag(input[i]);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Converts given {@link short} to {@link boolean}.
+	 *
+	 * @param input The {@code short}.
+	 * @return The converted {@code boolean} is returned.
+	 */
+	private static boolean fromODSValidFlag(short input) {
+		return input == 15;
+	}
+
+	/**
+	 * Converts given {@link boolean[]} to {@link short[]}.
+	 *
+	 * @param input The {@code boolean}s.
+	 * @return The converted {@code short}s are returned.
+	 */
+	public static short[] toODSValidFlagSeq(boolean[] input) {
+		short[] result = new short[input.length];
+		for (int i = 0; i < result.length; i++) {
+			result[i] = toODSValidFlag(input[i]);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Converts given {@link boolean} to {@link short}.
+	 *
+	 * @param input The {@code boolean}.
+	 * @return The converted {@code short} is returned.
+	 */
+	public static short toODSValidFlag(boolean input) {
+		return (short) (input ? 15 : 0);
+	}
+
+	/**
+	 * Converts given {@link T_LONGLONG[]} to {@link long[]}.
+	 *
+	 * @param input The {@code T_LONGLONG}s.
+	 * @return The converted {@code long}s are returned.
+	 */
+	private static long[] fromODSLongSeq(T_LONGLONG[] input) {
+		long[] result = new long[input.length];
+		for (int i = 0; i < result.length; i++) {
+			result[i] = fromODSLong(input[i]);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Converts given {@link T_LONGLONG} to {@link long}.
+	 *
+	 * @param input The {@code T_LONGLONG}.
+	 * @return The converted {@code long} is returned.
+	 */
+	public static long fromODSLong(T_LONGLONG input) {
+		T_LONGLONG value = input == null ? new T_LONGLONG() : input;
+		return (value.high + (value.low >= 0 ? 0 : 1)) * 0x100000000L + value.low;
+	}
+
+	/**
+	 * Converts given {@link long[]} to {@link T_LONGLONG[]}.
+	 *
+	 * @param input The {@code long}s.
+	 * @return The converted {@code T_LONGLONG}s are returned.
+	 */
+	private static T_LONGLONG[] toODSLongSeq(long[] input) {
+		List<T_LONGLONG> result = new ArrayList<>(input.length);
+		for (long value : input) {
+			result.add(toODSLong(value));
+		}
+
+		return result.toArray(new T_LONGLONG[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link long} to {@link T_LONGLONG}.
+	 *
+	 * @param input The {@code long}.
+	 * @return The converted {@code T_LONGLONG} is returned.
+	 */
+	public static T_LONGLONG toODSLong(long input) {
+		return new T_LONGLONG((int) (input >> 32 & 0xffffffffL), (int) (input & 0xffffffffL));
+	}
+
+	/**
+	 * Converts a given MDM ID string to {@link T_LONGLONG}.
+	 * 
+	 * @param input The MDM ID string.
+	 * @return The converted {@code T_LONGLONG} is returned.
+	 */
+	public static T_LONGLONG toODSID(String input) {
+		try {
+			return toODSLong(Long.valueOf(input));
+		} catch (NumberFormatException e) {
+			return new T_LONGLONG();
+		}
+	}
+
+	/**
+	 * Converts given {@link String[]} to {@link LocalDateTime[]}.
+	 *
+	 * @param input The {@code String}s.
+	 * @return The converted {@code LocalDateTime}s are returned.
+	 */
+	private static LocalDateTime[] fromODSDateSeq(String[] input) {
+		List<LocalDateTime> result = new ArrayList<>();
+		if (input != null) {
+			for (String value : input) {
+				result.add(fromODSDate(value));
+			}
+		}
+
+		return result.toArray(new LocalDateTime[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link String} to {@link LocalDateTime}.
+	 *
+	 * @param input The {@code T_COMPLEX}.
+	 * @return The converted {@code String} is returned.
+	 */
+	private static LocalDateTime fromODSDate(String input) {
+		if (input == null || input.isEmpty()) {
+			return null;
+		}
+
+		DateTimeFormatter formatter = ODS_DATE_FORMATTERS.get(input.length());
+		if (formatter == null) {
+			throw new IllegalArgumentException("Invalid ODS date: " + input);
+		}
+
+		try {
+			if (input.length() <= 8) {
+				// Java does not accept a bare date as DateTime, so we are using LocalDate
+				// instead of LocalDateTime
+				return LocalDate.parse(input, formatter).atStartOfDay();
+			} else {
+				return LocalDateTime.parse(input, formatter);
+			}
+		} catch (DateTimeParseException e) {
+			throw new IllegalArgumentException("Invalid ODS date: " + input, e);
+		}
+	}
+
+	/**
+	 * Converts given {@link LocalDateTime[]} to {@link String[]}.
+	 *
+	 * @param input The {@code LocalDateTime}s.
+	 * @return The converted {@code String}s are returned.
+	 */
+	private static String[] toODSDateSeq(LocalDateTime[] input) {
+		List<String> result = new ArrayList<>(input.length);
+		for (LocalDateTime value : input) {
+			result.add(toODSDate(value));
+		}
+
+		return result.toArray(new String[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link LocalDateTime} to {@link String}.
+	 *
+	 * @param input The {@code LocalDateTime}.
+	 * @return The converted {@code String} is returned.
+	 */
+	private static String toODSDate(LocalDateTime input) {
+		return input == null ? "" : input.format(ODS_DATE_FORMATTERS.get(14));
+	}
+
+	/**
+	 * Converts given {@link T_COMPLEX[]} to {@link FloatComplex[]}.
+	 *
+	 * @param input The {@code T_COMPLEX}s.
+	 * @return The converted {@code FloatComplex}s are returned.
+	 */
+	private static FloatComplex[] fromODSFloatComplexSeq(T_COMPLEX[] input) {
+		List<FloatComplex> result = new ArrayList<>();
+		if (input != null) {
+			for (T_COMPLEX value : input) {
+				result.add(fromODSFloatComplex(value));
+			}
+		}
+
+		return result.toArray(new FloatComplex[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link T_COMPLEX} to {@link FloatComplex}.
+	 *
+	 * @param input The {@code T_COMPLEX}.
+	 * @return The converted {@code FloatComplex} is returned.
+	 */
+	private static FloatComplex fromODSFloatComplex(T_COMPLEX input) {
+		return input == null ? null : new FloatComplex(input.r, input.i);
+	}
+
+	/**
+	 * Converts given {@link FloatComplex[]} to {@link T_COMPLEX[]}.
+	 *
+	 * @param input The {@code FloatComplex}s.
+	 * @return The converted {@code T_COMPLEX}s are returned.
+	 */
+	private static T_COMPLEX[] toODSFloatComplexSeq(FloatComplex[] input) {
+		List<T_COMPLEX> result = new ArrayList<>(input.length);
+		for (FloatComplex value : input) {
+			result.add(toODSFloatComplex(value));
+		}
+
+		return result.toArray(new T_COMPLEX[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link FloatComplex} to {@link T_COMPLEX}.
+	 *
+	 * @param input The {@code FloatComplex}.
+	 * @return The converted {@code T_COMPLEX} is returned.
+	 */
+	private static T_COMPLEX toODSFloatComplex(FloatComplex input) {
+		return input == null ? null : new T_COMPLEX(input.real(), input.imaginary());
+	}
+
+	/**
+	 * Converts given {@link T_DCOMPLEX[]} to {@link DoubleComplex[]}.
+	 *
+	 * @param input The {@code T_DCOMPLEX}s.
+	 * @return The converted {@code DoubleComplex}s are returned.
+	 */
+	private static DoubleComplex[] fromODSDoubleComplexSeq(T_DCOMPLEX[] input) {
+		List<DoubleComplex> result = new ArrayList<>();
+		if (input != null) {
+			for (T_DCOMPLEX value : input) {
+				result.add(fromODSDoubleComplex(value));
+			}
+		}
+
+		return result.toArray(new DoubleComplex[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link T_DCOMPLEX} to {@link DoubleComplex}.
+	 *
+	 * @param input The {@code T_DCOMPLEX}.
+	 * @return The converted {@code DoubleComplex} is returned.
+	 */
+	private static DoubleComplex fromODSDoubleComplex(T_DCOMPLEX input) {
+		return input == null ? null : new DoubleComplex(input.r, input.i);
+	}
+
+	/**
+	 * Converts given {@link DoubleComplex[]} to {@link T_DCOMPLEX[]}.
+	 *
+	 * @param input The {@code DoubleComplex}s.
+	 * @return The converted {@code T_DCOMPLEX}s are returned.
+	 */
+	private static T_DCOMPLEX[] toODSDoubleComplexSeq(DoubleComplex[] input) {
+		List<T_DCOMPLEX> result = new ArrayList<>(input.length);
+		for (DoubleComplex value : input) {
+			result.add(toODSDoubleComplex(value));
+		}
+
+		return result.toArray(new T_DCOMPLEX[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link DoubleComplex} to {@link T_DCOMPLEX}.
+	 *
+	 * @param input The {@code DoubleComplex}.
+	 * @return The converted {@code T_DCOMPLEX} is returned.
+	 */
+	private static T_DCOMPLEX toODSDoubleComplex(DoubleComplex input) {
+		return input == null ? null : new T_DCOMPLEX(input.real(), input.imaginary());
+	}
+
+	/**
+	 * Converts given {@link T_ExternalReference[]} to {@link FileLink[]}.
+	 *
+	 * @param input The {@code T_ExternalReference}s.
+	 * @return The converted {@code FileLink}s are returned.
+	 */
+	private static FileLink[] fromODSExternalReferenceSeq(T_ExternalReference[] input) {
+		List<FileLink> result = new ArrayList<>();
+		if (input != null) {
+			for (T_ExternalReference value : input) {
+				result.add(fromODSExternalReference(value));
+			}
+		}
+
+		return result.toArray(new FileLink[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link T_ExternalReference} to {@link FileLink}.
+	 *
+	 * @param input The {@code T_ExternalReference}.
+	 * @return The converted {@code FileLink} is returned.
+	 */
+	private static FileLink fromODSExternalReference(T_ExternalReference input) {
+		if (input == null) {
+			return null;
+		}
+		return FileLink.newRemote(input.location, new MimeType(input.mimeType), input.description);
+	}
+
+	/**
+	 * Converts given {@link FileLink[]} to {@link T_ExternalReference[]}.
+	 *
+	 * @param input The {@code FileLink}s.
+	 * @return The converted {@code T_ExternalReference}s are returned.
+	 */
+	private static T_ExternalReference[] toODSExternalReferenceSeq(FileLink[] input) {
+		List<T_ExternalReference> result = new ArrayList<>(input.length);
+		for (FileLink value : input) {
+			result.add(toODSExternalReference(value));
+		}
+
+		return result.toArray(new T_ExternalReference[result.size()]);
+	}
+
+	/**
+	 * Converts given {@link FileLink} to {@link T_ExternalReference}.
+	 *
+	 * @param input The {@code FileLink}.
+	 * @return The converted {@code T_ExternalReference} is returned.
+	 */
+	private static T_ExternalReference toODSExternalReference(FileLink input) {
+		if (input == null) {
+			return new T_ExternalReference("", "", "");
+		}
+		String remotePath = input.isRemote() ? input.getRemotePath() : "";
+		return new T_ExternalReference(input.getDescription(), input.getMimeType().toString(), remotePath);
+	}
+
+	/**
+	 * Converts given {@link Blob} to {@link Object}.
+	 *
+	 * @param input The {@code Blob}
+	 * @return The converted {@code Object} is returned.
+	 */
+	private static Object fromODSBlob(Blob input) {
+		throw new UnsupportedOperationException("NOT YET IMPLEMENTED");
+	}
+
+	/**
+	 * Converts given object to {@link Blob}.
+	 *
+	 * @param input The object.
+	 * @return The converted {@code Blob} is returned.
+	 */
+	private static Blob toODSBlob(Object input) {
+		throw new UnsupportedOperationException("NOT YET IMPLEMENTED");
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnum.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnum.java
new file mode 100755
index 0000000..2bf11d9
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnum.java
@@ -0,0 +1,34 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.utils;
+
+import org.eclipse.mdm.api.base.model.EnumerationValue;
+
+/**
+ * Special enumeration class for ODS enumerations
+ *
+ */
+public class ODSEnum extends EnumerationValue {
+	/**
+	 * Constructor
+	 * 
+	 * @param name:    the text representation of the enumeration value
+	 * @param ordinal: the numeric representation of the enumeration value
+	 */
+	public ODSEnum(String name, int ordinal) {
+		super(name, ordinal);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnumerations.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnumerations.java
new file mode 100644
index 0000000..76cc4d5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSEnumerations.java
@@ -0,0 +1,465 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.utils;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.mdm.api.base.model.AxisType;
+import org.eclipse.mdm.api.base.model.EnumRegistry;
+import org.eclipse.mdm.api.base.model.Enumeration;
+import org.eclipse.mdm.api.base.model.EnumerationValue;
+import org.eclipse.mdm.api.base.model.Interpolation;
+import org.eclipse.mdm.api.base.model.ScalarType;
+import org.eclipse.mdm.api.base.model.SequenceRepresentation;
+import org.eclipse.mdm.api.base.model.TypeSpecification;
+import org.eclipse.mdm.api.base.model.VersionState;
+
+/**
+ * Utility class for enumeration constant conversions from/to ODS types.
+ *
+ * @since 1.0.0
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ */
+public final class ODSEnumerations {
+
+	// ======================================================================
+	// Class variables
+	// ======================================================================
+
+	private static final String SCALAR_TYPE_NAME = "datatype_enum";
+	private static final String STATE_NAME = "valid_enum";
+	private static final String INTERPOLATION_NAME = "interpolation_enum";
+	private static final String AXIS_TYPE_NAME = "axistype";
+	private static final String TYPE_SPECIFICATION_NAME = "typespec_enum";
+	private static final String SEQUENCE_REPRESENTATION_NAME = "seq_rep_enum";
+
+	// ======================================================================
+	// Constructors
+	// ======================================================================
+
+	/**
+	 * Constructor.
+	 */
+	private ODSEnumerations() {
+	}
+
+	// ======================================================================
+	// Public methods
+	// ======================================================================
+
+	/**
+	 * Returns the enumeration class identified by given name.
+	 *
+	 * @param <E>  The enumeration type.
+	 * @param name The ODS name of the requested enumeration class.
+	 * @return The corresponding enumeration class is returned.
+	 * @throws IllegalArgumentException Thrown if ODS enumeration name is unknown.
+	 */
+	// FIXME (Florian Schmitt): can we do this simpler?
+	public static Enumeration<? extends EnumerationValue> getEnumObj(String name) {
+		EnumRegistry er = EnumRegistry.getInstance();
+		if (SCALAR_TYPE_NAME.equals(name)) {
+			return (er.get(EnumRegistry.SCALAR_TYPE));
+		} else if (STATE_NAME.equals(name)) {
+			return (er.get(EnumRegistry.VERSION_STATE));
+		} else if (INTERPOLATION_NAME.equals(name)) {
+			return (er.get(EnumRegistry.INTERPOLATION));
+		} else if (AXIS_TYPE_NAME.equals(name)) {
+			return (er.get(EnumRegistry.AXIS_TYPE));
+		} else if (TYPE_SPECIFICATION_NAME.equals(name)) {
+			return (er.get(EnumRegistry.TYPE_SPECIFICATION));
+		} else if (SEQUENCE_REPRESENTATION_NAME.equals(name)) {
+			return (er.get(EnumRegistry.SEQUENCE_REPRESENTATION));
+		} else {
+			return er.get(name);
+		}
+	}
+
+	/**
+	 * Returns the ODS enumeration name for given enumeration class.
+	 *
+	 * @param enumObj The enumeration object.
+	 * @return The corresponding ODS enumeration name is returned.
+	 * @throws IllegalArgumentException Thrown if enumeration class is unknown.
+	 */
+	public static String getEnumName(Enumeration<?> enumObj) {
+		if (enumObj == null) {
+			throw new IllegalArgumentException("EnumerationValue class is not allowed to be null.");
+		} else if (EnumRegistry.SCALAR_TYPE.equals(enumObj.getName())) {
+			return SCALAR_TYPE_NAME;
+		} else if (EnumRegistry.VERSION_STATE.equals(enumObj.getName())) {
+			return STATE_NAME;
+		} else if (EnumRegistry.INTERPOLATION.equals(enumObj.getName())) {
+			return INTERPOLATION_NAME;
+		} else if (EnumRegistry.AXIS_TYPE.equals(enumObj.getName())) {
+			return AXIS_TYPE_NAME;
+		} else if (EnumRegistry.TYPE_SPECIFICATION.equals(enumObj.getName())) {
+			return TYPE_SPECIFICATION_NAME;
+		} else if (EnumRegistry.SEQUENCE_REPRESENTATION.equals(enumObj.getName())) {
+			return SEQUENCE_REPRESENTATION_NAME;
+		} else {
+			return enumObj.getName();
+		}
+	}
+
+	// ======================================================================
+	// Package methods
+	// ======================================================================
+
+	/**
+	 * Converts given ODS enumeration value using given enumeration class to the
+	 * corresponding enumeration constant.
+	 *
+	 * @param <E>       The enumeration type.
+	 * @param enumClass The enumeration class.
+	 * @param value     The ODS enumeration value.
+	 * @return The corresponding enumeration constant is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	@SuppressWarnings("unchecked")
+	// FIXME: cant we have this easier?
+	static <E extends EnumerationValue> E fromODSEnum(Enumeration<E> enumObj, int value) {
+		if (enumObj == null) {
+			throw new IllegalArgumentException("EnumerationValue class is not allowed to be null.");
+		} else if (EnumRegistry.SCALAR_TYPE.equals(enumObj.getName())) {
+			return (E) fromODSScalarType(value);
+		} else if (EnumRegistry.SEQUENCE_REPRESENTATION.equals(enumObj.getName())) {
+			return (E) fromODSSequenceRepresentation(value);
+		} else {
+			return (E) fromODSEnumByOrdinal(enumObj, value);
+		}
+	}
+
+	/**
+	 * Converts given ODS enumeration values using given enumeration class to the
+	 * corresponding enumeration constants.
+	 *
+	 * @param <E>       The enumeration type.
+	 * @param enumClass The enumeration class.
+	 * @param values    The ODS enumeration values.
+	 * @return The corresponding enumeration constants are returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	@SuppressWarnings("unchecked")
+	static <E extends EnumerationValue> E[] fromODSEnumSeq(Enumeration<?> enumObj, int[] values) {
+		if (enumObj == null) {
+			throw new IllegalArgumentException("EnumerationValue class is not allowed to be null.");
+		} else if (EnumRegistry.SCALAR_TYPE.equals(enumObj.getName())) {
+			List<E> scalarTypes = new ArrayList<>(values.length);
+			for (int value : values) {
+				scalarTypes.add((E) fromODSScalarType(value));
+			}
+			return (E[]) scalarTypes.toArray(new ScalarType[values.length]);
+		} else if (EnumRegistry.SEQUENCE_REPRESENTATION.equals(enumObj.getName())) {
+			List<E> sequenceRepresentations = new ArrayList<>(values.length);
+			for (int value : values) {
+				sequenceRepresentations.add((E) fromODSSequenceRepresentation(value));
+			}
+			return (E[]) sequenceRepresentations.toArray(new SequenceRepresentation[values.length]);
+		} else {
+			return (E[]) fromODSEnumSeqByOrdinal(enumObj, values);
+		}
+	}
+
+	/**
+	 * Converts given enumeration constant to the corresponding ODS enumeration
+	 * value.
+	 *
+	 * @param <E>      The enumeration type.
+	 * @param constant The enumeration constant.
+	 * @return The corresponding ODS enumeration value is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	static <E extends EnumerationValue> int toODSEnum(E constant) {
+		if (constant == null) {
+			return 0;
+		} else if (constant instanceof ScalarType) {
+			return toODSScalarType((ScalarType) constant);
+		} else if (constant instanceof VersionState || constant instanceof Interpolation || constant instanceof AxisType
+				|| constant instanceof TypeSpecification) {
+			// NOTE: Ordinal numbers map directly to the corresponding ODS
+			// enumeration constant value.
+			return constant.ordinal();
+		} else if (constant instanceof SequenceRepresentation) {
+			return toODSSequenceRepresentation((SequenceRepresentation) constant);
+		}
+
+		throw new IllegalArgumentException(
+				"EnumerationValue mapping for type '" + constant.getClass().getSimpleName() + "' does not exist.");
+	}
+
+	/**
+	 * Converts given enumeration constants to the corresponding ODS enumeration
+	 * values.
+	 *
+	 * @param <E>       The enumeration type.
+	 * @param constants The enumeration constants.
+	 * @return The corresponding ODS enumeration values are returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	static <E extends EnumerationValue> int[] toODSEnumSeq(E[] constants) {
+		if (constants == null) {
+			return new int[0];
+		}
+
+		int[] values = new int[constants.length];
+		if (constants instanceof ScalarType[]) {
+			for (int i = 0; i < values.length; i++) {
+				values[i] = toODSScalarType((ScalarType) constants[i]);
+			}
+		} else if (constants instanceof VersionState[] || constants instanceof Interpolation[]
+				|| constants instanceof AxisType[] || constants instanceof TypeSpecification[]) {
+			for (int i = 0; i < values.length; i++) {
+				// NOTE: Ordinal numbers directly map to the corresponding ODS
+				// enumeration constant value.
+				// FIXME: do we really want this?
+				values[i] = ((EnumerationValue) constants[i]).ordinal();
+			}
+		} else if (constants instanceof SequenceRepresentation[]) {
+			for (int i = 0; i < values.length; i++) {
+				values[i] = toODSSequenceRepresentation((SequenceRepresentation) constants[i]);
+			}
+		} else {
+			throw new IllegalArgumentException("EnumerationValue mapping for type '"
+					+ constants.getClass().getComponentType().getSimpleName() + "' does not exist.");
+		}
+
+		return values;
+	}
+
+	// ======================================================================
+	// Private methods
+	// ======================================================================
+
+	/**
+	 * Converts given ODS enumeration value to the corresponding {@link ScalarType}
+	 * constant.
+	 *
+	 * @param value The ODS enumeration value.
+	 * @return The corresponding {@code ScalarType} constant is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	private static ScalarType fromODSScalarType(int value) {
+		if (value == 0) {
+			return ScalarType.UNKNOWN;
+		} else if (value == 1) {
+			return ScalarType.STRING;
+		} else if (value == 2) {
+			return ScalarType.SHORT;
+		} else if (value == 3) {
+			return ScalarType.FLOAT;
+		} else if (value == 4) {
+			return ScalarType.BOOLEAN;
+		} else if (value == 5) {
+			return ScalarType.BYTE;
+		} else if (value == 6) {
+			return ScalarType.INTEGER;
+		} else if (value == 7) {
+			return ScalarType.DOUBLE;
+		} else if (value == 8) {
+			return ScalarType.LONG;
+		} else if (value == 10) {
+			return ScalarType.DATE;
+		} else if (value == 11) {
+			return ScalarType.BYTE_STREAM;
+		} else if (value == 12) {
+			return ScalarType.BLOB;
+		} else if (value == 13) {
+			return ScalarType.FLOAT_COMPLEX;
+		} else if (value == 14) {
+			return ScalarType.DOUBLE_COMPLEX;
+		} else if (value == 28) {
+			return ScalarType.FILE_LINK;
+		} else if (value == 30) {
+			return ScalarType.ENUMERATION;
+		}
+
+		throw new IllegalArgumentException("Unable to map ODS enumeration vaue '" + value + "' to constant of type '"
+				+ ScalarType.class.getSimpleName() + "'.");
+	}
+
+	/**
+	 * Converts given {@link ScalarType} to the corresponding ODS enumeration value.
+	 *
+	 * @param scalarType The {@code ScalarType}.
+	 * @return The corresponding ODS enumeration value is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	private static int toODSScalarType(ScalarType scalarType) {
+		if (ScalarType.UNKNOWN == scalarType) {
+			return 0;
+		} else if (ScalarType.STRING == scalarType) {
+			return 1;
+		} else if (ScalarType.SHORT == scalarType) {
+			return 2;
+		} else if (ScalarType.FLOAT == scalarType) {
+			return 3;
+		} else if (ScalarType.BOOLEAN == scalarType) {
+			return 4;
+		} else if (ScalarType.BYTE == scalarType) {
+			return 5;
+		} else if (ScalarType.INTEGER == scalarType) {
+			return 6;
+		} else if (ScalarType.DOUBLE == scalarType) {
+			return 7;
+		} else if (ScalarType.LONG == scalarType) {
+			return 8;
+		} else if (ScalarType.DATE == scalarType) {
+			return 10;
+		} else if (ScalarType.BYTE_STREAM == scalarType) {
+			return 11;
+		} else if (ScalarType.BLOB == scalarType) {
+			return 12;
+		} else if (ScalarType.FLOAT_COMPLEX == scalarType) {
+			return 13;
+		} else if (ScalarType.DOUBLE_COMPLEX == scalarType) {
+			return 14;
+		} else if (ScalarType.FILE_LINK == scalarType) {
+			return 28;
+		} else if (ScalarType.ENUMERATION == scalarType) {
+			return 30;
+		}
+
+		throw new IllegalArgumentException("Unable to map enumeration constant '" + scalarType + "' of type '"
+				+ ScalarType.class.getSimpleName() + "' to ODS enumeration value.");
+	}
+
+	/**
+	 * Converts given ODS enumeration value to the corresponding
+	 * {@link SequenceRepresentation} constant.
+	 *
+	 * @param value The ODS enumeration value.
+	 * @return The corresponding {@code SequenceRepresentation} constant is
+	 *         returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	private static SequenceRepresentation fromODSSequenceRepresentation(int value) {
+		if (value == 0) {
+			return SequenceRepresentation.EXPLICIT;
+		} else if (value == 1) {
+			return SequenceRepresentation.IMPLICIT_CONSTANT;
+		} else if (value == 2) {
+			return SequenceRepresentation.IMPLICIT_LINEAR;
+		} else if (value == 3) {
+			return SequenceRepresentation.IMPLICIT_SAW;
+		} else if (value == 4) {
+			return SequenceRepresentation.RAW_LINEAR;
+		} else if (value == 5) {
+			return SequenceRepresentation.RAW_POLYNOMIAL;
+		} else if (value == 7) {
+			return SequenceRepresentation.EXPLICIT_EXTERNAL;
+		} else if (value == 8) {
+			return SequenceRepresentation.RAW_LINEAR_EXTERNAL;
+		} else if (value == 9) {
+			return SequenceRepresentation.RAW_POLYNOMIAL_EXTERNAL;
+		} else if (value == 10) {
+			return SequenceRepresentation.RAW_LINEAR_CALIBRATED;
+		} else if (value == 11) {
+			return SequenceRepresentation.RAW_LINEAR_CALIBRATED_EXTERNAL;
+		}
+
+		throw new IllegalArgumentException("Unable to map ODS enumeration vaue '" + value + "' to constant of type '"
+				+ SequenceRepresentation.class.getSimpleName() + "'.");
+	}
+
+	/**
+	 * Converts given {@link SequenceRepresentation} to the corresponding ODS
+	 * enumeration value.
+	 *
+	 * @param sequenceRepresentation The {@code SequenceRepresentation}.
+	 * @return The corresponding ODS enumeration value is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	private static int toODSSequenceRepresentation(SequenceRepresentation sequenceRepresentation) {
+		if (SequenceRepresentation.EXPLICIT == sequenceRepresentation) {
+			return 0;
+		} else if (SequenceRepresentation.IMPLICIT_CONSTANT == sequenceRepresentation) {
+			return 1;
+		} else if (SequenceRepresentation.IMPLICIT_LINEAR == sequenceRepresentation) {
+			return 2;
+		} else if (SequenceRepresentation.IMPLICIT_SAW == sequenceRepresentation) {
+			return 3;
+		} else if (SequenceRepresentation.RAW_LINEAR == sequenceRepresentation) {
+			return 4;
+		} else if (SequenceRepresentation.RAW_POLYNOMIAL == sequenceRepresentation) {
+			return 5;
+		} else if (SequenceRepresentation.EXPLICIT_EXTERNAL == sequenceRepresentation) {
+			return 7;
+		} else if (SequenceRepresentation.RAW_LINEAR_EXTERNAL == sequenceRepresentation) {
+			return 8;
+		} else if (SequenceRepresentation.RAW_POLYNOMIAL_EXTERNAL == sequenceRepresentation) {
+			return 9;
+		} else if (SequenceRepresentation.RAW_LINEAR_CALIBRATED == sequenceRepresentation) {
+			return 10;
+		} else if (SequenceRepresentation.RAW_LINEAR_CALIBRATED_EXTERNAL == sequenceRepresentation) {
+			return 11;
+		}
+
+		throw new IllegalArgumentException("Unable to map enumeration constant '" + sequenceRepresentation
+				+ "' of type '" + SequenceRepresentation.class.getSimpleName() + "' to ODS enumeration value.");
+	}
+
+	/**
+	 * Converts given ODS enumeration value to the corresponding enumeration
+	 * constant. The ODS enumeration value is used as the ordinal number of the
+	 * requested enumeration constant.
+	 *
+	 * @param <E>       The enumeration type.
+	 * @param enumClass The enumeration class.
+	 * @param value     The ODS enumeration value.
+	 * @return The corresponding enumeration constant is returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	private static <E extends EnumerationValue> E fromODSEnumByOrdinal(Enumeration<E> enumObj, int value) {
+		// NOTE: Ordinal numbers directly map to the corresponding ODS
+		// enumeration constant value.
+		E enumvalue = enumObj.valueOf(value);
+		if (enumvalue == null) {
+			throw new IllegalArgumentException();
+		}
+		return enumvalue;
+	}
+
+	/**
+	 * Converts given ODS enumeration values to the corresponding enumeration
+	 * constants. The ODS enumeration values are used as the ordinal numbers of the
+	 * requested enumeration constants.
+	 *
+	 * @param <E>       The enumeration type.
+	 * @param enumClass The enumeration class.
+	 * @param values    The ODS enumeration values.
+	 * @return The corresponding enumeration constants are returned.
+	 * @throws IllegalArgumentException Thrown if conversion not possible.
+	 */
+	@SuppressWarnings("unchecked")
+	private static <E extends EnumerationValue> E[] fromODSEnumSeqByOrdinal(Enumeration<E> enumObj, int[] values) {
+		List<E> enumValues = new ArrayList<>(values.length);
+
+		for (int value : values) {
+			// NOTE: Ordinal numbers directly map to the corresponding ODS
+			// enumeration constant value.
+			E enumvalue = enumObj.valueOf(value);
+			if (enumvalue == null) {
+				throw new IllegalArgumentException();
+			}
+			enumValues.add(enumvalue);
+		}
+
+		return enumValues.toArray((E[]) Array.newInstance(enumObj.getClass(), values.length));
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSUtils.java b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSUtils.java
new file mode 100644
index 0000000..8cd50f3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSUtils.java
@@ -0,0 +1,138 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.utils;
+
+import org.asam.ods.AggrFunc;
+import org.asam.ods.DataType;
+import org.asam.ods.SelOpcode;
+import org.asam.ods.SelOperator;
+import org.eclipse.mdm.api.base.adapter.RelationType;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.BooleanOperator;
+import org.eclipse.mdm.api.base.query.BracketOperator;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.JoinType;
+
+import com.google.common.collect.ImmutableBiMap;
+
+/**
+ * Utility class provides bidirectional mappings for ODS types
+ *
+ * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
+ * @since 1.0.0
+ */
+public abstract class ODSUtils {
+	/**
+	 * Maps {@link RelationType} to the corresponding ODS {@link RelationType}.
+	 */
+	public static final ImmutableBiMap<RelationType, org.asam.ods.RelationType> RELATIONSHIPS = ImmutableBiMap.<RelationType, org.asam.ods.RelationType>builder()
+			.put(RelationType.FATHER_CHILD, org.asam.ods.RelationType.FATHER_CHILD)
+			.put(RelationType.INFO, org.asam.ods.RelationType.INFO)
+			.put(RelationType.INHERITANCE, org.asam.ods.RelationType.INHERITANCE).build();
+
+	/**
+	 * Maps {@link Aggregation} to the corresponding ODS {@link AggrFunc}.
+	 */
+	public static final ImmutableBiMap<Aggregation, AggrFunc> AGGREGATIONS = ImmutableBiMap
+			.<Aggregation, AggrFunc>builder().put(Aggregation.NONE, AggrFunc.NONE)
+			.put(Aggregation.COUNT, AggrFunc.COUNT).put(Aggregation.DISTINCT_COUNT, AggrFunc.DCOUNT)
+			.put(Aggregation.MINIMUM, AggrFunc.MIN).put(Aggregation.MAXIMUM, AggrFunc.MAX)
+			.put(Aggregation.AVERAGE, AggrFunc.AVG).put(Aggregation.DEVIATION, AggrFunc.STDDEV)
+			.put(Aggregation.SUM, AggrFunc.SUM).put(Aggregation.DISTINCT, AggrFunc.DISTINCT).build();
+
+	/**
+	 * Maps {@link ContextType} to the corresponding ODS {@link String}.
+	 */
+	public static final ImmutableBiMap<ContextType, String> CONTEXTTYPES = ImmutableBiMap.<ContextType, String>builder()
+			.put(ContextType.UNITUNDERTEST, "UnitUnderTest").put(ContextType.TESTSEQUENCE, "TestSequence")
+			.put(ContextType.TESTEQUIPMENT, "TestEquipment").build();
+
+	/**
+	 * Maps {@link ComparisonOperator} to the corresponding ODS {@link SelOpcode}.
+	 */
+	public static final ImmutableBiMap<ComparisonOperator, SelOpcode> OPERATIONS = ImmutableBiMap
+			.<ComparisonOperator, SelOpcode>builder().put(ComparisonOperator.LIKE, SelOpcode.LIKE)
+			.put(ComparisonOperator.CASE_INSENSITIVE_LIKE, SelOpcode.CI_LIKE)
+			.put(ComparisonOperator.NOT_LIKE, SelOpcode.NOTLIKE)
+			.put(ComparisonOperator.CASE_INSENSITIVE_NOT_LIKE, SelOpcode.CI_NOTLIKE)
+			.put(ComparisonOperator.EQUAL, SelOpcode.EQ).put(ComparisonOperator.CASE_INSENSITIVE_EQUAL, SelOpcode.CI_EQ)
+			.put(ComparisonOperator.NOT_EQUAL, SelOpcode.NEQ)
+			.put(ComparisonOperator.CASE_INSENSITIVE_NOT_EQUAL, SelOpcode.CI_NEQ)
+			.put(ComparisonOperator.GREATER_THAN, SelOpcode.GT)
+			.put(ComparisonOperator.CASE_INSENSITIVE_GREATER_THAN, SelOpcode.CI_GT)
+			.put(ComparisonOperator.GREATER_THAN_OR_EQUAL, SelOpcode.GTE)
+			.put(ComparisonOperator.CASE_INSENSITIVE_GREATER_THAN_OR_EQUAL, SelOpcode.CI_GTE)
+			.put(ComparisonOperator.LESS_THAN, SelOpcode.LT)
+			.put(ComparisonOperator.CASE_INSENSITIVE_LESS_THAN, SelOpcode.CI_LT)
+			.put(ComparisonOperator.LESS_THAN_OR_EQUAL, SelOpcode.LTE)
+			.put(ComparisonOperator.CASE_INSENSITIVE_LESS_THAN_OR_EQUAL, SelOpcode.CI_LTE)
+			.put(ComparisonOperator.IS_NULL, SelOpcode.IS_NULL)
+			.put(ComparisonOperator.IS_NOT_NULL, SelOpcode.IS_NOT_NULL).put(ComparisonOperator.IN_SET, SelOpcode.INSET)
+			.put(ComparisonOperator.CASE_INSENSITIVE_IN_SET, SelOpcode.CI_INSET)
+			.put(ComparisonOperator.NOT_IN_SET, SelOpcode.NOTINSET)
+			.put(ComparisonOperator.CASE_INSENSITIVE_NOT_IN_SET, SelOpcode.CI_NOTINSET)
+			.put(ComparisonOperator.BETWEEN, SelOpcode.BETWEEN).build();
+
+	/**
+	 * Maps {@link BooleanOperator} to the corresponding ODS {@link SelOperator}.
+	 */
+	public static final ImmutableBiMap<BooleanOperator, SelOperator> OPERATORS = ImmutableBiMap
+			.<BooleanOperator, SelOperator>builder().put(BooleanOperator.AND, SelOperator.AND)
+			.put(BooleanOperator.OR, SelOperator.OR).put(BooleanOperator.NOT, SelOperator.NOT).build();
+
+	/**
+	 * Maps {@link BracketOperator} to the corresponding ODS {@link SelOperator}.
+	 */
+	public static final ImmutableBiMap<BracketOperator, SelOperator> BRACKETOPERATORS = ImmutableBiMap
+			.<BracketOperator, SelOperator>builder().put(BracketOperator.OPEN, SelOperator.OPEN)
+			.put(BracketOperator.CLOSE, SelOperator.CLOSE).build();
+
+	/**
+	 * Maps {@link ValueType} to the corresponding ODS {@link DataType}.
+	 */
+	public static final ImmutableBiMap<ValueType<?>, DataType> VALUETYPES = ImmutableBiMap
+			.<ValueType<?>, DataType>builder().put(ValueType.UNKNOWN, DataType.DT_UNKNOWN)
+			.put(ValueType.STRING, DataType.DT_STRING).put(ValueType.STRING_SEQUENCE, DataType.DS_STRING)
+			.put(ValueType.DATE, DataType.DT_DATE).put(ValueType.DATE_SEQUENCE, DataType.DS_DATE)
+			.put(ValueType.BOOLEAN, DataType.DT_BOOLEAN).put(ValueType.BOOLEAN_SEQUENCE, DataType.DS_BOOLEAN)
+			.put(ValueType.BYTE, DataType.DT_BYTE).put(ValueType.BYTE_SEQUENCE, DataType.DS_BYTE)
+			.put(ValueType.SHORT, DataType.DT_SHORT).put(ValueType.SHORT_SEQUENCE, DataType.DS_SHORT)
+			.put(ValueType.INTEGER, DataType.DT_LONG).put(ValueType.INTEGER_SEQUENCE, DataType.DS_LONG)
+			.put(ValueType.LONG, DataType.DT_LONGLONG).put(ValueType.LONG_SEQUENCE, DataType.DS_LONGLONG)
+			.put(ValueType.FLOAT, DataType.DT_FLOAT).put(ValueType.FLOAT_SEQUENCE, DataType.DS_FLOAT)
+			.put(ValueType.DOUBLE, DataType.DT_DOUBLE).put(ValueType.DOUBLE_SEQUENCE, DataType.DS_DOUBLE)
+			.put(ValueType.BYTE_STREAM, DataType.DT_BYTESTR).put(ValueType.BYTE_STREAM_SEQUENCE, DataType.DS_BYTESTR)
+			.put(ValueType.FLOAT_COMPLEX, DataType.DT_COMPLEX)
+			.put(ValueType.FLOAT_COMPLEX_SEQUENCE, DataType.DS_COMPLEX)
+			.put(ValueType.DOUBLE_COMPLEX, DataType.DT_DCOMPLEX)
+			.put(ValueType.DOUBLE_COMPLEX_SEQUENCE, DataType.DS_DCOMPLEX).put(ValueType.ENUMERATION, DataType.DT_ENUM)
+			.put(ValueType.ENUMERATION_SEQUENCE, DataType.DS_ENUM)
+			.put(ValueType.FILE_LINK, DataType.DT_EXTERNALREFERENCE)
+			.put(ValueType.FILE_LINK_SEQUENCE, DataType.DS_EXTERNALREFERENCE).put(ValueType.BLOB, DataType.DT_BLOB)
+			.build();
+
+	/**
+	 * Maps {@link JoinType} to the corresponding ODS {@link org.asam.ods.JoinType}.
+	 */
+	public static final ImmutableBiMap<JoinType, org.asam.ods.JoinType> JOINS = ImmutableBiMap.<JoinType, org.asam.ods.JoinType>builder()
+			.put(JoinType.INNER, org.asam.ods.JoinType.JTDEFAULT).put(JoinType.OUTER, org.asam.ods.JoinType.JTOUTER)
+			.build();
+
+	public static boolean isValidID(String instanceID) {
+		return instanceID != null && !instanceID.isEmpty() && !"0".equals(instanceID);
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/main/proto/notification.proto b/org.eclipse.mdm.api.odsadapter/src/main/proto/notification.proto
new file mode 100644
index 0000000..7503205
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/main/proto/notification.proto
@@ -0,0 +1,49 @@
+/********************************************************************************

+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation

+ *

+ * See the NOTICE file(s) distributed with this work for additional

+ * information regarding copyright ownership.

+ *

+ * This program and the accompanying materials are made available under the

+ * terms of the Eclipse Public License v. 2.0 which is available at

+ * http://www.eclipse.org/legal/epl-2.0.

+ *

+ * SPDX-License-Identifier: EPL-2.0

+ *

+ ********************************************************************************/

+ 
+syntax = "proto3";
+
+package com.peaksolution.ods.notification;
+option java_package = "com.peaksolution.ods.notification.protobuf";
+option java_outer_classname = "NotificationProtos";
+
+import "google/protobuf/timestamp.proto";
+
+enum ModificationType {
+  NEW = 0;
+  MODIFY = 1;
+  DELETE = 2;
+  MODEL = 3;
+  SECURITY = 4;
+}
+	
+message Registration {
+	enum NotificationMode {
+		PUSH = 0;
+		PULL = 1;
+	}
+	
+	NotificationMode mode = 1;
+	repeated ModificationType type = 2;
+	repeated int64 aid = 3;
+}
+
+message Notification {
+	ModificationType type = 1;
+	string uuid = 2;
+	google.protobuf.Timestamp creation = 3;
+	int64 userId = 4;
+	int64 aid = 5;
+	repeated int64 iid = 6;
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java
new file mode 100644
index 0000000..048089c
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java
@@ -0,0 +1,169 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+/**
+ * Aggregation test
+ *
+ * @since 1.0.0
+ * @author maf, Peak Solution GmbH
+ */
+@Ignore
+// FIXME 11.01.2018: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class AggregationTest {
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	@org.junit.Test
+	public void testQueryIdAndNameNoAggregation() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		QueryService queryService = context.getQueryService().get();
+
+		EntityType unitEntityType = modelManager.getEntityType(Unit.class);
+		Attribute idAttribute = unitEntityType.getAttribute("Id");
+		Attribute nameAttribute = unitEntityType.getAttribute("Name");
+
+		List<Result> listRes = queryService.createQuery().select(idAttribute).select(nameAttribute).fetch();
+
+		assertThat(listRes.size()).isGreaterThanOrEqualTo(1);
+		assertThat(listRes.get(0).getValue(idAttribute).getValueType()).isEqualTo(ValueType.STRING);
+		// Test retrieving attribute value with Aggregation.NONE (should yield the same
+		// result as with no aggregation):
+		assertThat(listRes.get(0).getValue(idAttribute, Aggregation.NONE).getValueType()).isEqualTo(ValueType.STRING);
+		assertThat(listRes.get(0).getValue(nameAttribute).getValueType()).isEqualTo(ValueType.STRING);
+	}
+
+	@org.junit.Test
+	public void testQueryIdWithAggregation() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		QueryService queryService = context.getQueryService().get();
+
+		EntityType unitEntityType = modelManager.getEntityType(Unit.class);
+		Attribute idAttribute = unitEntityType.getAttribute("Id");
+
+		List<Result> listRes = queryService.createQuery().select(idAttribute, Aggregation.MAXIMUM) // should be a string
+																									// in result, just
+																									// like
+																									// non-aggregated Id
+																									// attribute
+				.select(idAttribute, Aggregation.AVERAGE) // should be a numeric value in result
+				.fetch();
+
+		assertThat(listRes.size()).isGreaterThanOrEqualTo(1);
+		assertThat(listRes.get(0).getValue(idAttribute, Aggregation.MAXIMUM).getValueType())
+				.isEqualTo(ValueType.STRING);
+		assertThat(listRes.get(0).getValue(idAttribute, Aggregation.AVERAGE).getValueType()).isEqualTo(ValueType.LONG);
+	}
+
+	@org.junit.Test
+	public void testQueryFactorWithAggregation() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		QueryService queryService = context.getQueryService().get();
+
+		EntityType unitEntityType = modelManager.getEntityType(Unit.class);
+		Attribute factorAttribute = unitEntityType.getAttribute("Factor");
+
+		List<Result> listRes = queryService.createQuery().select(factorAttribute, Aggregation.COUNT)
+				.group(factorAttribute).fetch();
+
+		assertThat(listRes.size()).isGreaterThanOrEqualTo(1);
+		assertThat(listRes.get(0).getValue(factorAttribute, Aggregation.COUNT).getValueType())
+				.isEqualTo(ValueType.INTEGER);
+	}
+
+	@org.junit.Test
+	public void testQueryFactorWithAndWithoutAggregation() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		QueryService queryService = context.getQueryService().get();
+
+		EntityType unitEntityType = modelManager.getEntityType(Unit.class);
+		Attribute factorAttribute = unitEntityType.getAttribute("Factor");
+
+		List<Result> listRes = queryService.createQuery().select(factorAttribute)
+				.select(factorAttribute, Aggregation.SUM).group(factorAttribute).fetch();
+
+		assertThat(listRes.size()).isGreaterThanOrEqualTo(1);
+		assertThat(listRes.get(0).getValue(factorAttribute).getValueType()).isEqualTo(ValueType.DOUBLE);
+		assertThat(listRes.get(0).getValue(factorAttribute, Aggregation.SUM).getValueType())
+				.isEqualTo(ValueType.DOUBLE);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java
new file mode 100644
index 0000000..483b1d0
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java
@@ -0,0 +1,356 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+/**
+ * JoinType test
+ *
+ * @since 1.0.0
+ * @author jst, Peak Solution GmbH
+ */
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class JoinTest {
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	@org.junit.Test
+	public void findTestFromTestStepId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(TestStep.class);
+
+		List<Test> list = searchService.fetch(Test.class, Filter.idOnly(et, "37"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestFromMeasurementId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Measurement.class);
+
+		List<Test> list = searchService.fetch(Test.class, Filter.idOnly(et, "65"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestFromChannelGroupId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(ChannelGroup.class);
+
+		List<Test> list = searchService.fetch(Test.class, Filter.idOnly(et, "80"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestFromChannelId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Channel.class);
+
+		List<Test> list = searchService.fetch(Test.class, Filter.idOnly(et, "302"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestStepFromTestId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Test.class);
+
+		List<TestStep> list = searchService.fetch(TestStep.class, Filter.idOnly(et, "28"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestStepFromMeasurementId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Measurement.class);
+
+		List<TestStep> list = searchService.fetch(TestStep.class, Filter.idOnly(et, "65"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestStepFromChannelGroupId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(ChannelGroup.class);
+
+		List<Test> list = searchService.fetch(Test.class, Filter.idOnly(et, "80"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findTestStepFromChannelId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Channel.class);
+
+		List<TestStep> list = searchService.fetch(TestStep.class, Filter.idOnly(et, "302"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findMeasurementFromTestId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Test.class);
+
+		List<Measurement> list = searchService.fetch(Measurement.class, Filter.idOnly(et, "28"));
+
+		assertEquals(9, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findMeasurementFromTestStepId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(TestStep.class);
+
+		List<Measurement> list = searchService.fetch(Measurement.class, Filter.idOnly(et, "37"));
+
+		assertEquals(9, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findMeasurementFromChannelGroupId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(ChannelGroup.class);
+
+		List<Measurement> list = searchService.fetch(Measurement.class, Filter.idOnly(et, "80"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findMeasurementFromChannelId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Channel.class);
+
+		List<Measurement> list = searchService.fetch(Measurement.class, Filter.idOnly(et, "302"));
+
+		assertEquals(1, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelGroupFromTestId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Test.class);
+
+		List<ChannelGroup> list = searchService.fetch(ChannelGroup.class, Filter.idOnly(et, "28"));
+
+		assertEquals(14, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelGroupFromTestStepId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(TestStep.class);
+
+		List<ChannelGroup> list = searchService.fetch(ChannelGroup.class, Filter.idOnly(et, "37"));
+
+		assertEquals(14, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelGroupFromMeasurementId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Measurement.class);
+
+		List<ChannelGroup> list = searchService.fetch(ChannelGroup.class, Filter.idOnly(et, "65"));
+
+		assertEquals(2, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelGroupFromChannelId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Channel.class);
+
+		List<ChannelGroup> list = searchService.fetch(ChannelGroup.class, Filter.idOnly(et, "302"));
+
+		assertEquals(2, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelFromTestId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Test.class);
+
+		List<Channel> list = searchService.fetch(Channel.class, Filter.idOnly(et, "28"));
+
+		assertEquals(43, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelFromTestStepId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(TestStep.class);
+
+		List<Channel> list = searchService.fetch(Channel.class, Filter.idOnly(et, "37"));
+
+		assertEquals(43, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelFromMeasurementId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(Measurement.class);
+
+		List<Channel> list = searchService.fetch(Channel.class, Filter.idOnly(et, "65"));
+
+		assertEquals(2, list.size());
+		System.out.println(list.size());
+	}
+
+	@org.junit.Test
+	public void findChannelFromChannelGroupId() throws DataAccessException {
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType et = modelManager.getEntityType(ChannelGroup.class);
+
+		List<Channel> list = searchService.fetch(Channel.class, Filter.idOnly(et, "80"));
+
+		assertEquals(2, list.size());
+		System.out.println(list.size());
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java
new file mode 100644
index 0000000..6bd6241
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java
@@ -0,0 +1,442 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.massdata.WriteRequest;
+import org.eclipse.mdm.api.base.massdata.WriteRequestBuilder;
+import org.eclipse.mdm.api.base.model.AxisType;
+import org.eclipse.mdm.api.base.model.BaseEntity;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.ContextComponent;
+import org.eclipse.mdm.api.base.model.ContextRoot;
+import org.eclipse.mdm.api.base.model.ContextType;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.EnumRegistry;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.MimeType;
+import org.eclipse.mdm.api.base.model.PhysicalDimension;
+import org.eclipse.mdm.api.base.model.Quantity;
+import org.eclipse.mdm.api.base.model.ScalarType;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.dflt.model.CatalogComponent;
+import org.eclipse.mdm.api.dflt.model.EntityFactory;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.dflt.model.TemplateComponent;
+import org.eclipse.mdm.api.dflt.model.TemplateRoot;
+import org.eclipse.mdm.api.dflt.model.TemplateTest;
+import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class ODSAdapterTest {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSAdapterTest.class);
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static EntityManager entityManager;
+	private static EntityFactory entityFactory;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+		entityManager = context.getEntityManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
+		entityFactory = context.getEntityFactory()
+				.orElseThrow(() -> new IllegalStateException("Entity manager factory not available."));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	/*
+	 * FIXME this test requires that there is a teststep with id 2, that has a
+	 * unitundertest component called "filetest", that has an empty filelink
+	 * attribute "myextref" and a string attrinute "attr1". remove the comment at
+	 * org.junit.Test if you fulfill these requirements
+	 */
+	// @org.junit.Test
+	public void changeFile() throws Exception {
+		String idteststep = "2";
+		ModelManager modelManager = context.getModelManager().get();
+		SearchService searchService = context.getSearchService().get();
+
+		EntityType etteststep = modelManager.getEntityType(TestStep.class);
+		Transaction transaction;
+
+		transaction = entityManager.startTransaction();
+
+		try {
+			List<TestStep> mealist;
+			mealist = searchService.fetch(TestStep.class, Filter.idOnly(etteststep, idteststep));
+			assertEquals(1, mealist.size());
+			TestStep ts = mealist.get(0);
+			Map<ContextType, ContextRoot> loadContexts = ts.loadContexts(entityManager, ContextType.UNITUNDERTEST);
+			ContextRoot contextRoot = loadContexts.get(ContextType.UNITUNDERTEST);
+			Optional<ContextComponent> contextComponent = contextRoot.getContextComponent("filetest");
+			Value value = contextComponent.get().getValue("myextref");
+			contextComponent.get().getValue("attr1").set("val4711");
+			FileLink fl = FileLink.newRemote("", new MimeType(""), "");
+			FileLink fl2 = (FileLink) value.extract();
+			assertEquals(fl2, fl);
+			List<BaseEntity> toUpdate = new ArrayList<>();
+			toUpdate.add(contextComponent.get());
+			transaction.update(toUpdate);
+			transaction.commit();
+		} catch (RuntimeException e) {
+			transaction.abort();
+			throw e;
+		}
+	}
+
+	@org.junit.Test
+	public void runtTestScript() throws DataAccessException {
+		List<CatalogComponent> catalogComponents = createCatalogComponents();
+		List<TemplateRoot> templateRoots = createTemplateRoots(catalogComponents);
+		List<TemplateTestStep> templateTestSteps = createTemplateTestSteps(templateRoots);
+		TemplateTest templateTest = createTemplateTest(templateTestSteps);
+		PhysicalDimension physicalDimension = entityFactory.createPhysicalDimension("any_physical_dimension");
+		Unit unit = entityFactory.createUnit("any_unit", physicalDimension);
+		Quantity quantity = entityFactory.createQuantity("any_quantity", unit);
+
+		Transaction transaction = entityManager.startTransaction();
+		try {
+			create(transaction, "catalog components", catalogComponents);
+			create(transaction, "template roots", templateRoots);
+			create(transaction, "template test steps", templateTestSteps);
+			create(transaction, "template test", Collections.singletonList(templateTest));
+			create(transaction, "physical dimension", Collections.singletonList(physicalDimension));
+			create(transaction, "unit", Collections.singletonList(unit));
+			create(transaction, "quantity", Collections.singletonList(quantity));
+
+			transaction.commit();
+		} catch (RuntimeException e) {
+			transaction.abort();
+			e.printStackTrace();
+			fail("Unable to create test data due to: " + e.getMessage());
+		}
+
+		List<Project> projects = Collections.emptyList();
+		try {
+			projects = createTestData(templateTest, quantity);
+		} catch (RuntimeException e) {
+			e.printStackTrace();
+		}
+
+		transaction = entityManager.startTransaction();
+		try {
+			// delete in reverse order!
+			if (!projects.isEmpty()) {
+				delete(transaction, "projects and their children", projects);
+			}
+
+			delete(transaction, "quantity", Collections.singletonList(quantity));
+			delete(transaction, "unit", Collections.singletonList(unit));
+			delete(transaction, "physical dimension", Collections.singletonList(physicalDimension));
+			delete(transaction, "template test", Collections.singletonList(templateTest));
+			delete(transaction, "template test steps", templateTestSteps);
+			delete(transaction, "template roots", templateRoots);
+			delete(transaction, "catalog components", catalogComponents);
+
+			transaction.commit();
+		} catch (RuntimeException e) {
+			transaction.abort();
+			fail("Unable to delete test data due to: " + e.getMessage());
+		}
+
+		if (projects.isEmpty()) {
+			fail("Was unable to create test data.");
+		}
+	}
+
+	private List<Project> createTestData(TemplateTest templateTest, Quantity quantity) throws DataAccessException {
+
+		Project project = entityFactory.createProject("simple_project");
+		Pool pool = entityFactory.createPool("simple_pool", project);
+
+		List<Test> tests = createTests(2, pool, templateTest);
+
+		// create measurement test data
+		List<WriteRequest> writeRequests = new ArrayList<>();
+		for (Test test : tests) {
+			for (TestStep testStep : test.getCommissionedTestSteps()) {
+				Optional<TemplateTestStep> templateTestStep = TemplateTestStep.of(testStep);
+				ContextRoot[] contextRoots = new ContextRoot[0];
+				if (templateTestStep.isPresent()) {
+					contextRoots = templateTestStep.get().getTemplateRoots().stream()
+							.map(templateRoot -> entityFactory.createContextRoot(templateRoot))
+							.toArray(ContextRoot[]::new);
+				}
+				for (int i = 1; i < 3; i++) {
+					Measurement measurement = entityFactory.createMeasurement("measurement_" + i, testStep,
+							contextRoots);
+
+					// create channels
+					List<Channel> channels = new ArrayList<>();
+					for (int j = 0; j < 9; j++) {
+						channels.add(entityFactory.createChannel("channel_ " + j, measurement, quantity));
+					}
+
+					// create channel group
+					ChannelGroup channelGroup = entityFactory.createChannelGroup("group", 10, measurement);
+					writeRequests.addAll(createMeasurementData(measurement, channelGroup, channels));
+				}
+			}
+		}
+
+		Transaction transaction = entityManager.startTransaction();
+		try {
+			create(transaction, "project and pool with tests based on teamplates with measurements and mass data",
+					Collections.singleton(project));
+
+			transaction.writeMeasuredValues(writeRequests);
+			transaction.commit();
+			return Collections.singletonList(project);
+		} catch (DataAccessException e) {
+			e.printStackTrace();
+			transaction.abort();
+		}
+
+		return Collections.emptyList();
+	}
+
+	private List<WriteRequest> createMeasurementData(Measurement measurement, ChannelGroup channelGroup,
+			List<Channel> channels) {
+		// set length of the channel value sequence
+		List<WriteRequest> writeRequests = new ArrayList<>();
+
+		// populate channel value write requests - one per channel
+		Collections.sort(channels, (c1, c2) -> c1.getName().compareTo(c2.getName()));
+
+		WriteRequestBuilder wrb = WriteRequest.create(channelGroup, channels.get(0), AxisType.X_AXIS);
+		writeRequests.add(wrb.implicitLinear(ScalarType.FLOAT, 0, 1).independent().build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(1), AxisType.Y_AXIS);
+		writeRequests.add(wrb.explicit()
+				.booleanValues(new boolean[] { true, true, false, true, true, false, true, false, false, false })
+				.build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(2), AxisType.Y_AXIS);
+		writeRequests.add(wrb.explicit().byteValues(new byte[] { 5, 32, 42, 9, 17, 65, 13, 8, 15, 21 }).build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(3), AxisType.Y_AXIS);
+		writeRequests.add(
+				wrb.explicit().integerValues(new int[] { 423, 645, 221, 111, 675, 353, 781, 582, 755, 231 }).build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(4), AxisType.Y_AXIS);
+		writeRequests.add(wrb.explicit()
+				.stringValues(new String[] { "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10" }).build());
+
+		LocalDateTime now = LocalDateTime.now();
+		wrb = WriteRequest.create(channelGroup, channels.get(5), AxisType.Y_AXIS);
+		writeRequests
+				.add(wrb.explicit()
+						.dateValues(new LocalDateTime[] { now, now.plusDays(1), now.plusDays(2), now.plusDays(3),
+								now.plusDays(4), now.plusDays(5), now.plusDays(6), now.plusDays(7), now.plusDays(8),
+								now.plusDays(9) })
+						.build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(6), AxisType.Y_AXIS);
+		writeRequests.add(wrb.explicit().byteStreamValues(new byte[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 9, 10 },
+				{ 11 }, { 12, 13, 14 }, { 15, 16 }, { 17, 18, 19, 20 }, { 21, 22 }, { 23 } }).build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(7), AxisType.Y_AXIS);
+		writeRequests.add(wrb.implicitConstant(ScalarType.SHORT, Short.MAX_VALUE).build());
+
+		wrb = WriteRequest.create(channelGroup, channels.get(8), AxisType.Y_AXIS);
+		writeRequests.add(wrb.implicitSaw(ScalarType.FLOAT, 0, 1, 4).build());
+
+		return writeRequests;
+	}
+
+	private static void delete(Transaction transaction, String key, Collection<? extends Deletable> entities)
+			throws DataAccessException {
+		LOGGER.info(">>>>>>>>>>>>>>>>> deleting " + key + "...");
+		long start = System.currentTimeMillis();
+		transaction.delete(entities);
+		LOGGER.info(">>>>>>>>>>>>>>>>> " + key + " deleted in " + (System.currentTimeMillis() - start) + " ms");
+	}
+
+	private static void create(Transaction transaction, String key, Collection<? extends Entity> entities)
+			throws DataAccessException {
+		LOGGER.info(">>>>>>>>>>>>>>>>> creating " + key + "...");
+		long start = System.currentTimeMillis();
+		transaction.create(entities);
+		LOGGER.info(">>>>>>>>>>>>>>>>> " + key + " written in " + (System.currentTimeMillis() - start) + " ms");
+	}
+
+	private List<Test> createTests(int count, Pool pool, TemplateTest templateTest) {
+		return IntStream.range(1, ++count)
+				.mapToObj(i -> entityFactory.createTest("simple_test_" + i, pool, templateTest))
+				.collect(Collectors.toList());
+	}
+
+	private TemplateTest createTemplateTest(List<TemplateTestStep> templateTestSteps) {
+		TemplateTest templateTest = entityFactory.createTemplateTest("tpl_test");
+		templateTestSteps.forEach(tts -> {
+			entityFactory.createTemplateTestStepUsage(UUID.randomUUID().toString(), templateTest, tts);
+		});
+		return templateTest;
+	}
+
+	private List<TemplateTestStep> createTemplateTestSteps(List<TemplateRoot> templateRoots) {
+		// make sure each context type is given only once
+		templateRoots.stream().collect(Collectors.toMap(TemplateRoot::getContextType, Function.identity()));
+
+		List<TemplateTestStep> templateTestSteps = new ArrayList<>();
+		TemplateTestStep templateTestStep1 = entityFactory.createTemplateTestStep("tpl_test_step_1");
+		templateRoots.forEach(tr -> templateTestStep1.setTemplateRoot(tr));
+		templateTestSteps.add(templateTestStep1);
+		TemplateTestStep templateTestStep2 = entityFactory.createTemplateTestStep("tpl_test_step_2");
+		templateRoots.forEach(tr -> templateTestStep2.setTemplateRoot(tr));
+		templateTestSteps.add(templateTestStep2);
+
+		return templateTestSteps;
+	}
+
+	private List<TemplateRoot> createTemplateRoots(List<CatalogComponent> catalogComponents) {
+		Map<ContextType, List<CatalogComponent>> groups = catalogComponents.stream()
+				.collect(Collectors.groupingBy(CatalogComponent::getContextType));
+
+		List<TemplateRoot> templateRoots = new ArrayList<>();
+		groups.forEach((contextType, catalogComps) -> {
+			TemplateRoot templateRoot = entityFactory.createTemplateRoot(contextType,
+					"tpl_" + toLower(contextType.name()) + "_root");
+			// create child template components for template root
+			catalogComps.forEach(catalogComp -> {
+				TemplateComponent templateComponent = entityFactory
+						.createTemplateComponent("tpl_" + catalogComp.getName() + "_parent", templateRoot, catalogComp);
+				entityFactory.createTemplateComponent("tpl_" + catalogComp.getName() + "_child", templateComponent,
+						catalogComp);
+			});
+
+			templateRoots.add(templateRoot);
+		});
+
+		return templateRoots;
+	}
+
+	private List<CatalogComponent> createCatalogComponents() {
+		List<CatalogComponent> catalogComponents = new ArrayList<>();
+		catalogComponents.add(createCatalogComponent(ContextType.UNITUNDERTEST));
+		catalogComponents.add(createCatalogComponent(ContextType.TESTSEQUENCE));
+		catalogComponents.add(createCatalogComponent(ContextType.TESTEQUIPMENT));
+		return catalogComponents;
+	}
+
+	private CatalogComponent createCatalogComponent(ContextType contextType) {
+		CatalogComponent catalogComponent = entityFactory.createCatalogComponent(contextType,
+				toLower(contextType.name()));
+
+		entityFactory.createCatalogAttribute("string", ValueType.STRING, catalogComponent);
+		entityFactory.createCatalogAttribute("date", ValueType.DATE, catalogComponent);
+		entityFactory.createCatalogAttribute("long", ValueType.LONG, catalogComponent);
+		entityFactory.createCatalogAttribute("file_link", ValueType.FILE_LINK, catalogComponent);
+		entityFactory.createCatalogAttribute("file_link_array", ValueType.FILE_LINK_SEQUENCE, catalogComponent);
+		EnumRegistry er = EnumRegistry.getInstance();
+		entityFactory.createCatalogAttribute("scalar_type", er.get(EnumRegistry.SCALAR_TYPE), catalogComponent);
+
+		return catalogComponent;
+	}
+
+	private static String toLower(String name) {
+		return name.toLowerCase(Locale.ROOT);
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java
new file mode 100644
index 0000000..d0f93e5
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java
@@ -0,0 +1,175 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.asam.ods.AoException;
+import org.asam.ods.InstanceElement;
+import org.assertj.core.api.Condition;
+import org.assertj.core.api.Fail;
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.model.BaseEntity;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.mockito.Mockito;
+
+@Ignore
+//FIXME 26.01.2018: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+//Comment this in for local tests only.
+public class ODSContextTest {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static EntityManager entityManager;
+
+	private static String nameServiceHost = System.getProperty("host");
+	private static String nameServicePort = System.getProperty("port");
+	private static String serviceName = System.getProperty("service");
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+		entityManager = context.getEntityManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	@org.junit.Test
+	public void testGetAdapterType() {
+		assertThat(context.getAdapterType()).isEqualTo("ods");
+	}
+
+	@org.junit.Test
+	public void testGetLink() {
+		// we assume a test with ID 4 exists.
+		Test test = entityManager.load(Test.class, "4");
+
+		Map<Entity, String> asamPaths = entityManager.getLinks(Arrays.asList(test));
+
+		assertThat(asamPaths).hasSize(1).containsOnlyKeys(test).hasEntrySatisfying(test,
+				new Condition<String>(s -> s.startsWith(getLinkPrefix()), ""));
+	}
+
+	@org.junit.Test
+	public void testGetLinkAndLoadOdsInstance() {
+		// we assume a test with ID 4 exists.
+		long testId = 4L;
+		Test test = entityManager.load(Test.class, Long.toString(testId));
+
+		Map<Entity, String> asamPaths = entityManager.getLinks(Arrays.asList(test));
+
+		assertThat(asamPaths).hasSize(1).containsOnlyKeys(test).hasEntrySatisfying(test,
+				new Condition<String>(s -> s.startsWith(getLinkPrefix()), ""));
+		// We try to load the instance from the ODS Server with the AsamPath, but
+		// without the service prefix
+		String asamPathWithoutService = asamPaths.get(test).replace(getLinkPrefix(), "");
+
+		try {
+			InstanceElement ie = ((ODSContext) context).getAoSession().getApplicationStructure()
+					.getInstanceByAsamPath(asamPathWithoutService);
+			assertThat(ODSConverter.fromODSLong(ie.getId())).isEqualTo(testId);
+		} catch (AoException e) {
+			Fail.fail(
+					"Instance with AsamPath '" + asamPathWithoutService + "' could not be loaded. Reason: " + e.reason,
+					e);
+		}
+	}
+
+	@org.junit.Test(expected = IllegalArgumentException.class)
+	public void testGetLinksWithInvalidType() {
+		// we assume a test with ID 4 exists.
+		Test test = entityManager.load(Test.class, "4");
+		BaseEntity entity = Mockito.mock(BaseEntity.class);
+		// Mock an entity with a non existing TypeName
+		when(entity.getTypeName()).thenReturn("invalidType");
+
+		entityManager.getLinks(Arrays.asList(test, entity));
+	}
+
+	@org.junit.Test
+	public void testGetLinksWithEnitityWithMissingId() {
+		// we assume a test with ID 4 exists.
+		Test test = entityManager.load(Test.class, "4");
+
+		// Mock an entity with a non existing ID
+		TestStep testStep = Mockito.mock(TestStep.class);
+		when(testStep.getID()).thenReturn("-1");
+
+		Map<Entity, String> asamPaths = entityManager.getLinks(Arrays.asList(test, testStep));
+
+		assertThat(asamPaths).hasSize(1).containsOnlyKeys(test).hasEntrySatisfying(test,
+				new Condition<String>(s -> s.startsWith(getLinkPrefix()), ""));
+	}
+
+	private String getLinkPrefix() {
+		return String.format("corbaloc::1.2@%s:%s/NameService/%s.ASAM-ODS", nameServiceHost, nameServicePort,
+				serviceName);
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
new file mode 100644
index 0000000..4620a5d
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
@@ -0,0 +1,206 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.dflt.model.EntityFactory;
+import org.eclipse.mdm.api.dflt.model.Role;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class ODSRoleTest {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(ODSRoleTest.class);
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static EntityManager em;
+	private static EntityFactory entityFactory;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+		em = context.getEntityManager().orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
+		entityFactory = context.getEntityFactory()
+				.orElseThrow(() -> new IllegalStateException("Entity manager factory not available."));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	@org.junit.Test
+	public void testLoadRelatedUsers()
+			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		User user = em.loadAll(User.class, "sa").get(0);
+		List<Role> role = em.loadRelatedEntities(user, "users2groups", Role.class);
+
+		assertThat(role).hasSize(1).extracting(Role::getName).containsExactly("MDMSystemAdministrator");
+	}
+
+	@org.junit.Test
+	public void testLoadRelatedRoles()
+			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		Role role = em.loadAll(Role.class, "MDMSystemAdministrator").get(0);
+		List<User> user = em.loadRelatedEntities(role, "groups2users", User.class);
+
+		assertThat(user).hasSize(1).extracting(User::getName).containsExactly("sa");
+	}
+
+	@org.junit.Test
+	public void testCreateUserAndRole()
+			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		String userName = "CreateUserAndRole";
+		String roleName = "CreateUserAndRole";
+
+		try {
+			Transaction transaction = em.startTransaction();
+			User user = entityFactory.createUser(userName, "Test", "User");
+			Role role = entityFactory.createRole(roleName);
+			role.addUser(user);
+
+			transaction.create(Arrays.asList(user, role));
+			transaction.commit();
+
+			assertThat(em.loadRelatedEntities(role, "users2groups", User.class)).hasSize(1).extracting(User::getName)
+					.contains(userName);
+
+			assertThat(em.loadRelatedEntities(user, "groups2users", Role.class)).hasSize(1).extracting(Role::getName)
+					.contains(roleName);
+		} finally {
+			Transaction transaction = em.startTransaction();
+			List<User> users = em.loadAll(User.class, userName);
+			transaction.delete(users);
+			List<Role> roles = em.loadAll(Role.class, roleName);
+			transaction.delete(roles);
+			transaction.commit();
+		}
+	}
+
+	@org.junit.Test
+	public void testAddMultipleUsersToNewRole()
+			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		String roleName = "AddMultipleUsersToNewRole";
+		try {
+			Transaction transaction = em.startTransaction();
+			List<User> users = em.loadAll(User.class);
+			Role role = entityFactory.createRole(roleName);
+
+			users.forEach(u -> role.addUser(u));
+			transaction.create(Arrays.asList(role));
+			transaction.commit();
+
+			assertThat(em.loadRelatedEntities(role, "users2groups", User.class)).hasSize(users.size());
+		} finally {
+			Transaction transaction = em.startTransaction();
+			List<Role> roles = em.loadAll(Role.class, roleName);
+			transaction.delete(roles);
+			transaction.commit();
+		}
+	}
+
+	@org.junit.Test
+	public void testRemoveUserFromRole()
+			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		String userName = "RemoveUserFromRole";
+		try {
+			Transaction transaction = em.startTransaction();
+			Role role = em.load(Role.class, "1");
+			User user = entityFactory.createUser(userName, "User", "User");
+
+			role.addUser(user);
+
+			transaction.create(Arrays.asList(user));
+			transaction.update(Arrays.asList(role));
+			transaction.commit();
+
+			assertThat(em.loadRelatedEntities(role, "groups2users", User.class)).hasSize(2);
+
+			Role role2 = em.load(Role.class, "1");
+			transaction = em.startTransaction();
+			role2.removeUser(user);
+			transaction.update(Arrays.asList(role2));
+			transaction.commit();
+
+			assertThat(em.loadRelatedEntities(role2, "groups2users", User.class)).hasSize(1);
+		} finally {
+			Transaction transaction = em.startTransaction();
+			List<User> users = em.loadAll(User.class, userName);
+			transaction.delete(users);
+			transaction.commit();
+		}
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java
new file mode 100755
index 0000000..a07b428
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java
@@ -0,0 +1,185 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter;
+
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.adapter.EntityStore;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.ParameterSet;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Record;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.RelationSearchQuery;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class RelationTest {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static EntityManager entityManager;
+	private static ModelManager modelManager;
+	private static QueryService queryService;
+	private static SearchService searchService;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+		entityManager = context.getEntityManager()
+				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
+		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+		queryService = context.getQueryService().orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
+		searchService = context.getSearchService()
+				.orElseThrow(() -> new IllegalStateException("Search service not available."));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	/**
+	 * changes a relation between instances. There needs to exist a MeaResult of id
+	 * 1101 and a ParameterSet of id 1102 which will be related after running this
+	 * test. If these don't exist, please leave the following line commented, or the
+	 * test will fail.
+	 * 
+	 * @throws Exception
+	 */
+	@org.junit.Test
+	public void changeRelation() throws Exception {
+		String idmea = "1101";
+		String idparamset = "1002";
+
+		EntityType etmeasurement = modelManager.getEntityType(Measurement.class);
+		EntityType etparamset = modelManager.getEntityType(ParameterSet.class);
+		Transaction transaction;
+
+		transaction = entityManager.startTransaction();
+
+		try {
+			List<Measurement> mealist;
+			// we use the searchService to fetch a measurement. Please note, that we
+			// use the per default defined method to fetch the measurement.
+			// This does not load any related ParameterSets! But
+			// we don't care at this point, because we just want to change
+			// the related ParameterSet to a new one, not look at
+			// the existing relations.
+			mealist = searchService.fetch(Measurement.class, Filter.idOnly(etmeasurement, idmea));
+			assertEquals(1, mealist.size());
+			Measurement mea = mealist.get(0);
+
+			// load the parameter set which we want to relate to our measurment.
+			// again we don't care for any preexisting relations.
+			List<ParameterSet> paramsetlist = new ArrayList<>();
+			ParameterSet paramset = entityManager.load(ParameterSet.class, idparamset);
+			paramsetlist.add(paramset);
+			// Note: we can only set relations in the mutable store (which
+			// doesn't include parent-child-relations)
+			EntityStore store = ODSEntityFactory.getMutableStore(paramset);
+			store.set(mea);
+			assertEquals(store.get(Measurement.class), mea);
+
+			transaction.update(paramsetlist);
+			transaction.commit();
+
+			// reload from database and check if relation is consistent with
+			// expectations
+			// first we need to build our own SearchQuery, because the
+			// predefined ones don't include ParameterSet as stated above.
+			RelationSearchQuery mq = new RelationSearchQuery((ODSModelManager) modelManager, queryService);
+			// the SearchQuery defines how to join measurement and parameterset,
+			// but we also have to declare that we want to fetch the related
+			// measurement
+			List<EntityType> fetchList = new ArrayList<>();
+			fetchList.add(etmeasurement);
+			List<Result> fetch = mq.fetchComplete(fetchList, Filter.idOnly(etparamset, idparamset));
+			assertEquals(fetch.size(), 1);
+
+			// now we can check that the new relation is there as expected
+			Record record = fetch.get(0).getRecord(etmeasurement);
+			assertNotNull(record);
+			assertEquals(record.getID(), idmea);
+
+		} catch (RuntimeException e) {
+			transaction.abort();
+			throw e;
+		}
+
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java
new file mode 100644
index 0000000..ca152f7
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java
@@ -0,0 +1,332 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.notification.peak;
+
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.asam.ods.AIDName;
+import org.asam.ods.AIDNameValueSeqUnitId;
+import org.asam.ods.AoException;
+import org.asam.ods.AoSession;
+import org.asam.ods.ApplElemAccess;
+import org.asam.ods.ApplicationElement;
+import org.asam.ods.TS_UnionSeq;
+import org.asam.ods.TS_ValueSeq;
+import org.asam.ods.T_LONGLONG;
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.Transaction;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.model.User;
+import org.eclipse.mdm.api.base.notification.NotificationException;
+import org.eclipse.mdm.api.base.notification.NotificationFilter;
+import org.eclipse.mdm.api.base.notification.NotificationListener;
+import org.eclipse.mdm.api.base.notification.NotificationService;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.EntityManager;
+import org.eclipse.mdm.api.dflt.model.EntityFactory;
+import org.eclipse.mdm.api.odsadapter.ODSContext;
+import org.eclipse.mdm.api.odsadapter.ODSContextFactory;
+import org.eclipse.mdm.api.odsadapter.notification.ODSNotificationServiceFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test notification service.
+ * 
+ * Needs a running ODS and Notification Server. Assumes an existing Test with
+ * name defined in {@link PeakNotificationTest#PARENT_TEST}, an UnitUnderTest
+ * with ID 11 and an UnitUnderTestPart with ID 34.
+ * 
+ * @author Matthias Koller, Peak Solution GmbH
+ *
+ */
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class PeakNotificationTest {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+
+	private static final Logger LOGGER = LoggerFactory.getLogger(EventProcessor.class);
+
+	// TODO name service: corbaloc::1.2@<SERVER_IP>:<SERVER_PORT>/NameService
+	private static final String NAME_SERVICE = "corbaloc::1.2@127.0.0.1:2809/NameService";
+
+	// TODO service name: <SERVICE_NAME>.ASAM-ODS
+	private static final String SERVICE_NAME = "MDMNVH.ASAM-ODS";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static final String PARENT_TEST = "PBN_UNECE_R51_13022014_1349";
+
+	private static final String NOTIFICATION_URL = "http://localhost:8080/api";
+	private static final String NOTIFICATION_REGISTRATION_NAME = "mdm";
+	private static final String NOTIFICATION_USER = "sa";
+	private static final String NOTIFICATION_PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static EntityManager entityManager;
+	private static NotificationService notificationManager;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, NAME_SERVICE);
+		connectionParameters.put(PARAM_SERVICENAME, SERVICE_NAME);
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+
+		Map<String, String> notificationParameters = new HashMap<>();
+		notificationParameters.put(ODSNotificationServiceFactory.PARAM_SERVER_TYPE,
+				ODSNotificationServiceFactory.SERVER_TYPE_PEAK);
+		notificationParameters.put(ODSNotificationServiceFactory.PARAM_URL, NOTIFICATION_URL);
+		notificationParameters.put(ODSContextFactory.PARAM_USER, NOTIFICATION_USER);
+		notificationParameters.put(ODSContextFactory.PARAM_PASSWORD, NOTIFICATION_PASSWORD);
+
+		notificationManager = new ODSNotificationServiceFactory().create(context, notificationParameters);
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException, NotificationException {
+		if (context != null) {
+			context.close();
+		}
+
+		if (notificationManager != null) {
+			notificationManager.deregister(NOTIFICATION_REGISTRATION_NAME);
+			notificationManager.close(true);
+		}
+	}
+
+	@org.junit.Test
+	public void testCreateTestStep() throws NotificationException, DataAccessException, InterruptedException {
+		String testStepName = USER + "_TestStep";
+
+		NotificationListener l = Mockito.mock(NotificationListener.class);
+
+		notificationManager.register(NOTIFICATION_REGISTRATION_NAME, new NotificationFilter(), l);
+
+		try {
+			createTestStep(PARENT_TEST, testStepName);
+
+			// make sure notification has some time to be pushed
+			Thread.sleep(1000L);
+
+			@SuppressWarnings({ "unchecked", "rawtypes" })
+			ArgumentCaptor<List<TestStep>> testStepCaptor = ArgumentCaptor.forClass((Class) List.class);
+			ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
+
+			verify(l, times(1)).instanceCreated(testStepCaptor.capture(), userCaptor.capture());
+
+			assertThat(testStepCaptor.getValue().size(), is(1));
+			assertThat(testStepCaptor.getValue().get(0).getName(), is(testStepName));
+			assertThat(userCaptor.getValue().getName(), is(USER));
+		} finally {
+			notificationManager.deregister(NOTIFICATION_REGISTRATION_NAME);
+			deleteTestStep(testStepName);
+		}
+	}
+
+	@org.junit.Test
+	public void testModifyContextRoot()
+			throws NotificationException, DataAccessException, InterruptedException, IOException {
+		NotificationListener l = Mockito.mock(NotificationListener.class);
+
+		notificationManager.register(NOTIFICATION_REGISTRATION_NAME, new NotificationFilter(), l);
+
+		try {
+			updateUUT(11, "application/x-asam.aounitundertest.unitundertest");
+
+			// make sure notification has some time to be pushed
+			Thread.sleep(1000L);
+
+			@SuppressWarnings({ "unchecked", "rawtypes" })
+			ArgumentCaptor<List<Entity>> entityCaptor = ArgumentCaptor.forClass((Class) List.class);
+			ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
+
+			verify(l, times(1)).instanceModified(entityCaptor.capture(), userCaptor.capture());
+
+			assertThat(entityCaptor.getValue().size(), is(1));
+			assertThat(entityCaptor.getValue().get(0).getName(), is("PBN_UNECE_R51_Left_AccV"));
+			assertThat(userCaptor.getValue().getName(), is(USER));
+		} finally {
+			notificationManager.deregister(NOTIFICATION_REGISTRATION_NAME);
+		}
+	}
+
+	@org.junit.Test
+	public void testModifyContextComponent()
+			throws NotificationException, DataAccessException, InterruptedException, IOException {
+		NotificationListener l = Mockito.mock(NotificationListener.class);
+
+		notificationManager.register(NOTIFICATION_REGISTRATION_NAME, new NotificationFilter(), l);
+
+		try {
+			updateUUTP(34, "test");
+
+			// make sure notification has some time to be pushed
+			Thread.sleep(1000L);
+
+			@SuppressWarnings({ "unchecked", "rawtypes" })
+			ArgumentCaptor<List<Entity>> entityCaptor = ArgumentCaptor.forClass((Class) List.class);
+			ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
+
+			verify(l, times(1)).instanceModified(entityCaptor.capture(), userCaptor.capture());
+
+			assertThat(entityCaptor.getValue().size(), is(1));
+			assertThat(entityCaptor.getValue().get(0).getName(), is("PBN_UNECE_R51_Left_SteadyV"));
+			assertThat(userCaptor.getValue().getName(), is(USER));
+		} finally {
+			notificationManager.deregister(NOTIFICATION_REGISTRATION_NAME);
+		}
+	}
+
+	private void createTestStep(String parentName, String name) throws DataAccessException {
+		Transaction transaction = entityManager.startTransaction();
+
+		List<Test> tests = entityManager.loadAll(Test.class, parentName);
+
+		assertThat("Parent test not found!", !tests.isEmpty());
+
+		Optional<? extends EntityFactory> entityFactory = context.getEntityFactory();
+		if (!entityFactory.isPresent()) {
+			throw new IllegalStateException("Entity factory not present!");
+		}
+
+		TestStep testStep = entityFactory.get().createTestStep(name, tests.get(0));
+		testStep.setSortIndex(0);
+
+		transaction.create(Arrays.asList(testStep));
+
+		transaction.commit();
+	}
+
+	private void deleteTestStep(String name) throws DataAccessException {
+		Transaction transaction = entityManager.startTransaction();
+
+		List<TestStep> testSteps = entityManager.loadAll(TestStep.class, name);
+
+		transaction.delete(testSteps);
+
+		transaction.commit();
+	}
+
+	private void updateUUT(int uutId, String newValue) throws DataAccessException {
+
+		AoSession session = null;
+		try {
+			session = ((ODSContext) context).getAoSession().createCoSession();
+
+			ApplicationElement aeUUT = session.getApplicationStructure().getElementsByBaseType("AoUnitUnderTest")[0];
+
+			final ApplElemAccess aea = session.getApplElemAccess();
+
+			TS_UnionSeq uId = new TS_UnionSeq();
+			uId.longlongVal(new T_LONGLONG[] { new T_LONGLONG(0, uutId) });
+
+			TS_UnionSeq uManufacturer = new TS_UnionSeq();
+			uManufacturer.stringVal(new String[] { newValue });
+
+			AIDNameValueSeqUnitId[] val = new AIDNameValueSeqUnitId[] {
+					new AIDNameValueSeqUnitId(new AIDName(aeUUT.getId(), "Id"), new T_LONGLONG(),
+							new TS_ValueSeq(uId, new short[] { (short) 15 })),
+					new AIDNameValueSeqUnitId(new AIDName(aeUUT.getId(), "Mimetype"), new T_LONGLONG(),
+							new TS_ValueSeq(uManufacturer, new short[] { (short) 15 })) };
+			session.startTransaction();
+			aea.updateInstances(val);
+			session.commitTransaction();
+
+		} catch (AoException e) {
+			throw new DataAccessException(e.reason, e);
+		} finally {
+			if (session != null) {
+				try {
+					session.close();
+				} catch (AoException e) {
+					LOGGER.warn("Exception when closing the ods session: " + e.reason, e);
+				}
+			}
+		}
+	}
+
+	private void updateUUTP(int tyreId, String newValue) throws DataAccessException {
+
+		AoSession session = null;
+		try {
+			session = ((ODSContext) context).getAoSession().createCoSession();
+
+			ApplicationElement aeTyre = session.getApplicationStructure().getElementByName("tyre");
+
+			final ApplElemAccess aea = session.getApplElemAccess();
+
+			TS_UnionSeq uId = new TS_UnionSeq();
+			uId.longlongVal(new T_LONGLONG[] { new T_LONGLONG(0, tyreId) });
+
+			TS_UnionSeq uManufacturer = new TS_UnionSeq();
+			uManufacturer.stringVal(new String[] { newValue });
+
+			AIDNameValueSeqUnitId[] val = new AIDNameValueSeqUnitId[] {
+					new AIDNameValueSeqUnitId(new AIDName(aeTyre.getId(), "Id"), new T_LONGLONG(),
+							new TS_ValueSeq(uId, new short[] { (short) 15 })),
+					new AIDNameValueSeqUnitId(new AIDName(aeTyre.getId(), "manufacturer"), new T_LONGLONG(),
+							new TS_ValueSeq(uManufacturer, new short[] { (short) 15 })) };
+			session.startTransaction();
+			aea.updateInstances(val);
+			session.commitTransaction();
+
+		} catch (AoException e) {
+			throw new DataAccessException(e.reason, e);
+		} finally {
+			if (session != null) {
+				try {
+					session.close();
+				} catch (AoException e) {
+					LOGGER.warn("Exception when closing the ods session: " + e.reason, e);
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearchTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearchTest.java
new file mode 100644
index 0000000..279ba65
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSFreeTextSearchTest.java
@@ -0,0 +1,192 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyCollection;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.text.StringEscapeUtils;
+import org.apache.http.HttpHost;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
+import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RestClient;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testcontainers.elasticsearch.ElasticsearchContainer;
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
+
+@Ignore
+//FIXME 05.02.2020: this test needs a docker to run elasticsearch and is not suitable for continous build in Jenkins.
+//Comment this in for local tests only, if docker is available
+public class ODSFreeTextSearchTest {
+
+	private EntityLoader loader;
+	private ODSFreeTextSearch fts;
+	private TestStep ts;
+
+	private RestClient client;
+
+	@ClassRule
+	public static ElasticsearchContainer elasticSearch = new ElasticsearchContainer(
+			"docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.0");
+
+	@SuppressWarnings("unchecked")
+	@Before
+	public void init() throws DataAccessException {
+		ts = mock(TestStep.class);
+		loader = mock(EntityLoader.class);
+
+		when(loader.loadAll(any(Key.class), anyCollection())).thenAnswer(new Answer<List<Entity>>() {
+
+			@Override
+			public List<Entity> answer(InvocationOnMock invocation) throws Throwable {
+				Collection<Long> object = (Collection<Long>) invocation.getArguments()[1];
+
+				List<Entity> res = new ArrayList<>();
+				for (int i = 0; i < object.size(); i++) {
+					res.add(ts);
+				}
+
+				return res;
+			}
+		});
+
+		client = RestClient.builder(HttpHost.create(elasticSearch.getHttpHostAddress())).build();
+		fts = new ODSFreeTextSearch(loader, "mdm", "http://" + elasticSearch.getHttpHostAddress());
+	}
+
+	@Test
+	public void noIndex_emptyResult() throws DataAccessException {
+		ODSFreeTextSearch ftsOtherIndex = new ODSFreeTextSearch(loader, "UNKNOWN_INDEX",
+				"http://" + elasticSearch.getHttpHostAddress());
+
+		Map<Class<? extends Entity>, List<Entity>> map = ftsOtherIndex.search("VAG_002");
+		assertThat(map).isEmpty();
+	}
+
+	@Test
+	public void exampleIndex_querySuccessfull() throws Exception {
+		try {
+			createExampleIndex("mdm", "TestStep", "asdf");
+
+			assertThat(fts.search("asdf").get(TestStep.class).get(0)).isEqualTo(ts);
+		} finally {
+			deleteIndex("mdm");
+		}
+	}
+
+	@Test
+	public void specialCharacters_correctlyEscaped() throws InterruptedException {
+		try {
+			createExampleIndex("mdm", "Measurement", "hallo\"!§");
+
+			Map<Class<? extends Entity>, List<Entity>> search = fts.search("hallo\"!§");
+			assertThat(search.get(Measurement.class).get(0)).isEqualTo(ts);
+		} finally {
+			deleteIndex("mdm");
+		}
+	}
+
+	@Test
+	public void nonMdmResults_ignored() throws InterruptedException {
+		try {
+			createExampleIndex("mdm", "NONMDMStuff", "test");
+
+			Map<Class<? extends Entity>, List<Entity>> search = fts.search("test");
+			assertThat(search).isEmpty();
+		} finally {
+			deleteIndex("mdm");
+		}
+	}
+
+	@Test
+	public void twoResults_twoResultsRetuned() throws InterruptedException {
+		try {
+			createExampleIndex("mdm", "Test", "0", "unicorn ASDF");
+			createExampleIndex("mdm", "Test", "1", "unicorn XYZ");
+
+			Map<Class<? extends Entity>, List<Entity>> search = fts.search("unicorn");
+			assertThat(search.get(org.eclipse.mdm.api.base.model.Test.class)).hasSize(2);
+		} finally {
+			deleteIndex("mdm");
+		}
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void illegalLoadRequest_niceExceptionIsThrown() throws DataAccessException, InterruptedException {
+		try {
+			loader = mock(EntityLoader.class);
+			when(loader.loadAll(any(), anyCollection())).thenThrow(new DataAccessException(""));
+			createExampleIndex("mdm2", "TestStep", "asdf");
+			ODSFreeTextSearch fts2 = new ODSFreeTextSearch(loader, "mdm2",
+					"http://" + elasticSearch.getHttpHostAddress());
+
+			fts2.search("asdf");
+		} finally {
+			deleteIndex("mdm2");
+		}
+	}
+
+	private void createExampleIndex(String indexName, String type, String value) throws InterruptedException {
+		createExampleIndex(indexName, type, "0", value);
+	}
+
+	private void createExampleIndex(String indexName, String type, String id, String value)
+			throws InterruptedException {
+		ObjectMapper mapper = new ObjectMapper();
+		Map<String, String> json = new HashMap<>();
+		json.put("id", StringEscapeUtils.escapeJson(id));
+		json.put("type", StringEscapeUtils.escapeJson(type));
+		json.put("attr", StringEscapeUtils.escapeJson(value));
+
+		try {
+			Request a = new Request("PUT", indexName + "/_doc/" + type + "-" + id);
+			a.setJsonEntity(mapper.writeValueAsString(json));
+			client.performRequest(a);
+		} catch (IOException e) {
+			throw new RuntimeException("Could not index!");
+		}
+
+		Thread.sleep(1000); // let the index some time to populate
+	}
+
+	private void deleteIndex(String indexName) {
+		try {
+			client.performRequest(new Request("DELETE", indexName));
+		} catch (IOException e) {
+			throw new RuntimeException("Could not delete index!");
+		}
+	}
+
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java
new file mode 100644
index 0000000..2e11dd3
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java
@@ -0,0 +1,212 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_PASSWORD;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_SERVICENAME;
+import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_USER;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.assertj.core.api.iterable.Extractor;
+import org.assertj.core.groups.Tuple;
+import org.eclipse.mdm.api.base.ConnectionException;
+import org.eclipse.mdm.api.base.ServiceNotProvidedException;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.ParameterSet;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.BooleanOperator;
+import org.eclipse.mdm.api.base.query.BracketOperator;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.FilterItem;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.SearchService;
+import org.eclipse.mdm.api.dflt.ApplicationContext;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.ODSContextFactory;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.mockito.Mockito;
+
+import com.google.common.collect.ImmutableMap;
+
+@Ignore
+// FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
+// Comment this in for local tests only.
+public class ODSSearchServiceIT {
+
+	/*
+	 * ATTENTION: ==========
+	 *
+	 * To run this test make sure the target service is running a MDM default model
+	 * and any database constraint which enforces a relation of Test to a parent
+	 * entity is deactivated!
+	 */
+
+	private static final String NAME_SERVICE = "corbaloc::1.2@%s:%s/NameService";
+
+	private static final String USER = "sa";
+	private static final String PASSWORD = "sa";
+
+	private static ApplicationContext context;
+	private static ModelManager modelManager;
+	private static SearchService searchService;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws ConnectionException {
+		String nameServiceHost = System.getProperty("host");
+		String nameServicePort = System.getProperty("port");
+		String serviceName = System.getProperty("service");
+
+		if (nameServiceHost == null || nameServiceHost.isEmpty()) {
+			throw new IllegalArgumentException("name service host is unknown: define system property 'host'");
+		}
+
+		nameServicePort = nameServicePort == null || nameServicePort.isEmpty() ? String.valueOf(2809) : nameServicePort;
+		if (nameServicePort == null || nameServicePort.isEmpty()) {
+			throw new IllegalArgumentException("name service port is unknown: define system property 'port'");
+		}
+
+		if (serviceName == null || serviceName.isEmpty()) {
+			throw new IllegalArgumentException("service name is unknown: define system property 'service'");
+		}
+
+		Map<String, String> connectionParameters = new HashMap<>();
+		connectionParameters.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, nameServicePort));
+		connectionParameters.put(PARAM_SERVICENAME, serviceName + ".ASAM-ODS");
+		connectionParameters.put(PARAM_USER, USER);
+		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
+
+		context = new ODSContextFactory().connect(connectionParameters);
+		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+		searchService = context.getSearchService()
+				.orElseThrow(() -> new IllegalStateException("Search service not available."));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() throws ConnectionException {
+		if (context != null) {
+			context.close();
+		}
+	}
+
+	final class MeasurementSearchQuery extends BaseEntitySearchQuery {
+
+		/**
+		 * Constructor.
+		 *
+		 * @param modelManager Used to load {@link EntityType}s.
+		 * @param contextState The {@link ContextState}.
+		 */
+		MeasurementSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+			super(modelManager, queryService, ParameterSet.class, Project.class);
+
+			// layers
+			addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+			addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+			addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+			addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+			addJoinConfig(JoinConfig.up(ParameterSet.class, Measurement.class));
+			addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+			addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+
+			// context
+			addJoinConfig(contextState);
+		}
+
+	}
+
+	private Extractor<FilterItem, Tuple> filterExtractors = new Extractor<FilterItem, Tuple>() {
+
+		@Override
+		public Tuple extract(FilterItem f) {
+			return tuple(f.isBooleanOperator() ? f.getBooleanOperator() : null,
+					f.isCondition() ? f.getCondition().getAttribute().getName() : null,
+					f.isCondition() ? f.getCondition().getComparisonOperator() : null,
+					f.isCondition() ? f.getCondition().getValue().extract() : null,
+					f.isBracketOperator() ? f.getBracketOperator() : null);
+		}
+	};
+
+	@org.junit.Test
+	public void testGetMergedFilter() throws Exception {
+
+		ODSSearchService service = Mockito.spy((ODSSearchService) searchService);
+
+		Mockito.doReturn(ImmutableMap.of(TestStep.class, Arrays.asList("10"))).when(service)
+				.fetchIds(Mockito.anyString());
+
+		EntityType testStep = modelManager.getEntityType(TestStep.class);
+
+		assertThat(service.getMergedFilter(Filter.idOnly(testStep, "11"), "query")).hasSize(7)
+				.extracting(filterExtractors).containsExactly(tuple(null, null, null, null, BracketOperator.OPEN),
+						tuple(null, "Id", ComparisonOperator.EQUAL, "10"),
+						tuple(null, null, null, null, BracketOperator.CLOSE),
+						tuple(BooleanOperator.AND, null, null, null, null),
+						tuple(null, null, null, null, BracketOperator.OPEN),
+						tuple(null, "Id", ComparisonOperator.IN_SET, new String[] { "10" }, null),
+						tuple(null, null, null, null, BracketOperator.CLOSE));
+	}
+
+	@org.junit.Test
+	public void testGetMergedFilterNoAttributeFilter() throws Exception {
+		ODSSearchService service = Mockito.spy((ODSSearchService) searchService);
+
+		Mockito.doReturn(ImmutableMap.of(TestStep.class, Arrays.asList("10"))).when(service)
+				.fetchIds(Mockito.anyString());
+
+		assertThat(service.getMergedFilter(Filter.and(), "query")).extracting(filterExtractors)
+				.containsExactly(tuple(null, "Id", ComparisonOperator.IN_SET, new String[] { "10" }));
+	}
+
+	@org.junit.Test
+	public void testGetMergedFilterNoFreetextResult() throws Exception {
+		ODSSearchService service = Mockito.spy((ODSSearchService) searchService);
+
+		Mockito.doReturn(Collections.emptyMap()).when(service).fetchIds(Mockito.anyString());
+
+		EntityType testStep = modelManager.getEntityType(TestStep.class);
+
+		assertThat(service.getMergedFilter(Filter.idOnly(testStep, "11"), "")).extracting(filterExtractors)
+				.containsExactly(tuple(null, "Id", ComparisonOperator.EQUAL, "11"));
+	}
+
+	@org.junit.Test
+	public void testGetMergedFilterNoAttributeFilterAndNoFreetextResult() throws Exception {
+		ODSSearchService service = Mockito.spy((ODSSearchService) searchService);
+
+		Mockito.doReturn(Collections.emptyMap()).when(service).fetchIds(Mockito.anyString());
+
+		assertThat(service.getMergedFilter(Filter.and(), null)).isEmpty();
+
+		assertThat(service.getMergedFilter(Filter.and(), "")).isEmpty();
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceTest.java
new file mode 100644
index 0000000..2e320af
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceTest.java
@@ -0,0 +1,74 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.ValueType;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.junit.Test;
+
+public class ODSSearchServiceTest {
+
+	@Test
+	public void testGetMergedFilter() {
+		EntityType testEntity = mockEntityType();
+		ODSSearchService searchService = mockODSSearchService(testEntity);
+
+		// No freetext query -> original filter is returned
+		assertThat(searchService.getMergedFilter(Filter.idOnly(testEntity, "1"), ""))
+				.isEqualTo(Filter.and().id(testEntity, "1"));
+
+		// Freetext query with result -> conjuction of old filter and filter generated
+		// by freetext result
+		assertThat(searchService.getMergedFilter(Filter.idOnly(testEntity, "1"), "existing"))
+				.isEqualTo(Filter.and().id(testEntity, "1").merge(Filter.or().id(testEntity, "5")));
+
+		// Freetext query with no result -> empty filter is returned
+		assertThat(searchService.getMergedFilter(Filter.idOnly(testEntity, "1"), "not existing"))
+				.isEqualTo(Filter.or());
+
+		// No filter -> filter generated by freetext result is returned
+		assertThat(searchService.getMergedFilter(Filter.or(), "existing")).isEqualTo(Filter.or().id(testEntity, "5"));
+	}
+
+	private ODSSearchService mockODSSearchService(EntityType testEntity) {
+		ODSSearchService searchService = mock(ODSSearchService.class);
+		when(searchService.getMergedFilter(any(), any())).thenCallRealMethod();
+
+		Filter f = Filter.or().id(testEntity, "5");
+		when(searchService.getFilterForFreetextQuery("existing")).thenReturn(f);
+		when(searchService.getFilterForFreetextQuery("not existing")).thenReturn(null);
+		when(searchService.getFilterForFreetextQuery("")).thenReturn(Filter.or());
+		return searchService;
+	}
+
+	private EntityType mockEntityType() {
+		Attribute idAttribute = mock(Attribute.class);
+		when(idAttribute.getName()).thenReturn("Id");
+		when(idAttribute.createValue("", "1")).thenReturn(ValueType.STRING.create("Id", "1"));
+
+		EntityType testEntity = mock(EntityType.class);
+		when(testEntity.getName()).thenReturn("TestEntity");
+		when(testEntity.getIDAttribute()).thenReturn(idAttribute);
+		when(idAttribute.getEntityType()).thenReturn(testEntity);
+		return testEntity;
+	}
+}
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/RelationSearchQuery.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/RelationSearchQuery.java
new file mode 100755
index 0000000..5d050d2
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/RelationSearchQuery.java
@@ -0,0 +1,66 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.ParameterSet;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * This class is used as a helper to the tests in
+ * org.eclipse.mdm.api.odsadapter.RelationTest It needs to be here, because
+ * BaseEntitySearchQuery is declared as protected in the
+ * org.eclipse.mdm.api.odsadapter.search package. It makes some sense to leave
+ * it protected in that way, because implementing a BaseEntitySearchQuery
+ * requires understanding of the underlying data model which The RelationTest
+ * requires that the related parametersets to a measurement are loaded. This
+ * class provides a JoinConfig which allows this to happen by defining the way
+ * the entities in question have to be joined. If we wouldn't join the
+ * ParameterSet in, the related entities would not be loaded, and it would be
+ * impossible to determine whether there are any related ParameterSets or not.
+ *
+ */
+public final class RelationSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	public RelationSearchQuery(ODSModelManager modelManager, QueryService queryService) {
+		super(modelManager, queryService, ParameterSet.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+		addJoinConfig(JoinConfig.up(ParameterSet.class, Measurement.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, ChannelGroup.class));
+
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverterTest.java b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverterTest.java
new file mode 100644
index 0000000..d9bd991
--- /dev/null
+++ b/org.eclipse.mdm.api.odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverterTest.java
@@ -0,0 +1,113 @@
+/********************************************************************************
+ * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.odsadapter.utils;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.time.LocalDateTime;
+
+import org.asam.ods.TS_UnionSeq;
+import org.asam.ods.TS_ValueSeq;
+import org.eclipse.mdm.api.base.query.Aggregation;
+import org.eclipse.mdm.api.odsadapter.query.ODSAttribute;
+import org.junit.Test;
+
+public class ODSConverterTest {
+
+	@Test
+	public void testFromODSValueSeqODSDateYear() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("2017"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 1, 1, 0, 0)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDateMonth() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("201710"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 1, 0, 0)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDate() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("20171004"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 4, 0, 0)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDateHour() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("2017100412"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 4, 12, 0)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDateMinute() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("201710041213"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 4, 12, 13)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDateSecond() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("20171004121314"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 4, 12, 13, 14, 0)));
+	}
+
+	@Test
+	public void testFromODSValueSeqODSDateMillisecond() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("20171004121314123"));
+
+		verify(attr).createValue(eq(""), eq(true), eq(LocalDateTime.of(2017, 10, 4, 12, 13, 14, 123_000_000)));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testFromODSValueSeqInvalidLength() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("201710041"));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testFromODSValueSeqInvalidMonth() throws Exception {
+		ODSAttribute attr = mock(ODSAttribute.class);
+
+		ODSConverter.fromODSValueSeq(attr, Aggregation.NONE, "", getTS_ValueSeqFromDates("20171304"));
+	}
+
+	private TS_ValueSeq getTS_ValueSeqFromDates(String... dates) {
+		TS_UnionSeq u = new TS_UnionSeq();
+		u.dateVal(dates);
+		return new TS_ValueSeq(u, new short[] { 15 });
+	}
+}