From 62c63b71bda489544b794bdb1c6d96c210caeba0 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 9 Sep 2016 00:28:25 +0200 Subject: [PATCH 1/1] Initial import. --- jOCCI-core/.gitignore | 7 + jOCCI-core/.travis.yml | 10 + jOCCI-core/LICENSE | 17 + jOCCI-core/README.md | 31 + jOCCI-core/debian/README.source | 9 + jOCCI-core/debian/changelog | 5 + jOCCI-core/debian/compat | 1 + jOCCI-core/debian/control | 46 + jOCCI-core/debian/copyright | 17 + .../debian/libjocci-core-java-doc.doc-base.api | 10 + jOCCI-core/debian/libjocci-core-java-doc.install | 2 + jOCCI-core/debian/libjocci-core-java.poms | 28 + jOCCI-core/debian/maven.cleanIgnoreRules | 1 + jOCCI-core/debian/maven.ignoreRules | 5 + jOCCI-core/debian/maven.properties | 4 + jOCCI-core/debian/maven.publishedRules | 1 + jOCCI-core/debian/maven.rules | 3 + jOCCI-core/debian/rules | 9 + jOCCI-core/debian/source/format | 1 + jOCCI-core/pom.xml | 186 +++ .../main/java/cz/cesnet/cloud/occi/Collection.java | 320 +++++ .../src/main/java/cz/cesnet/cloud/occi/Model.java | 586 +++++++++ .../cloud/occi/collection/AttributeMapCover.java | 253 ++++ .../cz/cesnet/cloud/occi/collection/SetCover.java | 193 +++ .../java/cz/cesnet/cloud/occi/core/Action.java | 279 ++++ .../cz/cesnet/cloud/occi/core/ActionInstance.java | 303 +++++ .../java/cz/cesnet/cloud/occi/core/Attribute.java | 300 +++++ .../java/cz/cesnet/cloud/occi/core/Category.java | 549 ++++++++ .../java/cz/cesnet/cloud/occi/core/Entity.java | 540 ++++++++ .../main/java/cz/cesnet/cloud/occi/core/Kind.java | 157 +++ .../main/java/cz/cesnet/cloud/occi/core/Link.java | 288 +++++ .../main/java/cz/cesnet/cloud/occi/core/Mixin.java | 106 ++ .../java/cz/cesnet/cloud/occi/core/Resource.java | 448 +++++++ .../exception/AmbiguousIdentifierException.java | 16 + .../occi/exception/InvalidAttributeException.java | 16 + .../exception/InvalidAttributeValueException.java | 16 + .../cloud/occi/exception/ParsingException.java | 16 + .../cloud/occi/exception/RenderingException.java | 16 + .../cesnet/cloud/occi/infrastructure/Compute.java | 272 ++++ .../cloud/occi/infrastructure/IPNetwork.java | 163 +++ .../occi/infrastructure/IPNetworkInterface.java | 165 +++ .../cesnet/cloud/occi/infrastructure/Network.java | 170 +++ .../occi/infrastructure/NetworkInterface.java | 163 +++ .../cesnet/cloud/occi/infrastructure/Storage.java | 168 +++ .../cloud/occi/infrastructure/StorageLink.java | 163 +++ .../infrastructure/enumeration/Allocation.java | 15 + .../infrastructure/enumeration/Architecture.java | 15 + .../infrastructure/enumeration/ComputeState.java | 15 + .../infrastructure/enumeration/NetworkState.java | 15 + .../enumeration/StorageLinkState.java | 15 + .../infrastructure/enumeration/StorageState.java | 15 + .../cesnet/cloud/occi/parser/CollectionType.java | 10 + .../cz/cesnet/cloud/occi/parser/JSONParser.java | 30 + .../cz/cesnet/cloud/occi/parser/MediaType.java | 13 + .../java/cz/cesnet/cloud/occi/parser/Parser.java | 53 + .../cz/cesnet/cloud/occi/parser/TextParser.java | 916 +++++++++++++ .../cesnet/cloud/occi/renderer/TextRenderer.java | 35 + .../cz/cesnet/cloud/occi/type/Identifiable.java | 14 + .../java/cz/cesnet/cloud/occi/CollectionTest.java | 38 + .../java/cz/cesnet/cloud/occi/DataGenerator.java | 295 +++++ .../test/java/cz/cesnet/cloud/occi/ModelTest.java | 252 ++++ .../test/java/cz/cesnet/cloud/occi/TestHelper.java | 14 + .../occi/collection/AttributeMapCoverTest.java | 142 ++ .../cesnet/cloud/occi/collection/SetCoverTest.java | 132 ++ .../cesnet/cloud/occi/core/ActionInstanceTest.java | 70 + .../java/cz/cesnet/cloud/occi/core/ActionTest.java | 77 ++ .../cz/cesnet/cloud/occi/core/AttributeTest.java | 74 ++ .../cz/cesnet/cloud/occi/core/CategoryTest.java | 42 + .../java/cz/cesnet/cloud/occi/core/EntityTest.java | 118 ++ .../java/cz/cesnet/cloud/occi/core/KindTest.java | 171 +++ .../java/cz/cesnet/cloud/occi/core/LinkTest.java | 156 +++ .../java/cz/cesnet/cloud/occi/core/MixinTest.java | 166 +++ .../cz/cesnet/cloud/occi/core/ResourceTest.java | 61 + .../cesnet/cloud/occi/parser/TextParserTest.java | 1357 ++++++++++++++++++++ jOCCI-core/src/test/resources/log4j.properties | 8 + .../text/collection_occi_action_attribute.txt | 1 + .../text/collection_occi_action_category.txt | 1 + .../parser/text/collection_occi_link_attribute.txt | 1 + .../parser/text/collection_occi_link_category.txt | 1 + .../text/collection_occi_resource_attribute.txt | 1 + .../text/collection_occi_resource_category.txt | 1 + .../parser/text/collection_occi_resource_link.txt | 1 + .../parser/text/collection_plain_action.txt | 7 + .../parser/text/collection_plain_link.txt | 12 + .../parser/text/collection_plain_resource.txt | 17 + .../test/resources/parser/text/locations_plain.txt | 3 + .../resources/parser/text/locations_uri-list.txt | 3 + .../parser/text/model_occi_actions_full.txt | 1 + .../parser/text/model_occi_actions_minimal.txt | 1 + .../test/resources/parser/text/model_occi_all.txt | 1 + .../parser/text/model_occi_kinds_full.txt | 1 + .../parser/text/model_occi_kinds_minimal.txt | 1 + .../parser/text/model_occi_mixins_full.txt | 1 + .../parser/text/model_occi_mixins_minimal.txt | 1 + .../parser/text/model_plain_actions_full.txt | 5 + .../parser/text/model_plain_actions_minimal.txt | 1 + .../test/resources/parser/text/model_plain_all.txt | 15 + .../parser/text/model_plain_kinds_full.txt | 5 + .../parser/text/model_plain_kinds_minimal.txt | 1 + .../parser/text/model_plain_mixins_full.txt | 5 + .../parser/text/model_plain_mixins_minimal.txt | 1 + .../rendering/text/action_headers_attributes.txt | 6 + .../rendering/text/action_headers_category.txt | 1 + .../test/resources/rendering/text/action_plain.txt | 7 + .../rendering/text/inline_link_headers.txt | 4 + .../resources/rendering/text/inline_link_plain.txt | 4 + .../test/resources/rendering/text/kind_headers.txt | 9 + .../test/resources/rendering/text/kind_plain.txt | 9 + .../rendering/text/link_headers_attributes.txt | 7 + .../rendering/text/link_headers_categories.txt | 4 + .../test/resources/rendering/text/link_plain.txt | 11 + .../resources/rendering/text/mixin_headers.txt | 6 + .../test/resources/rendering/text/mixin_plain.txt | 6 + .../rendering/text/resource_headers_attributes.txt | 7 + .../rendering/text/resource_headers_categories.txt | 6 + .../rendering/text/resource_headers_links.txt | 4 + .../resources/rendering/text/resource_plain.txt | 17 + 117 files changed, 10590 insertions(+) create mode 100644 jOCCI-core/.gitignore create mode 100644 jOCCI-core/.travis.yml create mode 100644 jOCCI-core/LICENSE create mode 100644 jOCCI-core/README.md create mode 100644 jOCCI-core/debian/README.source create mode 100644 jOCCI-core/debian/changelog create mode 100644 jOCCI-core/debian/compat create mode 100644 jOCCI-core/debian/control create mode 100644 jOCCI-core/debian/copyright create mode 100644 jOCCI-core/debian/libjocci-core-java-doc.doc-base.api create mode 100644 jOCCI-core/debian/libjocci-core-java-doc.install create mode 100644 jOCCI-core/debian/libjocci-core-java.poms create mode 100644 jOCCI-core/debian/maven.cleanIgnoreRules create mode 100644 jOCCI-core/debian/maven.ignoreRules create mode 100644 jOCCI-core/debian/maven.properties create mode 100644 jOCCI-core/debian/maven.publishedRules create mode 100644 jOCCI-core/debian/maven.rules create mode 100755 jOCCI-core/debian/rules create mode 100644 jOCCI-core/debian/source/format create mode 100644 jOCCI-core/pom.xml create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Collection.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Model.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/AttributeMapCover.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/SetCover.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Action.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/ActionInstance.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Attribute.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Category.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Entity.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Kind.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Link.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Mixin.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Resource.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/AmbiguousIdentifierException.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeException.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeValueException.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/ParsingException.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/RenderingException.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Compute.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetwork.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetworkInterface.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Network.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/NetworkInterface.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Storage.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/StorageLink.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Allocation.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Architecture.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/ComputeState.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/NetworkState.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageLinkState.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageState.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/CollectionType.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/JSONParser.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/MediaType.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/Parser.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/TextParser.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/renderer/TextRenderer.java create mode 100644 jOCCI-core/src/main/java/cz/cesnet/cloud/occi/type/Identifiable.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/CollectionTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/DataGenerator.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/ModelTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/TestHelper.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/AttributeMapCoverTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/SetCoverTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionInstanceTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/AttributeTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/CategoryTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/EntityTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/KindTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/LinkTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/MixinTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ResourceTest.java create mode 100644 jOCCI-core/src/test/java/cz/cesnet/cloud/occi/parser/TextParserTest.java create mode 100644 jOCCI-core/src/test/resources/log4j.properties create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_action_attribute.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_action_category.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_link_attribute.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_link_category.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_resource_attribute.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_resource_category.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_occi_resource_link.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_plain_action.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_plain_link.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/collection_plain_resource.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/locations_plain.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/locations_uri-list.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_actions_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_actions_minimal.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_all.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_kinds_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_kinds_minimal.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_mixins_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_occi_mixins_minimal.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_actions_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_actions_minimal.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_all.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_kinds_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_kinds_minimal.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_mixins_full.txt create mode 100644 jOCCI-core/src/test/resources/parser/text/model_plain_mixins_minimal.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/action_headers_attributes.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/action_headers_category.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/action_plain.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/inline_link_headers.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/inline_link_plain.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/kind_headers.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/kind_plain.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/link_headers_attributes.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/link_headers_categories.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/link_plain.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/mixin_headers.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/mixin_plain.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/resource_headers_attributes.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/resource_headers_categories.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/resource_headers_links.txt create mode 100644 jOCCI-core/src/test/resources/rendering/text/resource_plain.txt diff --git a/jOCCI-core/.gitignore b/jOCCI-core/.gitignore new file mode 100644 index 0000000..9ffb98a --- /dev/null +++ b/jOCCI-core/.gitignore @@ -0,0 +1,7 @@ +build.xml +/nbproject +nb-configuration.xml +/target/ +release.properties +pom.xml.releaseBackup +nbactions.xml diff --git a/jOCCI-core/.travis.yml b/jOCCI-core/.travis.yml new file mode 100644 index 0000000..11846ed --- /dev/null +++ b/jOCCI-core/.travis.yml @@ -0,0 +1,10 @@ +language: java + +jdk: + - openjdk7 + - oraclejdk7 + - oraclejdk8 + +bracnhes: + only: + - master diff --git a/jOCCI-core/LICENSE b/jOCCI-core/LICENSE new file mode 100644 index 0000000..f73d873 --- /dev/null +++ b/jOCCI-core/LICENSE @@ -0,0 +1,17 @@ +The work represented by this source file is partially or entirely funded +by the EGI-InSPIRE project through the European Commission's 7th Framework +Programme (contract # INFSO-RI-261323) + +Copyright (c) 2014-2015 CESNET + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/jOCCI-core/README.md b/jOCCI-core/README.md new file mode 100644 index 0000000..1098dad --- /dev/null +++ b/jOCCI-core/README.md @@ -0,0 +1,31 @@ +jOCCI-core - A Java OCCI Framework +================================== + +[![Build Status](https://secure.travis-ci.org/EGI-FCTF/jOCCI-core.png)](http://travis-ci.org/EGI-FCTF/jOCCI-core) + +Requirements +------------ +* JDK 7+ +* Maven + +Installation +------------ +Using Maven: +```xml + + cz.cesnet.cloud + jocci-core + 0.2.4 + +``` +### Continuous integration + +[Continuous integration for jOCCI by Travis-CI](http://travis-ci.org/EGI-FCTF/jOCCI-core/) + +### Contribute + +1. Fork it. +2. Create a branch (git checkout -b my_markup) +3. Commit your changes (git commit -am "My changes") +4. Push to the branch (git push origin my_markup) +5. Create an Issue with a link to your branch diff --git a/jOCCI-core/debian/README.source b/jOCCI-core/debian/README.source new file mode 100644 index 0000000..c7c6f7a --- /dev/null +++ b/jOCCI-core/debian/README.source @@ -0,0 +1,9 @@ +Information about jocci-core +---------------------------- + +This package was debianized using the mh_make command +from the maven-debian-helper package. + +The build system uses Maven but prevents it from downloading +anything from the Internet, making the build compliant with +the Debian policy. diff --git a/jOCCI-core/debian/changelog b/jOCCI-core/debian/changelog new file mode 100644 index 0000000..8bcaaae --- /dev/null +++ b/jOCCI-core/debian/changelog @@ -0,0 +1,5 @@ +jocci-core (0.2.4-1) unstable; urgency=low + + * Initial release + + -- František Dvořák Fri, 09 Sep 2016 00:13:39 +0200 diff --git a/jOCCI-core/debian/compat b/jOCCI-core/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/jOCCI-core/debian/compat @@ -0,0 +1 @@ +9 diff --git a/jOCCI-core/debian/control b/jOCCI-core/debian/control new file mode 100644 index 0000000..494f2c0 --- /dev/null +++ b/jOCCI-core/debian/control @@ -0,0 +1,46 @@ +Source: jocci-core +Section: java +Priority: optional +Maintainer: Debian Java Maintainers +Uploaders: František Dvořák +Build-Depends: debhelper (>= 9), cdbs, default-jdk, maven-debian-helper (>= 1.5) +Build-Depends-Indep: libslf4j-java, junit4, libslf4j-java, default-jdk-doc, libmaven-javadoc-plugin-java +Standards-Version: 3.9.5 +Vcs-Svn: svn://anonscm.debian.org/pkg-java/trunk/jocci-core +Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-java/trunk/jocci-core +Homepage: https://github.com/EGI-FCTF/jOCCI-core + +Package: libjocci-core-java +Architecture: all +Depends: ${misc:Depends}, ${maven:Depends} +Recommends: ${maven:OptionalDepends} +Suggests: libjocci-core-java-doc +Description: cz.cesnet.cloud:jocci-core + OCCI-core is a java-based implementation of the OCCI (Open Cloud Computing + Interface) standard. jOCCI-core currently implements: + . + * classes defined by the OCCI Core model and methods for manipulating them + * methods for rendering plain-text or HTTP header representations of those + classes' instances + * methods for basic parsing of such renderings + * methods for validation of OCCI requests with respect to known models on + client-side + +Package: libjocci-core-java-doc +Architecture: all +Section: doc +Depends: ${misc:Depends}, ${maven:DocDepends} +Recommends: ${maven:DocOptionalDepends} +Suggests: libjocci-core-java +Description: Documentation for cz.cesnet.cloud:jocci-core + OCCI-core is a java-based implementation of the OCCI (Open Cloud Computing + Interface) standard. jOCCI-core currently implements: + . + * classes defined by the OCCI Core model and methods for manipulating them + * methods for rendering plain-text or HTTP header representations of those + classes' instances + * methods for basic parsing of such renderings + * methods for validation of OCCI requests with respect to known models on + client-side + . + This package contains the API documentation of libjocci-core-java. diff --git a/jOCCI-core/debian/copyright b/jOCCI-core/debian/copyright new file mode 100644 index 0000000..b87f4f3 --- /dev/null +++ b/jOCCI-core/debian/copyright @@ -0,0 +1,17 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: cz.cesnet.cloud:jocci-core +Source: https://github.com/EGI-FCTF/jOCCI-core + +Files: * +Copyright: 2016, Michal Kimle +License: Apache-2.0 + +Files: debian/* +Copyright: 2016, František Dvořák +License: Apache-2.0 + +License: Apache-2.0 + On Debian systems, the full text of the Apache-2.0 license + can be found in the file '/usr/share/common-licenses/Apache-2.0' + + diff --git a/jOCCI-core/debian/libjocci-core-java-doc.doc-base.api b/jOCCI-core/debian/libjocci-core-java-doc.doc-base.api new file mode 100644 index 0000000..9586f94 --- /dev/null +++ b/jOCCI-core/debian/libjocci-core-java-doc.doc-base.api @@ -0,0 +1,10 @@ +Document: libjocci-core-java +Title: API Javadoc for cz.cesnet.cloud:jocci-core +Author: cz.cesnet.cloud:jocci-core developers +Abstract: This is the API Javadoc provided for the + libjocci-core-java library. +Section: Programming + +Format: HTML +Index: /usr/share/doc/libjocci-core-java/api/index.html +Files: /usr/share/doc/libjocci-core-java/api/* diff --git a/jOCCI-core/debian/libjocci-core-java-doc.install b/jOCCI-core/debian/libjocci-core-java-doc.install new file mode 100644 index 0000000..ee353e1 --- /dev/null +++ b/jOCCI-core/debian/libjocci-core-java-doc.install @@ -0,0 +1,2 @@ +target/apidocs/* usr/share/doc/libjocci-core-java/api + diff --git a/jOCCI-core/debian/libjocci-core-java.poms b/jOCCI-core/debian/libjocci-core-java.poms new file mode 100644 index 0000000..0417132 --- /dev/null +++ b/jOCCI-core/debian/libjocci-core-java.poms @@ -0,0 +1,28 @@ +# List of POM files for the package +# Format of this file is: +# [option]* +# where option can be: +# --ignore: ignore this POM and its artifact if any +# --ignore-pom: don't install the POM. To use on POM files that are created +# temporarily for certain artifacts such as Javadoc jars. [mh_install, mh_installpoms] +# --no-parent: remove the tag from the POM +# --package=: an alternative package to use when installing this POM +# and its artifact +# --has-package-version: to indicate that the original version of the POM is the same as the upstream part +# of the version for the package. +# --keep-elements=: a list of XML elements to keep in the POM +# during a clean operation with mh_cleanpom or mh_installpom +# --artifact=: path to the build artifact associated with this POM, +# it will be installed when using the command mh_install. [mh_install] +# --java-lib: install the jar into /usr/share/java to comply with Debian +# packaging guidelines +# --usj-name=: name to use when installing the library in /usr/share/java +# --usj-version=: version to use when installing the library in /usr/share/java +# --no-usj-versionless: don't install the versionless link in /usr/share/java +# --dest-jar=: the destination for the real jar. +# It will be installed with mh_install. [mh_install] +# --classifier=: Optional, the classifier for the jar. Empty by default. +# --site-xml=: Optional, the location for site.xml if it needs to be installed. +# Empty by default. [mh_install] +# +pom.xml --has-package-version diff --git a/jOCCI-core/debian/maven.cleanIgnoreRules b/jOCCI-core/debian/maven.cleanIgnoreRules new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/jOCCI-core/debian/maven.cleanIgnoreRules @@ -0,0 +1 @@ + diff --git a/jOCCI-core/debian/maven.ignoreRules b/jOCCI-core/debian/maven.ignoreRules new file mode 100644 index 0000000..01de3b8 --- /dev/null +++ b/jOCCI-core/debian/maven.ignoreRules @@ -0,0 +1,5 @@ + +com.github.github site-maven-plugin * * * * +org.apache.maven.plugins maven-javadoc-plugin * * * * +org.apache.maven.plugins maven-release-plugin * * * * +org.sonatype.plugins nexus-staging-maven-plugin * * * * diff --git a/jOCCI-core/debian/maven.properties b/jOCCI-core/debian/maven.properties new file mode 100644 index 0000000..7c29bd7 --- /dev/null +++ b/jOCCI-core/debian/maven.properties @@ -0,0 +1,4 @@ +# Include here properties to pass to Maven during the build. +# For example: +# maven.test.skip=true + diff --git a/jOCCI-core/debian/maven.publishedRules b/jOCCI-core/debian/maven.publishedRules new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/jOCCI-core/debian/maven.publishedRules @@ -0,0 +1 @@ + diff --git a/jOCCI-core/debian/maven.rules b/jOCCI-core/debian/maven.rules new file mode 100644 index 0000000..47fc41f --- /dev/null +++ b/jOCCI-core/debian/maven.rules @@ -0,0 +1,3 @@ + +cz.cesnet.cloud jocci-core jar s/.*/debian/ * * +junit junit jar s/4\..*/4.x/ * * diff --git a/jOCCI-core/debian/rules b/jOCCI-core/debian/rules new file mode 100755 index 0000000..b76c54a --- /dev/null +++ b/jOCCI-core/debian/rules @@ -0,0 +1,9 @@ +#!/usr/bin/make -f + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/maven.mk + +JAVA_HOME := /usr/lib/jvm/default-java + +get-orig-source: + uscan --download-version $(DEB_UPSTREAM_VERSION) --force-download --rename diff --git a/jOCCI-core/debian/source/format b/jOCCI-core/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/jOCCI-core/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/jOCCI-core/pom.xml b/jOCCI-core/pom.xml new file mode 100644 index 0000000..30ff58c --- /dev/null +++ b/jOCCI-core/pom.xml @@ -0,0 +1,186 @@ + + + 4.0.0 + cz.cesnet.cloud + jocci-core + 0.2.4 + jar + ${project.groupId}:${project.artifactId} + A Java OCCI framework - core library. + https://github.com/EGI-FCTF/jOCCI-core + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Michal Kimle + kimle.michal@gmail.com + CESNET + http://www.cesnet.cz/ + + + + scm:git:git@github.com:EGI-FCTF/jOCCI-core.git + scm:git:git@github.com:EGI-FCTF/jOCCI-core.git + https://github.com/EGI-FCTF/jOCCI-core + jocci-core-0.2.4 + + + + org.slf4j + slf4j-api + 1.7.7 + + + org.slf4j + slf4j-log4j12 + 1.7.7 + test + + + junit + junit + 4.10 + test + + + + UTF-8 + 1.7 + 1.7 + github + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + + + javadoc + + + + aggregate + false + + aggregate + + + + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + true + false + release + deploy + + + + org.apache.maven.plugins + maven-site-plugin + 3.4 + + + com.github.github + site-maven-plugin + 0.11 + + Creating site for ${project.version} + github + + + + + site + + site + + + + + + + + release + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + \ No newline at end of file diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Collection.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Collection.java new file mode 100644 index 0000000..64101b8 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Collection.java @@ -0,0 +1,320 @@ +package cz.cesnet.cloud.occi; + +import cz.cesnet.cloud.occi.collection.SetCover; +import cz.cesnet.cloud.occi.core.ActionInstance; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Resource; +import java.util.Objects; +import java.util.Set; + +/** + * Class representing a collection of OCCI instances. It can contain instances + * of classes Resource, Link and ActionInstance. Collection can be assigned a + * Model instance which will represent a OCCI model structure for all the + * instances in the collection. + * + * @author Michal Kimle + */ +public class Collection { + + private final SetCover resources = new SetCover<>(); + private final SetCover links = new SetCover<>(); + private final SetCover actions = new SetCover<>(); + private Model model; + + /** + * Creates an empty collection instance. + */ + public Collection() { + } + + /** + * Checks whether collection contains the resource. + * + * @param resource resource looked up in the collection + * @return true if collection contains the resource, false otherwise + */ + public boolean containsResource(Resource resource) { + return resources.contains(resource); + } + + /** + * Checks whether collection contains the resource specified by its + * identifier. + * + * @param resourceIdentifier identifier of the resource looked up in the + * collection + * @return true if collection contains the resource, false otherwise + */ + public boolean containsResource(String resourceIdentifier) { + return resources.contains(resourceIdentifier); + } + + /** + * Adds resource instance to the collection. + * + * @param resource resource to be added to the collection + * @return true if the addition was successful, false otherwise + */ + public boolean addResource(Resource resource) { + return resources.add(resource); + } + + /** + * Retrieves the resource specified by its identifier from the collection. + * + * @param resourceIdentifier identifier of the retrieved resource + * @return specified resource if in collection, null otherwise + */ + public Resource getResource(String resourceIdentifier) { + return resources.get(resourceIdentifier); + } + + /** + * Removes resource from the collection. + * + * @param resource resource instance to remove from the collection + * @return true if the removal was successful, false otherwise + */ + public boolean removeResource(Resource resource) { + return resources.remove(resource); + } + + /** + * Removes all resources from the collection. + */ + public void clearResources() { + resources.clear(); + } + + /** + * Returns all resources in the collection in form of a set. + * + * @return set of all resources in the collection + */ + public Set getResources() { + return resources.getSet(); + } + + /** + * Checks whether collection contains the link. + * + * @param link link looked up in the collection + * @return true if collection contains the link, false otherwise + */ + public boolean containsLink(Link link) { + return links.contains(link); + } + + /** + * Checks whether collection contains the link specified by its identifier. + * + * @param linkIdentifier identifier of the link looked up in the collection + * @return true if collection contains the link, false otherwise + */ + public boolean containsLink(String linkIdentifier) { + return links.contains(linkIdentifier); + } + + /** + * Adds link instance to the collection. + * + * @param link link to be added to the collection + * @return true if the addition was successful, false otherwise + */ + public boolean addLink(Link link) { + return links.add(link); + } + + /** + * Retrieves the link specified by its identifier from the collection. + * + * @param linkIdentifier identifier of the retrieved link + * @return specified link if in collection, null otherwise + */ + public Link getLink(String linkIdentifier) { + return links.get(linkIdentifier); + } + + /** + * Removes link from the collection. + * + * @param link link instance to remove from the collection + * @return true if the removal was successful, false otherwise + */ + public boolean removeLink(Link link) { + return links.remove(link); + } + + /** + * Removes all links from the collection. + */ + public void clearLinks() { + links.clear(); + } + + /** + * Returns all links in the collection in form of a set. + * + * @return set of all links in the collection + */ + public Set getLinks() { + return links.getSet(); + } + + /** + * Checks whether collection contains the action. + * + * @param action action looked up in the collection + * @return true if collection contains the action, false otherwise + */ + public boolean containsAction(ActionInstance action) { + return actions.contains(action); + } + + /** + * Checks whether collection contains the action specified by its + * identifier. + * + * @param actionIdentifier identifier of the action looked up in the + * collection + * @return true if collection contains the action, false otherwise + */ + public boolean containsAction(String actionIdentifier) { + return actions.contains(actionIdentifier); + } + + /** + * Adds action instance to the collection. + * + * @param action action to be added to the collection + * @return true if the addition was successful, false otherwise + */ + public boolean addAction(ActionInstance action) { + return actions.add(action); + } + + /** + * Retrieves the action specified by its identifier from the collection. + * + * @param actionIdentifier identifier of the retrieved action + * @return specified action if in collection, null otherwise + */ + public ActionInstance getAction(String actionIdentifier) { + return actions.get(actionIdentifier); + } + + /** + * Removes action from the collection. + * + * @param action action instance to remove from the collection + * @return true if the removal was successful, false otherwise + */ + public boolean removeAction(ActionInstance action) { + return actions.remove(action); + } + + /** + * Removes all actions from the collection. + */ + public void clearActions() { + actions.clear(); + } + + /** + * Returns all actions in the collection in form of a set. + * + * @return set of all actions in the collection + */ + public Set getActions() { + return actions.getSet(); + } + + /** + * Merges collection's content to the current collection. + * + * @param collection collection which content should be merged + */ + public void merge(Collection collection) { + resources.addAll(collection.getResources()); + links.addAll(collection.getLinks()); + actions.addAll(collection.getActions()); + } + + /** + * Sets model for the whole collection (all the resources, links and actions + * in the collection) + * + * @param model model to be set for this collection + */ + public void setModel(Model model) { + this.model = model; + for (Link link : links.getSet(true)) { + link.setModel(model); + } + for (Resource resource : resources.getSet(true)) { + resource.setModel(model); + } + for (ActionInstance ai : actions.getSet(true)) { + ai.setModel(model); + } + } + + /** + * Returns collection's model. + * + * @return collection's model + */ + public Model getModel() { + return model; + } + + /** + * @see Object#hashCode() + * @return collection's hash code + */ + @Override + public int hashCode() { + int hash = 5; + hash = 41 * hash + Objects.hashCode(this.resources); + hash = 41 * hash + Objects.hashCode(this.links); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare collection with + * @return true if two collections are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Collection other = (Collection) obj; + if (!Objects.equals(this.resources, other.resources)) { + return false; + } + if (!Objects.equals(this.links, other.links)) { + return false; + } + if (!Objects.equals(this.actions, other.actions)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the collection + * + * @see Object#toString() + * @return string representation of the collection + */ + @Override + public String toString() { + return "Collection{" + "resources=" + resources + ", links=" + links + ", model=" + model + '}'; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Model.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Model.java new file mode 100644 index 0000000..f9cdb9e --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/Model.java @@ -0,0 +1,586 @@ +package cz.cesnet.cloud.occi; + +import cz.cesnet.cloud.occi.collection.SetCover; +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.AmbiguousIdentifierException; +import cz.cesnet.cloud.occi.parser.CollectionType; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Class representing an OCCI model. Can contain instances of classes Kind, + * Mixin and Action. + * + * @author Michal Kimle + */ +public class Model { + + private final SetCover kinds = new SetCover<>(); + private final SetCover mixins = new SetCover<>(); + private final SetCover actions = new SetCover<>(); + + /** + * Creates an empty model. + */ + public Model() { + } + + /** + * Checks whether model contains a kind + * + * @param kind kind looked up in the model + * @return true if model contains the kind, false otherwise + */ + public boolean containsKind(Kind kind) { + return kinds.contains(kind); + } + + /** + * Checks whether model contains a kind specified by the identifier + * + * @param kindIdentifier identifier for the kind looked up in the model + * @return true if model contains the kind, false otherwise + */ + public boolean containsKind(String kindIdentifier) { + return kinds.contains(kindIdentifier); + } + + /** + * Adds kind to the model. + * + * @param kind kind to be added to the model + * @return true if the addition was successful, false otherwise + */ + public boolean addKind(Kind kind) { + return kinds.add(kind); + } + + /** + * Retrieves a kind from the model. + * + * @param kindIdentifier identifier of the kind to be retrieved + * @return kind instance from the mdoel + */ + public Kind getKind(String kindIdentifier) { + return kinds.get(kindIdentifier); + } + + /** + * Removes kind from model. + * + * @param kind kind to be removed from the model + * @return true if the removal was successful, false otherwise + */ + public boolean removeKind(Kind kind) { + return kinds.remove(kind); + } + + /** + * Remove all kinds from the model. + */ + public void clearKinds() { + kinds.clear(); + } + + /** + * Returns all kinds from the model in a form of set. + * + * @return set of all kinds from the model + */ + public Set getKinds() { + return kinds.getSet(); + } + + /** + * Checks whether model contains a mixin + * + * @param mixin mixin looked up in the model + * @return true if model contains the mixin, false otherwise + */ + public boolean containsMixin(Mixin mixin) { + return mixins.contains(mixin); + } + + /** + * Checks whether model contains a mixin specified by the identifier + * + * @param mixinIdentifier identifier for the mixin looked up in the model + * @return true if model contains the mixin, false otherwise + */ + public boolean containsMixin(String mixinIdentifier) { + return mixins.contains(mixinIdentifier); + } + + /** + * Adds mixin to the model. + * + * @param mixin mixin to be added to the model + * @return true if the addition was successful, false otherwise + */ + public boolean addMixin(Mixin mixin) { + return mixins.add(mixin); + } + + /** + * Retrieves a mixin from the model. + * + * @param mixinIdentifier identifier of the mixin to be retrieved + * @return mixin instance from the mdoel + */ + public Mixin getMixin(String mixinIdentifier) { + return mixins.get(mixinIdentifier); + } + + /** + * Removes mixin from model. + * + * @param mixin mixin to be removed from the model + * @return true if the removal was successful, false otherwise + */ + public boolean removeMixin(Mixin mixin) { + return mixins.remove(mixin); + } + + /** + * Remove all mixins from the model. + */ + public void clearMixins() { + mixins.clear(); + } + + /** + * Returns all mixins from the model in a form of set. + * + * @return set of all mixins from the model + */ + public Set getMixins() { + return mixins.getSet(); + } + + /** + * Checks whether model contains a action + * + * @param action action looked up in the model + * @return true if model contains the action, false otherwise + */ + public boolean containsAction(Action action) { + return actions.contains(action); + } + + /** + * Checks whether model contains a action specified by the identifier + * + * @param actionIdentifier identifier for the action looked up in the model + * @return true if model contains the action, false otherwise + */ + public boolean containsAction(String actionIdentifier) { + return actions.contains(actionIdentifier); + } + + /** + * Adds action to the model. + * + * @param action action to be added to the model + * @return true if the addition was successful, false otherwise + */ + public boolean addAction(Action action) { + return actions.add(action); + } + + /** + * Retrieves a action from the model. + * + * @param actionIdentifier identifier of the action to be retrieved + * @return action instance from the mdoel + */ + public Action getAction(String actionIdentifier) { + return actions.get(actionIdentifier); + } + + /** + * Removes action from model. + * + * @param action action to be removed from the model + * @return true if the removal was successful, false otherwise + */ + public boolean removeAction(Action action) { + return actions.remove(action); + } + + /** + * Remove all actions from the model. + */ + public void clearActions() { + actions.clear(); + } + + /** + * Returns all actions from the model in a form of set. + * + * @return set of all actions from the model + */ + public Set getActions() { + return actions.getSet(); + } + + /** + * Finds kind with given identifier (schema+term) in model. + * + * @param identifier + * @return Kind instance with given identifier if found, null otherwise + */ + public Kind findKind(URI identifier) { + if (identifier == null) { + return null; + } + + String identifierString = identifier.toString(); + for (Kind kind : kinds.getSet()) { + if (kind.getIdentifier().equals(identifierString)) { + return kind; + } + } + + return null; + } + + /** + * Finds kind with given term in model. + * + * @param term + * @return Kind instance with given term if found, null otherwise + * @throws AmbiguousIdentifierException if model contains more than one kind + * with given term + */ + public Kind findKind(String term) throws AmbiguousIdentifierException { + Kind foundKind = null; + for (Kind kind : kinds.getSet()) { + if (kind.getTerm().equals(term)) { + if (foundKind != null) { + throw new AmbiguousIdentifierException("term '" + term + "' is ambiguous"); + } + foundKind = kind; + } + } + + return foundKind; + } + + /** + * Finds kinds related to kind specified by given identifier. + * + * @param identifier + * @return list of Kinds related to the one specified Kind + */ + public List findRelatedKinds(URI identifier) { + Kind main = findKind(identifier); + return getRelatedKinds(main); + } + + /** + * Finds kinds related to kind specified by given term. + * + * @param term + * @return list of Kinds related to the one specified Kind + * @throws AmbiguousIdentifierException if model contains more than one kind + * with given term + */ + public List findRelatedKinds(String term) throws AmbiguousIdentifierException { + Kind main = findKind(term); + return getRelatedKinds(main); + } + + private List getRelatedKinds(Kind main) { + List related = new ArrayList<>(); + if (main == null) { + return related; + } + + for (Kind kind : kinds.getSet()) { + if (kind.relatesTo(main)) { + related.add(kind); + } + } + + return related; + } + + /** + * Determines CollectionType for given kind (for parsing purposes). + * + * @param kind + * @return CollectionType instance if determined, null otherwise + */ + public CollectionType findKindType(Kind kind) { + while (kind != null) { + if (kind.getIdentifier().equals(Resource.KIND_IDENTIFIER_DEFAULT)) { + return CollectionType.RESOURCE; + } + if (kind.getIdentifier().equals(Link.KIND_IDENTIFIER_DEFAULT)) { + return CollectionType.LINK; + } + kind = kind.getParentKind(); + } + + return null; + } + + /** + * Determines CollectionType for kind with given location (for parsing + * purposes). + * + * @param location + * @return CollectionType instance if determined, null otherwise + */ + public CollectionType findKindType(String location) { + Kind kind = null; + for (Kind k : kinds.getSet()) { + if (k.getLocation().getPath().equals(location)) { + kind = k; + break; + } + } + + return findKindType(kind); + } + + //TODO: refactor findMixin methods + /** + * Finds mixin with given identifier (schema+term) in model. + * + * @param identifier + * @return Mixin instance with given identifier if found, null otherwise + */ + public Mixin findMixin(URI identifier) { + if (identifier == null) { + return null; + } + + String identigfierString = identifier.toString(); + for (Mixin mixin : mixins.getSet()) { + if (mixin.getIdentifier().equals(identigfierString)) { + return mixin; + } + } + + return null; + } + + /** + * Finds mixin with given term in model. + * + * @param term + * @return Mixin instance with given term if found, null otherwise + * @throws AmbiguousIdentifierException if model contains more than one + * mixin with given term + */ + public Mixin findMixin(String term) throws AmbiguousIdentifierException { + Mixin foundMixin = null; + for (Mixin mixin : mixins.getSet()) { + if (mixin.getTerm().equals(term)) { + if (foundMixin != null) { + throw new AmbiguousIdentifierException("term '" + term + "' is ambiguous"); + } + foundMixin = mixin; + } + } + + return foundMixin; + } + + /** + * Finds mixin with given term and relation in model. + * + * @param term + * @param rel term of related mixin + * @return Mixin instance with given term and relation if found, null + * otherwise + * @throws AmbiguousIdentifierException if model contains more than one + * mixin with given term + */ + public Mixin findMixin(String term, String rel) throws AmbiguousIdentifierException { + Mixin relMixin = findMixin(rel); + if (relMixin == null) { + return null; + } + + Mixin foundMixin = null; + for (Mixin mixin : mixins.getSet()) { + if (mixin.getTerm().equals(term) && mixin.relatesTo(relMixin)) { + if (foundMixin != null) { + throw new AmbiguousIdentifierException("term '" + term + "' is ambiguous"); + } + foundMixin = mixin; + } + } + + return foundMixin; + } + + /** + * Finds mixin with given term and relation in model. + * + * @param term + * @param rel identifier of related mixin (scheme+term) + * @return Mixin instance with given term and relation if found, null + * otherwise + * @throws AmbiguousIdentifierException if model contains more than one + * mixin with given term + */ + public Mixin findMixin(String term, URI rel) throws AmbiguousIdentifierException { + if (rel == null) { + return null; + } + + Mixin foundMixin = null; + for (Mixin mixin : mixins.getSet()) { + if (mixin.getTerm().equals(term) && mixin.relatesTo(rel.toString())) { + if (foundMixin != null) { + throw new AmbiguousIdentifierException("term '" + term + "' is ambiguous"); + } + foundMixin = mixin; + } + } + + return foundMixin; + } + + /** + * Finds mixins related to mixin specified by given identifier. + * + * @param identifier + * @return list of Mixins related to the one specified Mixin + */ + public List findRelatedMixins(URI identifier) { + Mixin main = findMixin(identifier); + return getRelatedMixins(main); + } + + /** + * Finds mixins related to mixin specified by given term. + * + * @param term + * @return list of Mixins related to the one specified Mixin + * @throws AmbiguousIdentifierException if model contains more than one + * mixin with given term + */ + public List findRelatedMixins(String term) throws AmbiguousIdentifierException { + Mixin main = findMixin(term); + return getRelatedMixins(main); + } + + private List getRelatedMixins(Mixin main) { + List related = new ArrayList<>(); + if (main == null) { + return related; + } + + for (Mixin mixin : mixins.getSet()) { + if (mixin.relatesTo(main)) { + related.add(mixin); + } + } + + return related; + } + + /** + * Finds action with given term in model. + * + * @param term + * @return Action instance with given term if found, null otherwise + * @throws AmbiguousIdentifierException if model contains more than one + * action with given term + */ + public Action findAction(String term) throws AmbiguousIdentifierException { + Action foundAction = null; + for (Action action : actions.getSet()) { + if (action.getTerm().equals(term)) { + if (foundAction != null) { + throw new AmbiguousIdentifierException("term '" + term + "' is ambiguous"); + } + foundAction = action; + } + } + + return foundAction; + } + + /** + * Finds action with given identifier (schema+term) in model. + * + * @param identifier + * @return Action instance with given identifier if found, null otherwise + */ + public Action findAction(URI identifier) { + if (identifier == null) { + return null; + } + + String identigfierString = identifier.toString(); + for (Action action : actions.getSet()) { + if (action.getIdentifier().equals(identigfierString)) { + return action; + } + } + + return null; + } + + /** + * @see Object#hashCode() + * @return model's hash code + */ + @Override + public int hashCode() { + int hash = 3; + hash = 59 * hash + Objects.hashCode(this.kinds); + hash = 59 * hash + Objects.hashCode(this.mixins); + hash = 59 * hash + Objects.hashCode(this.actions); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare model with + * @return true if two models are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Model other = (Model) obj; + if (!Objects.equals(this.kinds, other.kinds)) { + return false; + } + if (!Objects.equals(this.mixins, other.mixins)) { + return false; + } + if (!Objects.equals(this.actions, other.actions)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the model + * + * @see Object#toString() + * @return string representation of the model + */ + @Override + public String toString() { + return "Model{" + "kinds=" + kinds + ", mixins=" + mixins + ", actions=" + actions + '}'; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/AttributeMapCover.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/AttributeMapCover.java new file mode 100644 index 0000000..8a77868 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/AttributeMapCover.java @@ -0,0 +1,253 @@ +package cz.cesnet.cloud.occi.collection; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.parser.TextParser; +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Class representing attributes and their values. + * + * @author Michal Kimle + */ +public class AttributeMapCover { + + private final Map attributes = new HashMap<>(); + + /** + * Stores attribute and its value. + * + * @param attribute attribute to be stored. Cannot be null. + * @param value value to be stored for the attribute. Cannot be null. + */ + public void add(Attribute attribute, String value) { + if (attribute == null) { + throw new NullPointerException("Cannot add null attribute."); + } + if (value == null) { + throw new NullPointerException("Cannot add null value."); + } + + attributes.put(attribute, value); + } + + /** + * Removes attribute from the collection. + * + * @param attribute attribute to be removed. Cannot be null. + */ + public void remove(Attribute attribute) { + if (attribute == null) { + throw new NullPointerException("Cannot remove null attribute."); + } + + attributes.remove(attribute); + } + + /** + * Removes attribute from the collection. + * + * @param attributeName name of the attribute to be removed. Cannot be null. + */ + public void remove(String attributeName) { + Attribute attTmp = new Attribute(attributeName); + attributes.remove(attTmp); + } + + /** + * Checks whether collection contains the attribute. + * + * @param attribute attribute to be looked up in the collection + * @return true if collection contains the attribute, false otherwise + */ + public boolean containsAttribute(Attribute attribute) { + return attributes.containsKey(attribute); + } + + /** + * Checks whether collection contains the attribute. + * + * @param attributeName name of the attribute to be looked up in the + * collection. Cannot be null. + * @return true if collection contains the attribute, false otherwise + */ + public boolean containsAttribute(String attributeName) { + Attribute attTmp = new Attribute(attributeName); + return containsAttribute(attTmp); + } + + /** + * Returns the value for the given attribute. + * + * @param attribute attribute of which value is returned. + * @return value for the given attribute + */ + public String getValue(Attribute attribute) { + return attributes.get(attribute); + } + + /** + * Returns the value for the given attribute. + * + * @param attributeName name of the attribute of which value is returned. + * Cannot be null. + * @return value for the given attribute + */ + public String getValue(String attributeName) { + Attribute attTmp = new Attribute(attributeName); + return getValue(attTmp); + } + + /** + * Returns all the attributes and their values in form of map. + * + * @return all the attributes and their values in form of map + */ + public Map getAttributes() { + return Collections.unmodifiableMap(attributes); + } + + /** + * Removes all attributes and their values from the collection. + */ + public void clear() { + attributes.clear(); + } + + /** + * Returns the number of attributes in the collection. + * + * @return the number of attributes in the collection + */ + public int size() { + return attributes.size(); + } + + /** + * @see Object#hashCode() + * @return collection's hash code + */ + @Override + public int hashCode() { + int hash = 5; + hash = 83 * hash + Objects.hashCode(this.attributes); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare collection with + * @return true if two collections are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final AttributeMapCover other = (AttributeMapCover) obj; + if (!Objects.equals(this.attributes, other.attributes)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the collection + * + * @see Object#toString() + * @return string representation of the collection + */ + @Override + public String toString() { + return "AttributeMapCover{" + attributes + '}'; + } + + /** + * Generates a list of strings from attributes and their values + * + * @return attributes and their values in form of list of strings + */ + private List toList() { + List list = new ArrayList<>(); + List attributeList = new ArrayList<>(attributes.keySet()); + Collections.sort(attributeList); + for (Attribute attribute : attributeList) { + String name = attribute.getName(); + StringBuilder sb = new StringBuilder(name); + String value = attributes.get(attribute); + if (value.matches(TextParser.REGEXP_NUMBER)) { + sb.append(TextRenderer.surroundString(value, "=", "")); + } else { + sb.append(TextRenderer.surroundString(value, "=\"", "\"")); + } + list.add(sb.toString()); + } + + Collections.sort(list); + return list; + } + + /** + * Returns a text representation of OCCI attributes with prefix. + * + * @return text representation of OCCI attributes with prefix + */ + public String toPrefixText() { + String prefix = "X-OCCI-Attribute: "; + StringBuilder sb = new StringBuilder(); + + for (String s : toList()) { + sb.append(prefix); + sb.append(s); + sb.append("\n"); + } + + if (!sb.toString().isEmpty()) { + sb.deleteCharAt(sb.length() - 1); + } + + return sb.toString(); + } + + /** + * Returns an occi text representation of OCCI attributes in form of + * headers. + * + * @return occi text representation of OCCI attributes in form of headers + */ + public Headers toHeaders() { + Headers headers = new Headers(); + + for (String s : toList()) { + headers.add("X-OCCI-Attribute", s); + } + + return headers; + } + + /** + * Returns text representation of OCCI attributes in one line. + * + * @return text representation of OCCI attributes in one line + */ + public String toOneLineText() { + StringBuilder sb = new StringBuilder(); + + for (String s : toList()) { + + sb.append(s); + sb.append(";"); + } + + return sb.toString(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/SetCover.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/SetCover.java new file mode 100644 index 0000000..4e50009 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/collection/SetCover.java @@ -0,0 +1,193 @@ +package cz.cesnet.cloud.occi.collection; + +import cz.cesnet.cloud.occi.type.Identifiable; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.HashSet; +import java.util.Objects; + +/** + * Collection class serving as a set for all classes identifiable. + * + * @author Michal Kimle + * @param + */ +public class SetCover { + + private final Set set = new HashSet<>(); + + /** + * Checks whether set contains the element. + * + * @param element looked up in the set + * @return true if set contains the element, false otherwise + */ + public boolean contains(E element) { + return set.contains(element); + } + + /** + * Checks whether set contains an element specified by the identifier. + * + * @param elementIdentifier identifier of the element looked up in the set + * @return true if set contains the element, false otherwise + */ + public boolean contains(String elementIdentifier) { + for (E element : set) { + if (element.getIdentifier().equals(elementIdentifier)) { + return true; + } + } + + return false; + } + + /** + * Adds element to the set. + * + * @param element element to be added. Cannot be null. + * @return true if the addition was successful, false otherwise + */ + public boolean add(E element) { + if (element == null) { + throw new NullPointerException("Cannot add null element."); + } + + return set.add(element); + } + + /** + * Adds all elements from the collection to the set. + * + * @param elements collection of elements to be added. Cannot contain any + * null elements. + * @return true if the addition was successful, false otherwise + */ + public boolean addAll(Collection elements) { + if (elements.contains(null)) { + throw new NullPointerException("Cannot add null element."); + } + + return set.addAll(elements); + } + + /** + * Retrieves element rom the set. + * + * @param elementIdentifier identifier of the element to be retrieved + * @return element specified by its identifier if in set, null otherwise + */ + public E get(String elementIdentifier) { + if (!contains(elementIdentifier)) { + return null; + } + + return find(elementIdentifier); + } + + /** + * Removes element from the set + * + * @param element element to be remoed from the set. Cannot be null. + * @return true if the deletion was successful, false otherwise + */ + public boolean remove(E element) { + if (element == null) { + throw new NullPointerException("Cannot remove null element."); + } + + return set.remove(element); + } + + private E find(String elementIdentifier) { + for (E element : set) { + if (element.getIdentifier().equals(elementIdentifier)) { + return element; + } + } + + return null; + } + + /** + * Removes all the elements from the set. + */ + public void clear() { + set.clear(); + } + + /** + * Returns unmodifiable set of elements. + * + * @return unmodifiable set of elements + */ + public Set getSet() { + return getSet(false); + } + + /** + * Returns set of elements. + * + * @param modifiable specifies if the set will be modifiable or not + * @return set of elements + */ + public Set getSet(boolean modifiable) { + if (modifiable) { + return set; + } else { + return Collections.unmodifiableSet(set); + } + } + + /** + * Returns number of elements in the set. + * + * @return number of elements in the set + */ + public int size() { + return set.size(); + } + + /** + * @see Object#hashCode() + * @return set's hash code + */ + @Override + public int hashCode() { + int hash = 7; + hash = 53 * hash + Objects.hashCode(this.set); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare set with + * @return true if two sets are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final SetCover other = (SetCover) obj; + if (!Objects.equals(this.set, other.set)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the set + * + * @see Object#toString() + * @return string representation of the set + */ + @Override + public String toString() { + return "SetCover{" + set + '}'; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Action.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Action.java new file mode 100644 index 0000000..e8d56ed --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Action.java @@ -0,0 +1,279 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import cz.cesnet.cloud.occi.type.Identifiable; +import java.net.URI; +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class representing an OCCI Action structure. + * + * @author Michal Kimle + */ +public class Action implements Identifiable, Comparable { + + private static final Logger LOGGER = LoggerFactory.getLogger(Action.class); + private Category category; + + /** + * Constructor. Creates an Action instance with given scheme, term, title + * and set of attributes. + * + * @param scheme action's scheme. Cannot be null. + * @param term action's term. Cannot be null nor empty. + * @param title action's title + * @param attributes set of action's attributes + */ + public Action(URI scheme, String term, String title, Collection attributes) { + LOGGER.debug("Creating action: scheme={}, term={}, title={}, attributes={}", scheme, term, title, attributes); + this.category = new Category(scheme, term, title, null, attributes); + } + + /** + * Constructor. Creates an Action instance with given scheme and term. + * + * @param scheme action's scheme. Cannot be null. + * @param term action's term. Cannot be null nor empty. + */ + public Action(URI scheme, String term) { + this(scheme, term, null, null); + } + + /** + * Returns action's scheme. + * + * @return action's scheme. + */ + public URI getScheme() { + return category.getScheme(); + } + + /** + * Sets action's scheme. + * + * @param scheme action's scheme. Cannot be null. + */ + public void setScheme(URI scheme) { + category.setScheme(scheme); + } + + /** + * Returns action's term. + * + * @return action's term. + */ + public String getTerm() { + return category.getTerm(); + } + + /** + * Sets action's term. + * + * @param term action's term. Cannot be null nor empty. + */ + public void setTerm(String term) { + category.setTerm(term); + } + + /** + * Returns action's identifier. + * + * @return action's identifier + */ + @Override + public String getIdentifier() { + return category.getIdentifier(); + } + + /** + * Returns action's title. + * + * @return action's title + */ + public String getTitle() { + return category.getTitle(); + } + + /** + * Sets action's title. + * + * @param title action's title + */ + public void setTitle(String title) { + category.setTitle(title); + } + + /** + * Checks whether action has the attribute. + * + * @param attribute attribute to be looked up + * @return true if action has the attribute, false otherwise + */ + public boolean containsAttribute(Attribute attribute) { + return category.containsAttribute(attribute); + } + + /** + * Checks whether action has the attribute. + * + * @param attributeName name of the attribute to be looked up + * @return true if action has the attribute, false otherwise + */ + public boolean containsAttribute(String attributeName) { + return category.containsAttribute(attributeName); + } + + /** + * Adds attribute to the action. + * + * @param attribute attribute to be added + * @return true if the addition was successful, false otherwise + */ + public boolean addAttribute(Attribute attribute) { + return category.addAttribute(attribute); + } + + /** + * Retrieves an attribute from the action. + * + * @param attributeName name of the attribute to be retrieved + * @return attribute + */ + public Attribute getAttribute(String attributeName) { + return category.getAttribute(attributeName); + } + + /** + * Removes attribute from the action. + * + * @param attribute attribute to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeAttribute(Attribute attribute) { + return category.removeAttribute(attribute); + } + + /** + * Returns all action's attribute in form of set. + * + * @return all action's attribute in form of set + */ + public Set getAttributes() { + return category.getAttributes(); + } + + /** + * Returns action's default scheme 'http://schemas.ogf.org/occi/core#' + * + * @return action's default scheme + */ + public URI getSchemeDefault() { + return Category.SCHEME_CORE_DEFAULT; + } + + /** + * Returns action's default term 'term' + * + * @return action's default term + */ + public String getTermDefault() { + return "action"; + } + + /** + * @see Object#hashCode() + * @return action's hash code + */ + @Override + public int hashCode() { + int hash = 7; + hash = 29 * hash + Objects.hashCode(this.category); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare action with + * @return true if two actions are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Action other = (Action) obj; + if (!Objects.equals(this.category, other.category)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the action + * + * @see Object#toString() + * @return string representation of the action + */ + @Override + public String toString() { + return "Action{" + "category=" + category + '}'; + } + + /** + * Returns a text representation of action link as described in OCCI + * standard. + * + * @param resourceLocation + * @return text representation of action link + */ + public String toText(String resourceLocation) { + StringBuilder sb = new StringBuilder("Link: "); + sb.append(textBody(resourceLocation)); + + return sb.toString(); + } + + /** + * Returns an occi text representation of action link as described in OCCI + * standard in form of headers. + * + * @param resourceLocation + * @return text representation of action link + */ + public Headers toHeaders(String resourceLocation) { + Headers headers = new Headers(); + headers.add("Link", textBody(resourceLocation)); + + return headers; + } + + private String textBody(String resourceLocation) { + StringBuilder sb = new StringBuilder(""); + + String descriptor = resourceLocation + "?action=" + getTerm(); + sb.append(TextRenderer.surroundString(descriptor, "<", ">;")); + + sb.append("rel"); + sb.append(TextRenderer.surroundString(getScheme().toString() + getTerm())); + + return sb.toString(); + } + + /** + * Comapres two actions lexicographically based on their identifier. + * + * @see Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(Action a) { + return getIdentifier().compareTo(a.getIdentifier()); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/ActionInstance.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/ActionInstance.java new file mode 100644 index 0000000..31b3db5 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/ActionInstance.java @@ -0,0 +1,303 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.collection.AttributeMapCover; +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import cz.cesnet.cloud.occi.type.Identifiable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class representing an instance of Action + * + * @author Michal Kimle + */ +public class ActionInstance implements Identifiable, Comparable { + + private static final Logger LOGGER = LoggerFactory.getLogger(ActionInstance.class); + private final AttributeMapCover attributes = new AttributeMapCover(); + private Action action; + private Model model; + + /** + * Constructor. Creates an instance of ActionInstance with given Action. + * + * @param action action to create instance of. Cannot be null. + */ + public ActionInstance(Action action) { + LOGGER.debug("Creating ActionInstance: action={}", action); + + if (action == null) { + throw new NullPointerException("ActionInstance action cannot be null."); + } + + this.action = action; + } + + /** + * Returns action of this instance. + * + * @return action of this instance + */ + public Action getAction() { + return action; + } + + /** + * Sets action for this instance. + * + * @param action action for this instance. Cannot be null. + */ + public void setAction(Action action) { + if (action == null) { + throw new NullPointerException("ActionInstance action cannot be null."); + } + + this.action = action; + } + + /** + * Returns action's identifier. + * + * @return action's identifier + */ + @Override + public String getIdentifier() { + return action.getIdentifier(); + } + + /** + * Returns instance's model. + * + * @return instance's model + */ + public Model getModel() { + return model; + } + + /** + * Sets model for the instance. + * + * @param model model for the instance + */ + public void setModel(Model model) { + this.model = model; + } + + /** + * Adds attribute and its value for the instance. + * + * @param attribute attribute to be added + * @param value value of the attribute to be added + */ + public void addAttribute(Attribute attribute, String value) { + attributes.add(attribute, value); + } + + /** + * Adds all attributes and their values from the given map. + * + * @param attributes map of attributes and their values + */ + public void addAttributes(Map attributes) { + for (String name : attributes.keySet()) { + addAttribute(new Attribute(name), attributes.get(name)); + } + } + + /** + * Removes attribute and its value from the instance. + * + * @param attribute attribute to be removed + */ + public void removeAttribute(Attribute attribute) { + attributes.remove(attribute); + } + + /** + * Checks whether the instance has an attribute. + * + * @param attribute attribute to be looked up + * @return true if instance has the attribute, false otherwise + */ + public boolean containsAttribute(Attribute attribute) { + return attributes.containsAttribute(attribute); + } + + /** + * Checks whether the instance has an attribute. + * + * @param attributeName name of the attribute to be looked up + * @return true if instance has the attribute, false otherwise + */ + public boolean containsAttribute(String attributeName) { + return attributes.containsAttribute(attributeName); + } + + /** + * Returns value of the given attribute. + * + * @param attribute attribute which value is returned + * @return value of the given attribute + */ + public String getValue(Attribute attribute) { + return attributes.getValue(attribute); + } + + /** + * Returns value of the given attribute. + * + * @param attributeName name of the attribute which value is returned + * @return value of the given attribute + */ + public String getValue(String attributeName) { + return attributes.getValue(attributeName); + } + + /** + * Returns all instance's attributes and their values in form of map. + * + * @return all instance's attributes and their values in form of map + */ + public Map getAttributes() { + return attributes.getAttributes(); + } + + /** + * Removes all attributes with their values from the instance. + */ + public void clearAttributes() { + attributes.clear(); + } + + /** + * Returns a plain text representation of action instance as described in + * OCCI standard. + * + * @return text representation of action instance + */ + public String toText() { + StringBuilder sb = new StringBuilder("Category: "); + sb.append(textBody()); + + String attributesString = attributes.toPrefixText(); + if (!attributesString.isEmpty()) { + sb.append("\n"); + sb.append(attributesString); + } + + return sb.toString(); + } + + /** + * Returns an occi text representation of action instance as described in + * OCCI standard in form of headers. + * + * @return occi text representation of action instance in form of headers + */ + public Headers toHeaders() { + Headers headers = new Headers(); + headers.add("Category", textBody()); + + Headers attributesHeaders = attributes.toHeaders(); + if (!attributesHeaders.isEmpty()) { + headers.putAll(attributesHeaders); + } + + return headers; + } + + private String textBody() { + StringBuilder sb = new StringBuilder(action.getTerm()); + sb.append(";"); + sb.append("scheme"); + sb.append(TextRenderer.surroundString(action.getScheme().toString())); + sb.append("class"); + sb.append(TextRenderer.surroundString(action.getClass().getSimpleName().toLowerCase())); + + String title = action.getTitle(); + if (title != null && !title.isEmpty()) { + sb.append("title"); + sb.append(TextRenderer.surroundString(title)); + } + + Set actionAttributes = action.getAttributes(); + if (actionAttributes != null && !actionAttributes.isEmpty()) { + sb.append("attributes"); + StringBuilder attrSB = new StringBuilder(); + List attributeList = new ArrayList<>(actionAttributes); + Collections.sort(attributeList); + for (Attribute attribute : attributeList) { + attrSB.append(attribute.toText()); + attrSB.append(" "); + } + attrSB.deleteCharAt(attrSB.length() - 1); + sb.append(TextRenderer.surroundString(attrSB.toString())); + } + + return sb.toString(); + } + + /** + * @see Object#hashCode() + * @return instance's hash code + */ + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + Objects.hashCode(this.attributes); + hash = 41 * hash + Objects.hashCode(this.action); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare instance with + * @return true if two instances are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ActionInstance other = (ActionInstance) obj; + if (!Objects.equals(this.attributes, other.attributes)) { + return false; + } + if (!Objects.equals(this.action, other.action)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the instance + * + * @see Object#toString() + * @return string representation of the instance + */ + @Override + public String toString() { + return "ActionInstance{" + "attributes=" + attributes + ", action=" + action + '}'; + } + + /** + * Comapres two instances lexicographically based on their actions. + * + * @see Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(ActionInstance a) { + return getIdentifier().compareTo(a.getIdentifier()); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Attribute.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Attribute.java new file mode 100644 index 0000000..f83febb --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Attribute.java @@ -0,0 +1,300 @@ +package cz.cesnet.cloud.occi.core; + +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import cz.cesnet.cloud.occi.type.Identifiable; +import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class representing an OCCI attribute. Attributes are used to store properties + * of OCCI classes. + * + * @author Michal Kimle + */ +public class Attribute implements Identifiable, Comparable { + + private static final Logger LOGGER = LoggerFactory.getLogger(Attribute.class); + private String name; + private boolean required; + private boolean immutable; + private String type; + private String pattern; + private String defaultValue; + private String description; + + /** + * Constructor. + * + * @param name name of the attribute. Cannot be null nor empty. + * @param required whether attribute is required or not + * @param immutable whether attribute is immutable or not + * @param type attribute's type + * @param pattern attribute's pattern + * @param defaultValue attribute's default value + * @param description attribute's description + */ + public Attribute(String name, boolean required, boolean immutable, String type, String pattern, String defaultValue, String description) { + LOGGER.debug("Creating attribute: name={}, required={}, immutable={}, type={}, pattern={}, defaultValue={}, description={}", + name, required, immutable, type, pattern, defaultValue, description); + + if (name == null) { + throw new NullPointerException("Attribute name cannot be null."); + } + if (name.isEmpty()) { + throw new IllegalArgumentException("Attribute name cannot be empty."); + } + + this.name = name; + this.required = required; + this.immutable = immutable; + this.type = type; + this.pattern = pattern == null ? ".*" : pattern; + this.defaultValue = defaultValue; + this.description = description; + } + + /** + * Constructor. + * + * @param name name of the attribute. Cannot be null nor empty. + * @param required whether attribute is required or not + * @param immutable whether attribute is immutable or not + */ + public Attribute(String name, boolean required, boolean immutable) { + this(name, required, immutable, null, null, null, null); + } + + /** + * Constructor. + * + * @param name name of the attribute. Cannot be null nor empty. + */ + public Attribute(String name) { + this(name, false, false, null, null, null, null); + } + + /** + * Returns attribute's name. + * + * @return attribute's name + */ + public String getName() { + return name; + } + + /** + * Sets attribute's name. + * + * @param name attribute's name. Cannot be null nor empty + */ + public void setName(String name) { + if (name == null) { + throw new NullPointerException("Attribute name cannot be null."); + } + if (name.isEmpty()) { + throw new IllegalArgumentException("Attribute name cannot be empty."); + } + + this.name = name; + } + + /** + * Returns attribute's identifier. + * + * @return attribute's identifier + */ + @Override + public String getIdentifier() { + return getName(); + } + + /** + * Returns whether atttribute is required. + * + * @return true if attribute is required, false otherwise + */ + public boolean isRequired() { + return required; + } + + /** + * Sets attribute's requiredness. + * + * @param required whether the attribute should be required or not + */ + public void setRequired(boolean required) { + this.required = required; + } + + /** + * Returns whether atttribute is immutable. + * + * @return true if attribute is immutable, false otherwise + */ + public boolean isImmutable() { + return immutable; + } + + /** + * Sets attribute's immutability. + * + * @param immutable whether the attribute should be immutable or not + */ + public void setImmutable(boolean immutable) { + this.immutable = immutable; + } + + /** + * Returns attribute's type. + * + * @return attribute's type + */ + public String getType() { + return type; + } + + /** + * Sets attribute's type. + * + * @param type attribute's type + */ + public void setType(String type) { + this.type = type; + } + + /** + * Returns attribute's pattern. + * + * @return attribute's pattern + */ + public String getPattern() { + return pattern; + } + + /** + * Sets attribute's pattern. + * + * @param pattern attribute's pattern + */ + public void setPattern(String pattern) { + this.pattern = pattern; + } + + /** + * Returns attribute's default value. + * + * @return attribute's default value + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * Sets attribute's default value. + * + * @param defaultValue attribute's default value + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Returns attribute's description. + * + * @return attribute's description + */ + public String getDescription() { + return description; + } + + /** + * Sets attribute's description. + * + * @param description attribute's description + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @see Object#hashCode() + * @return attribute's hash code + */ + @Override + public int hashCode() { + int hash = 3; + hash = 53 * hash + Objects.hashCode(this.name); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare attribute with + * @return true if two attributes are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Attribute other = (Attribute) obj; + if (!Objects.equals(this.name, other.name)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the attribute + * + * @see Object#toString() + * @return string representation of the attribute + */ + @Override + public String toString() { + return "Attribute{" + "name=" + name + ", required=" + required + ", immutable=" + immutable + ", type=" + type + ", pattern=" + pattern + ", defaultValue=" + defaultValue + ", description=" + description + '}'; + } + + /** + * Returns plain text representation of the attribute according to OCCI + * standard. + * + * @return plain text representation of the attribute + */ + public String toText() { + StringBuilder sb = new StringBuilder(name); + + StringBuilder properties = null; + if (required) { + properties = new StringBuilder("required"); + } + + if (immutable) { + if (properties == null) { + properties = new StringBuilder("immutable"); + } else { + properties.append(" immutable"); + } + } + + if (properties != null) { + sb.append(TextRenderer.surroundString(properties.toString(), "{", "}")); + } + + return sb.toString(); + } + + /** + * Comapres two attributes lexicographically based on their identifier. + * + * @see Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(Attribute a) { + return getIdentifier().compareTo(a.getIdentifier()); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Category.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Category.java new file mode 100644 index 0000000..d261291 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Category.java @@ -0,0 +1,549 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.collection.SetCover; +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import cz.cesnet.cloud.occi.type.Identifiable; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class representing an OCCI Category. + * + * @author Michal Kimle + */ +public class Category implements Identifiable, Comparable { + + private static final Logger LOGGER = LoggerFactory.getLogger(Category.class); + public static final URI SCHEME_CORE_DEFAULT = URI.create("http://schemas.ogf.org/occi/core#"); + public static final URI SCHEME_INFRASTRUCTURE_DEFAULT = URI.create("http://schemas.ogf.org/occi/infrastructure#"); + + private String term; + private URI scheme; + private String title; + private URI location; + private final SetCover attributes = new SetCover<>(); + private final SetCover actions = new SetCover<>(); + private final SetCover entities = new SetCover<>(); + + /** + * Constructor. Creates a category with scheme, term, title, location and + * attributes. + * + * @param scheme category's scheme. Cannot be null. + * @param term category's term. Cannot be null nor empty. + * @param title category's title + * @param location category's location + * @param attributes category's attributes + */ + public Category(URI scheme, String term, String title, URI location, Collection attributes) { + LOGGER.debug("Creating category: scheme={}, term={}, title={}, location={}, attributes={}", scheme, term, title, location, attributes); + + if (scheme == null) { + throw new NullPointerException("Category scheme cannot be null."); + } + if (term == null) { + throw new NullPointerException("Category term cannot be null."); + } + if (term.isEmpty()) { + throw new IllegalArgumentException("Category term cannot be empty."); + } + + this.scheme = scheme; + this.term = term; + this.title = title; + this.location = location; + + if (attributes != null) { + this.attributes.addAll(attributes); + } + } + + /** + * Constructor. Creates a category with scheme and term. + * + * @param scheme category's scheme. Cannot be null. + * @param term category's term. Cannot be null nor empty. + */ + public Category(URI scheme, String term) { + this(scheme, term, null, null, null); + } + + /** + * Returns category's term. + * + * @return category's term + */ + public String getTerm() { + return term; + } + + /** + * Sets category's term. + * + * @param term category's term. Cannot be null nor empty. + */ + public void setTerm(String term) { + if (term == null) { + throw new NullPointerException("Category term cannot be null."); + } + if (term.isEmpty()) { + throw new IllegalArgumentException("Category term cannot be empty."); + } + + this.term = term; + } + + /** + * Returns category's scheme. + * + * @return category's scheme + */ + public URI getScheme() { + return scheme; + } + + /** + * Sets category's scheme. + * + * @param scheme category's scheme. Cannot be null. + */ + public void setScheme(URI scheme) { + if (scheme == null) { + throw new NullPointerException("Category scheme cannot be null."); + } + + this.scheme = scheme; + } + + /** + * Returns category's identifier. + * + * @return category's identifier + */ + @Override + public String getIdentifier() { + return getScheme().toString() + getTerm(); + } + + /** + * Returns category's title. + * + * @return category's title + */ + public String getTitle() { + return title; + } + + /** + * Sets category's title + * + * @param title category's title + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Returns category's location. + * + * @return category's location + */ + public URI getLocation() { + return location; + } + + /** + * Sets category's location + * + * @param location category's location + */ + public void setLocation(URI location) { + this.location = location; + } + + //attributes + /** + * Checks whether category has given attribute. + * + * @param attribute attribute to be looked up + * @return true if category has given attribute, false otherwise + */ + public boolean containsAttribute(Attribute attribute) { + return attributes.contains(attribute); + } + + /** + * Checks whether category has given attribute. + * + * @param attributeIdentifier identifier of attribute to be looked up + * @return true if category has given attribute, false otherwise + */ + public boolean containsAttribute(String attributeIdentifier) { + return attributes.contains(attributeIdentifier); + } + + /** + * Adds given attribute to category. + * + * @param attribute attribute to be added + * @return true if the addition was successful, false otherwise + */ + public boolean addAttribute(Attribute attribute) { + return attributes.add(attribute); + } + + /** + * Returns attribute from category. + * + * @param attributeIdentifier identifier of the requested attribute + * @return attribute from category + */ + public Attribute getAttribute(String attributeIdentifier) { + return attributes.get(attributeIdentifier); + } + + /** + * Removes attribute from category + * + * @param attribute to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeAttribute(Attribute attribute) { + return attributes.remove(attribute); + } + + /** + * Removes all attributes from category. + */ + public void clearAttributes() { + attributes.clear(); + } + + /** + * Returns all category's attributes in form of set. + * + * @return all category's attributes in form of set + */ + public Set getAttributes() { + return attributes.getSet(); + } + + //actions + /** + * Checks whether category has given action. + * + * @param action action to be looked up + * @return true if category has given action, false otherwise + */ + public boolean containsAction(Action action) { + return actions.contains(action); + } + + /** + * Checks whether category has given action. + * + * @param actionIdentifier identifier of action to be looked up + * @return true if category has given action, false otherwise + */ + public boolean containsAction(String actionIdentifier) { + return actions.contains(actionIdentifier); + } + + /** + * Adds given action to category. + * + * @param action action to be added + * @return true if the addition was successful, false otherwise + */ + public boolean addAction(Action action) { + return actions.add(action); + } + + /** + * Returns action from category. + * + * @param actionIdentifier identifier of the requested action + * @return action from category + */ + public Action getAction(String actionIdentifier) { + return actions.get(actionIdentifier); + } + + /** + * Removes action from category + * + * @param action to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeAction(Action action) { + return actions.remove(action); + } + + /** + * Removes all actions from category. + */ + public void clearActions() { + actions.clear(); + } + + /** + * Returns all category's actions in form of set. + * + * @return all category's actions in form of set + */ + public Set getActions() { + return actions.getSet(); + } + + //entities + /** + * Checks whether category has given entity. + * + * @param entity entity to be looked up + * @return true if category has given entity, false otherwise + */ + public boolean containsEntity(Entity entity) { + return entities.contains(entity); + } + + /** + * Checks whether category has given entity. + * + * @param entityIdentifier identifier of entity to be looked up + * @return true if category has given entity, false otherwise + */ + public boolean containsEntity(String entityIdentifier) { + return entities.contains(entityIdentifier); + } + + /** + * Adds given entity to category. + * + * @param entity entity to be added + * @return true if the addition was successful, false otherwise + */ + public boolean addEntity(Entity entity) { + return entities.add(entity); + } + + /** + * Returns entity from category. + * + * @param entityIdentifier identifier of the requested entity + * @return entity from category + */ + public Entity getEntity(String entityIdentifier) { + return entities.get(entityIdentifier); + } + + /** + * Removes entity from category + * + * @param entity to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeEntity(Entity entity) { + return entities.remove(entity); + } + + /** + * Removes all entities from category. + */ + public void clearEntities() { + entities.clear(); + } + + /** + * Returns all category's entities in form of set. + * + * @return all category's entities in form of set + */ + public Set getEntities() { + return entities.getSet(); + } + + /** + * @see Object#hashCode() + * @return category's hash code + */ + @Override + public int hashCode() { + int hash = 7; + hash = 79 * hash + Objects.hashCode(this.term); + hash = 79 * hash + Objects.hashCode(this.scheme); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare category with + * @return true if two categories are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Category other = (Category) obj; + if (!Objects.equals(this.term, other.term)) { + return false; + } + if (!Objects.equals(this.scheme, other.scheme)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the category + * + * @see Object#toString() + * @return string representation of the category + */ + @Override + public String toString() { + return "Category{" + "term=" + term + ", scheme=" + scheme + ", title=" + title + ", location=" + location + ", attributes=" + attributes + '}'; + } + + /** + * Returns a plain text representation of category and its subtypes (kinds + * and mixins) according to OCCI standard. + * + * @return plain text representation of category + */ + public String toText() { + return toText(true); + } + + /** + * Returns a plain text representation of category and its subtypes (kinds + * and mixins) according to OCCI standard. + * + * @param fullRendering whether to render all the information + * @return plain text representation of category + */ + public String toText(boolean fullRendering) { + StringBuilder sb = new StringBuilder("Category: "); + sb.append(textBody(fullRendering)); + + return sb.toString(); + } + + /** + * Returns an occi text representation of category and its subtypes (kinds + * and mixins) according to OCCI standard in form of headers. + * + * @return plain text representation of category + */ + public Headers toHeaders() { + return toHeaders(true); + } + + /** + * Returns an occi text representation of category and its subtypes (kinds + * and mixins) according to OCCI standard in form of headers. + * + * @param fullRendering whether to render all the information + * @return plain text representation of category + */ + public Headers toHeaders(boolean fullRendering) { + Headers headers = new Headers(); + headers.add("Category", textBody(fullRendering)); + + return headers; + } + + private String textBody(boolean fullRendering) { + StringBuilder sb = new StringBuilder(term); + sb.append(";"); + sb.append("scheme"); + sb.append(TextRenderer.surroundString(scheme.toString())); + sb.append("class"); + sb.append(TextRenderer.surroundString(this.getClass().getSimpleName().toLowerCase())); + + if (fullRendering) { + if (title != null && !title.isEmpty()) { + sb.append("title"); + sb.append(TextRenderer.surroundString(title)); + } + + if (this instanceof Kind) { + Kind kind = (Kind) this; + if (kind.getRelations().size() == 1) { + sb.append("rel"); + for (Kind k : kind.getRelations()) { + sb.append(TextRenderer.surroundString(k.getIdentifier())); + } + } + } + + if (this instanceof Mixin) { + Mixin mixin = (Mixin) this; + if (mixin.getRelations().size() == 1) { + sb.append("rel"); + for (Mixin m : mixin.getRelations()) { + sb.append(TextRenderer.surroundString(m.getIdentifier())); + } + } + } + + if (location != null) { + sb.append("location"); + sb.append(TextRenderer.surroundString(location.toString())); + } + + if (attributes != null && !attributes.getSet().isEmpty()) { + sb.append("attributes"); + StringBuilder attrSB = new StringBuilder(); + List attributeList = new ArrayList<>(attributes.getSet()); + Collections.sort(attributeList); + for (Attribute attribute : attributeList) { + attrSB.append(attribute.toText()); + attrSB.append(" "); + } + attrSB.deleteCharAt(attrSB.length() - 1); + sb.append(TextRenderer.surroundString(attrSB.toString())); + } + + if (actions != null && !actions.getSet().isEmpty()) { + sb.append("actions"); + StringBuilder actionsSB = new StringBuilder(); + List actionList = new ArrayList<>(actions.getSet()); + Collections.sort(actionList); + for (Action action : actionList) { + actionsSB.append(action.getIdentifier()); + actionsSB.append(" "); + } + actionsSB.deleteCharAt(actionsSB.length() - 1); + sb.append(TextRenderer.surroundString(actionsSB.toString())); + } + } + + if (sb.charAt(sb.length() - 1) == ';') { + sb.deleteCharAt(sb.length() - 1); + } + + return sb.toString(); + } + + /** + * Comapres two cetegories lexicographically based on their identifier. + * + * @see Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(Category c) { + return getIdentifier().compareTo(c.getIdentifier()); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Entity.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Entity.java new file mode 100644 index 0000000..5a283c1 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Entity.java @@ -0,0 +1,540 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.collection.AttributeMapCover; +import cz.cesnet.cloud.occi.type.Identifiable; +import cz.cesnet.cloud.occi.collection.SetCover; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.exception.RenderingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class representing an OCCI Entity. + * + * @author Michal Kimle + */ +public abstract class Entity implements Identifiable, Comparable { + + public static final String ID_ATTRIBUTE_NAME = "occi.core.id"; + public static final String TITLE_ATTRIBUTE_NAME = "occi.core.title"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_CORE_DEFAULT; + public static final String TERM_DEFAULT = "entity"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + private static final Logger LOGGER = LoggerFactory.getLogger(Entity.class); + private Kind kind; + private Model model; + private final SetCover mixins = new SetCover<>(); + private final AttributeMapCover attributes = new AttributeMapCover(); + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind entity's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model entity's model + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public Entity(String id, Kind kind, String title, Model model) throws InvalidAttributeValueException { + LOGGER.debug("Creating Entity: class={}, id={}, kind={}, title={}, model={}", getClass().getName(), id, kind, title, model); + + if (id == null) { + throw new NullPointerException("Entity id cannot be null."); + } + if (kind == null) { + throw new NullPointerException("Entity kind cannot be null."); + } + + privateAddAttribute(ID_ATTRIBUTE_NAME, id); + if (title != null && !title.isEmpty()) { + privateAddAttribute(TITLE_ATTRIBUTE_NAME, title); + } + this.kind = kind; + this.model = model; + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind entity's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public Entity(String id, Kind kind) throws InvalidAttributeValueException { + this(id, kind, null, null); + } + + /** + * Returns entity's id. + * + * @return entity's id + */ + public String getId() { + return getValue(ID_ATTRIBUTE_NAME); + } + + /** + * Sets entity's id. + * + * @param id entity's id. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public void setId(String id) throws InvalidAttributeValueException { + if (id == null) { + throw new NullPointerException("Entity id cannot be null."); + } + + addAttribute(ID_ATTRIBUTE_NAME, id); + } + + /** + * Returns entity's kind. + * + * @return entity's kind + */ + public Kind getKind() { + return kind; + } + + /** + * Sets entity's kind. + * + * @param kind entity's kind. Cannot be null. + */ + public void setKind(Kind kind) { + if (kind == null) { + throw new NullPointerException("Entity kind cannot be null."); + } + + this.kind = kind; + } + + /** + * Returns entity's identifier. + * + * @return entity's identifier + */ + @Override + public String getIdentifier() { + return kind.getIdentifier() + "|" + getId(); + } + + /** + * Returns entity's title. + * + * @return entity's title + */ + public String getTitle() { + return getValue(TITLE_ATTRIBUTE_NAME); + } + + /** + * Sets entity's title. + * + * @param title entity's title + * @throws InvalidAttributeValueException in case of invalit tile value + */ + public void setTitle(String title) throws InvalidAttributeValueException { + addAttribute(TITLE_ATTRIBUTE_NAME, title); + } + + /** + * Returns entity's model. + * + * @return entity's model + */ + public Model getModel() { + return model; + } + + /** + * Sets entity's model. + * + * @param model entity's model + */ + public void setModel(Model model) { + this.model = model; + } + + private void privateAddAttribute(String attributeIdentifier, String value) throws InvalidAttributeValueException { + if (!isValidAttributeValue(attributeIdentifier, value)) { + Attribute attribute = getAttribute(attributeIdentifier); + throw new InvalidAttributeValueException("'" + value + "' is not a suitable value for " + attribute); + } + + Attribute attribute = getAttribute(attributeIdentifier); + if (attribute == null) { + attribute = new Attribute(attributeIdentifier); + } + attributes.add(attribute, value); + } + + /** + * Adds attribute and its value. If attribute has a content restriction, + * value is checked. + * + * @param attributeIdentifier + * @param value + * @throws InvalidAttributeValueException + */ + public void addAttribute(String attributeIdentifier, String value) throws InvalidAttributeValueException { + privateAddAttribute(attributeIdentifier, value); + } + + /** + * Adds attributes and their values. If attributes have a content + * restriction, values are checked. + * + * @param attributes + * @throws InvalidAttributeValueException + */ + public void addAttributes(Map attributes) throws InvalidAttributeValueException { + for (String name : attributes.keySet()) { + privateAddAttribute(name, attributes.get(name)); + } + } + + private boolean isValidAttributeValue(String attributeIdentifier, String value) { + Attribute attribute = getAttribute(attributeIdentifier); + + if (attribute == null) { + return true; + } + + if (attribute.getPattern() == null || attribute.getPattern().isEmpty()) { + return true; + } + + return value.matches(attribute.getPattern()); + } + + private Attribute getAttribute(String attributeIdentifier) { + Attribute attribute = getAttributeFromKindsIfExists(kind, attributeIdentifier); + if (attribute == null) { + attribute = getAttributeFromMixinsIfExists(getMixins(), attributeIdentifier); + } + + return attribute; + } + + private Attribute getAttributeFromKindsIfExists(Kind kind, String attributeIdentifier) { + if (kind == null) { + return null; + } + + if (kind.containsAttribute(attributeIdentifier)) { + return kind.getAttribute(attributeIdentifier); + } + + Attribute attribute = null; + for (Kind k : kind.getRelations()) { + if (attribute != null) { + return attribute; + } + + attribute = getAttributeFromKindsIfExists(k, attributeIdentifier); + } + + return attribute; + } + + private Attribute getAttributeFromMixinsIfExists(Set mixins, String attributeIdentifier) { + for (Mixin m : mixins) { + if (m.containsAttribute(attributeIdentifier)) { + return m.getAttribute(attributeIdentifier); + } + Attribute attribute = getAttributeFromMixinsIfExists(m.getRelations(), attributeIdentifier); + if (attribute != null) { + return attribute; + } + } + + return null; + } + + /** + * Removes attribute from entity. + * + * @param attributeIdentifier identifier of the attribute to be removed + */ + public void removeAttribute(String attributeIdentifier) { + attributes.remove(attributeIdentifier); + } + + /** + * Checks whether entity has given attribute. + * + * @param attribute attribute to be looked up + * @return true if entity has given attribute, false otherwise + */ + public boolean containsAttribute(Attribute attribute) { + return attributes.containsAttribute(attribute); + } + + /** + * Checks whether entity has given attribute. + * + * @param attributeName name of the attribute to be looked up + * @return true if entity has given attribute, false otherwise + */ + public boolean containsAttribute(String attributeName) { + return attributes.containsAttribute(attributeName); + } + + /** + * Returns value of given attribute. + * + * @param attribute attribute which value will be returned + * @return value of given attribute + */ + public String getValue(Attribute attribute) { + return attributes.getValue(attribute); + } + + /** + * Returns value of given attribute. + * + * @param attributeName name of the attribute which value will be returned + * @return value of given attribute + */ + public String getValue(String attributeName) { + return attributes.getValue(attributeName); + } + + /** + * Returns all entity's attributes and their values in form of map. + * + * @return all entity's attributes and their values in form of map + */ + public Map getAttributes() { + return attributes.getAttributes(); + } + + /** + * Removes all entity's attributes. + */ + public void clearAttributes() { + attributes.clear(); + } + + /** + * Returns text representation of entity's attributes in one line. + * + * @return text representation of entity's attributes in one line + */ + protected String attributesToOneLineText() { + return attributes.toOneLineText(); + } + + /** + * Returns a text representation of entity's attributes with prefix. + * + * @return text representation of entity's attributes with prefix + */ + protected String attributesToPrefixText() { + return attributes.toPrefixText(); + } + + /** + * Returns an occi text representation of entity's attributes in form of + * headers. + * + * @return occi text representation of entity's attributes in form of + * headers + */ + protected Headers attributesToHeaders() { + return attributes.toHeaders(); + } + + /** + * Checks whether the entity has given mixin. + * + * @param mixin mixin to be looked up + * @return true if entity has given mixin, false otherwise + */ + public boolean containsMixin(Mixin mixin) { + return mixins.contains(mixin); + } + + /** + * Checks whether the entity has given mixin. + * + * @param mixinIdentifier identifier of mixin to be looked up + * @return true if entity has given mixin, false otherwise + */ + public boolean containsMixin(String mixinIdentifier) { + return mixins.contains(mixinIdentifier); + } + + /** + * Adds mixin to the entity. + * + * @param mixin mixin to be added + * @return true if the addition was successful, false otherwise + */ + public boolean addMixin(Mixin mixin) { + return mixins.add(mixin); + } + + /** + * Adds all the mixins from given collection to the entity. + * + * @param mixins collection of mixins + * @return true if the addition was successful, false otherwise + */ + public boolean addMixins(Collection mixins) { + return this.mixins.addAll(mixins); + } + + /** + * Returns mixin form entity. + * + * @param mixinIdentifier identifier of requested mixin + * @return mixin form entity + */ + public Mixin getMixin(String mixinIdentifier) { + return mixins.get(mixinIdentifier); + } + + /** + * Removes mixin from entity. + * + * @param mixin mixin to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeMixin(Mixin mixin) { + return mixins.remove(mixin); + } + + /** + * Removes all mixins from entity. + */ + public void clearMixins() { + mixins.clear(); + } + + /** + * Returns all mixins from entity in form of a set. + * + * @return all mixins from entity in form of a set + */ + public Set getMixins() { + return mixins.getSet(); + } + + /** + * @see Object#hashCode() + * @return entity's hash code + */ + @Override + public int hashCode() { + int hash = 7; + hash = 89 * hash + Objects.hashCode(getId()); + hash = 89 * hash + Objects.hashCode(this.kind); + return hash; + } + + /** + * @see Object#equals(java.lang.Object) + * @param obj object to compare entity with + * @return true if two entity are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Entity)) { + return false; + } + final Entity other = (Entity) obj; + if (!Objects.equals(getId(), other.getId())) { + return false; + } + if (!Objects.equals(this.kind, other.kind)) { + return false; + } + return true; + } + + /** + * Resturns string representation of the entity + * + * @see Object#toString() + * @return string representation of the entity + */ + @Override + public String toString() { + return "Entity{" + "class=" + getClass().getName() + ", id=" + getId() + ", kind=" + kind + ", title=" + getTitle() + ", mixins=" + mixins + ", attributes=" + attributes + '}'; + } + + /** + * Renders entity to its plain text form as described in OCCI standard. + * + * @return plain text form of entity + * @throws RenderingException + */ + public abstract String toText() throws RenderingException; + + /** + * Renders entity to its occi text form as described in OCCI standard in + * form of headers. + * + * @return occi text form of entity + * @throws RenderingException + */ + public abstract Headers toHeaders() throws RenderingException; + + /** + * Renders entity to its JSON form as described in OCCI standard. + * + * @return JSON form of entity + */ + public abstract String toJSON(); + + /** + * Comapres two entities lexicographically based on their identifier. + * + * @see Comparable#compareTo(java.lang.Object) + */ + @Override + public int compareTo(Entity e) { + return getIdentifier().compareTo(e.getIdentifier()); + } + + /** + * Returns entity's default kind identifier (scheme+term). For Entity class + * this equals to 'http://schemas.ogf.org/occi/core#entity'. + * + * @return entity's default kind identifier + */ + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns entity's default attributes. For Entity class those are + * attributes occi.core.id and occi.core.title. + * + * @return list of entity's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.add(new Attribute(ID_ATTRIBUTE_NAME, true, true)); + list.add(new Attribute(TITLE_ATTRIBUTE_NAME, false, false)); + + return list; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Kind.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Kind.java new file mode 100644 index 0000000..22f1500 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Kind.java @@ -0,0 +1,157 @@ +package cz.cesnet.cloud.occi.core; + +import cz.cesnet.cloud.occi.collection.SetCover; +import java.net.URI; +import java.util.Collection; +import java.util.Set; + +/** + * Class representing an OCCI Kind. + * + * @author Michal Kimle + */ +public class Kind extends Category { + + private final SetCover related = new SetCover<>(); + private String entityType; + private Kind parentKind = null; + + /** + * Constructor. Creates new kind with scheme, term, title, location and + * attributes. + * + * @param scheme kind's scheme. Cannot be null. + * @param term kind's term. Cannot be null nor empty. + * @param title kind's title + * @param location kind's location + * @param attributes kind's attributes + */ + public Kind(URI scheme, String term, String title, URI location, Collection attributes) { + super(scheme, term, title, location, attributes); + } + + /** + * Constructor. Creates new kind with scheme and term. + * + * @param scheme kind's scheme. Cannot be null. + * @param term kind's term. Cannot be null nor empty. + */ + public Kind(URI scheme, String term) { + this(scheme, term, null, null, null); + } + + /** + * Returns kind's entity type. + * + * @return kind's entity type + */ + public String getEntityType() { + return entityType; + } + + /** + * Sets kind's entity type. + * + * @param entityType kind's entity type + */ + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + /** + * Returns kind's parent kind. For example kind + * 'http://schemas.ogf.org/occi/infrastructure#compute' has parent kind + * 'http://schemas.ogf.org/occi/core#resource'. + * + * @return kind's parent kind + */ + public Kind getParentKind() { + return parentKind; + } + + /** + * Sets kind's parent kind. + * + * @param parentKind kind's parent kind + */ + public void setParentKind(Kind parentKind) { + this.parentKind = parentKind; + } + + /** + * Checks whether this kind is in relation with given kind. + * + * @param kind kind to chcek relation with + * @return true if there is relation between kinds, false otherwise + */ + public boolean relatesTo(Kind kind) { + return related.contains(kind); + } + + /** + * Checks whether this kind is in relation with given kind. + * + * @param kindIdentifier identifier of kind to chcek relation with + * @return true if there is relation between kinds, false otherwise + */ + public boolean relatesTo(String kindIdentifier) { + return related.contains(kindIdentifier); + } + + /** + * Creates a relation with given kind. + * + * @param kind kind to create a relation with + * @return true if the relation was created successfully, false otherwise + */ + public boolean addRelation(Kind kind) { + return related.add(kind); + } + + /** + * Creates a relation with given kind. + * + * @param kindIdentifier identifier of kind to create a relation with + * @return true if the relation was created successfully, false otherwise + */ + public Kind getRelatedKind(String kindIdentifier) { + return related.get(kindIdentifier); + } + + /** + * Removes relation with given kind. + * + * @param kind kind with which relation will be removed + * @return true if the relation was removed successfully, false otherwise + */ + public boolean removeRelation(Kind kind) { + return related.remove(kind); + } + + /** + * Remove all relations. + */ + public void clearRelations() { + related.clear(); + } + + /** + * Returns all related kinds in form of set. + * + * @return all related kinds in form of set + */ + public Set getRelations() { + return related.getSet(); + } + + /** + * Resturns string representation of kind + * + * @see Object#toString() + * @return string representation of kind + */ + @Override + public String toString() { + return "Kind{" + "term=" + getTerm() + ", scheme=" + getScheme() + ", title=" + getTitle() + ", location=" + getLocation() + ", attributes=" + getAttributes() + ", related=" + related + '}'; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Link.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Link.java new file mode 100644 index 0000000..c81857b --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Link.java @@ -0,0 +1,288 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.exception.RenderingException; +import cz.cesnet.cloud.occi.renderer.TextRenderer; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Class representing an OCCI Link. + * + * @author Michal Kimle + */ +public class Link extends Entity { + + public static final String SOURCE_ATTRIBUTE_NAME = "occi.core.source"; + public static final String TARGET_ATTRIBUTE_NAME = "occi.core.target"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_CORE_DEFAULT; + public static final String TERM_DEFAULT = "link"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + private String relation; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind link's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model link's model + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public Link(String id, Kind kind, String title, Model model) throws InvalidAttributeValueException { + super(id, kind, title, model); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind link's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public Link(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns link's source (value of occi.core.source attribute). + * + * @return link's source + */ + public String getSource() { + return getValue(SOURCE_ATTRIBUTE_NAME); + } + + /** + * Sets link's source. + * + * @param source link's source. Cannot be null. + * @throws InvalidAttributeValueException in case source value is invalid + */ + public void setSource(Resource source) throws InvalidAttributeValueException { + if (source == null) { + throw new NullPointerException("source cannot be null"); + } + addAttribute(SOURCE_ATTRIBUTE_NAME, source.getLocation()); + } + + /** + * Sets link's source. + * + * @param sourceLocation location of link's source + * @throws InvalidAttributeValueException in case source value is invalid + */ + public void setSource(String sourceLocation) throws InvalidAttributeValueException { + addAttribute(SOURCE_ATTRIBUTE_NAME, sourceLocation); + } + + /** + * Returns link's target (value of occi.core.terget attribute). + * + * @return link's target + */ + public String getTarget() { + return getValue(TARGET_ATTRIBUTE_NAME); + } + + /** + * Sets link's target. + * + * @param target link's target. Cannot be null. + * @throws InvalidAttributeValueException in case target value is invalid + */ + public void setTarget(Resource target) throws InvalidAttributeValueException { + if (target == null) { + throw new NullPointerException("target cannot be null"); + } + addAttribute(TARGET_ATTRIBUTE_NAME, target.getLocation()); + } + + /** + * Sets link's target. + * + * @param targetLocation location of link's target + * @throws InvalidAttributeValueException in case target value is invalid + */ + public void setTarget(String targetLocation) throws InvalidAttributeValueException { + addAttribute(TARGET_ATTRIBUTE_NAME, targetLocation); + } + + /** + * Returns link's relation. + * + * @return link's relation + */ + public String getRelation() { + return relation; + } + + /** + * Sets link's relation. + * + * @param relation + */ + public void setRelation(String relation) { + this.relation = relation; + } + + /** + * Returns link's default identifier 'http://schemas.ogf.org/occi/core#link' + * + * @return link's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Entity.getDefaultAttributes()); + list.add(new Attribute(SOURCE_ATTRIBUTE_NAME, true, false)); + list.add(new Attribute(TARGET_ATTRIBUTE_NAME, true, false)); + + return list; + } + + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Link", URI.create("/link/"), Link.getDefaultAttributes()); + return kind; + } + + /** + * Returns a plain text representation of link instance as described in OCCI + * standard. + * + * @return plain text representation of link instance + */ + @Override + public String toText() { + StringBuilder sb = new StringBuilder(); + + sb.append(getKind().toText(false)); + + List mixinList = new ArrayList<>(getMixins()); + Collections.sort(mixinList); + for (Mixin m : mixinList) { + sb.append("\n"); + sb.append(m.toText(false)); + } + + String attributesString = attributesToPrefixText(); + if (!attributesString.isEmpty()) { + sb.append("\n"); + sb.append(attributesString); + } + + return sb.toString(); + } + + /** + * Returns an occi text representation of link instance as described in OCCI + * standard in form of headers. + * + * @return plain text representation of link instance + */ + @Override + public Headers toHeaders() { + Headers headers = new Headers(); + + headers.putAll(getKind().toHeaders(false)); + + List mixinList = new ArrayList<>(getMixins()); + Collections.sort(mixinList); + for (Mixin m : mixinList) { + Headers mixinHeaders = m.toHeaders(false); + for (String name : mixinHeaders.keySet()) { + for (String value : mixinHeaders.get(name)) { + headers.add(name, value); + } + } + } + + Headers attributeHeaders = attributesToHeaders(); + if (!attributeHeaders.isEmpty()) { + headers.putAll(attributeHeaders); + } + + return headers; + } + + /** + * Returns an inline plain text representation of link instance as described + * in OCCI standard. + * + * @return inline plain text representation of link instance + * @throws RenderingException + */ + public String toInlineText() throws RenderingException { + StringBuilder sb = new StringBuilder("Link: "); + sb.append(inlineTextBody()); + + return sb.toString(); + } + + /** + * Returns an inline occi text representation of link instance as described + * in OCCI standard in form of headers. + * + * @return inline occi text representation of link instance in form of + * headers + * @throws RenderingException + */ + public Headers toInlineHeaders() throws RenderingException { + Headers headers = new Headers(); + headers.add("Link", inlineTextBody()); + + return headers; + } + + private String inlineTextBody() throws RenderingException { + StringBuilder sb = new StringBuilder(""); + if (getTarget() == null || getTarget().isEmpty()) { + throw new RenderingException("Link " + this + " is missing a target attribute."); + } + sb.append(TextRenderer.surroundString(getTarget(), "<", ">;")); + + if (relation == null || relation.isEmpty()) { + throw new RenderingException("Link " + this + " is missing a relation."); + } + sb.append("rel"); + sb.append(TextRenderer.surroundString(relation)); + + if (getKind().getLocation() != null && getId() != null && !getId().isEmpty()) { + sb.append("self"); + sb.append(TextRenderer.surroundString(getKind().getLocation().toString() + getId())); + } + + sb.append("category"); + sb.append("=\""); + sb.append(getKind().getIdentifier()); + for (Mixin mixin : getMixins()) { + sb.append(" "); + sb.append(mixin.getIdentifier()); + } + sb.append("\";"); + + sb.append(attributesToOneLineText()); + + return sb.toString(); + } + + /** + * Returns a JSON representation of link instance as described in OCCI + * standard. NOT IMPLEMENTED YET! + * + * @return JSON representation of link instance + */ + @Override + public String toJSON() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Mixin.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Mixin.java new file mode 100644 index 0000000..f901068 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Mixin.java @@ -0,0 +1,106 @@ +package cz.cesnet.cloud.occi.core; + +import cz.cesnet.cloud.occi.collection.SetCover; +import java.net.URI; +import java.util.Collection; +import java.util.Set; + +/** + * Class representing an OCCI Mixin. + * + * @author Michal Kimle + */ +public class Mixin extends Category { + + private final SetCover related = new SetCover<>(); + + /** + * Constructor. Creates new mixin with scheme, term, title, location and + * attributes. + * + * @param scheme mixin's scheme. Cannot be null. + * @param term mixin's term. Cannot be null nor empty. + * @param title mixin's title + * @param location mixin's location + * @param attributes mixin's attributes + */ + public Mixin(URI scheme, String term, String title, URI location, Collection attributes) { + super(scheme, term, title, location, attributes); + } + + /** + * Constructor. Creates new mixin with scheme and term. + * + * @param scheme mixin's scheme. Cannot be null. + * @param term mixin's term. Cannot be null nor empty. + */ + public Mixin(URI scheme, String term) { + this(scheme, term, null, null, null); + } + + /** + * Checks whether this mixin is in relation with given mixin. + * + * @param mixin mixin to chcek relation with + * @return true if there is relation between mixins, false otherwise + */ + public boolean relatesTo(Mixin mixin) { + return related.contains(mixin); + } + + /** + * Checks whether this mixin is in relation with given mixin. + * + * @param mixinIdentifier identifier of mixin to chcek relation with + * @return true if there is relation between mixins, false otherwise + */ + public boolean relatesTo(String mixinIdentifier) { + return related.contains(mixinIdentifier); + } + + /** + * Creates a relation with given mixin. + * + * @param mixin mixin to create a relation with + * @return true if the relation was created successfully, false otherwise + */ + public boolean addRelation(Mixin mixin) { + return related.add(mixin); + } + + /** + * Creates a relation with given mixin. + * + * @param mixinIdentifier identifier of mixin to create a relation with + * @return true if the relation was created successfully, false otherwise + */ + public Mixin getRelatedMixin(String mixinIdentifier) { + return related.get(mixinIdentifier); + } + + /** + * Removes relation with given mixin. + * + * @param mixin mixin with which relation will be removed + * @return true if the relation was removed successfully, false otherwise + */ + public boolean removeRelation(Mixin mixin) { + return related.remove(mixin); + } + + /** + * Remove all relations. + */ + public void clearRelations() { + related.clear(); + } + + /** + * Returns all related mixins in form of set. + * + * @return all related mixins in form of set + */ + public Set getRelations() { + return related.getSet(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Resource.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Resource.java new file mode 100644 index 0000000..54e096c --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/core/Resource.java @@ -0,0 +1,448 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.collection.SetCover; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.exception.RenderingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.slf4j.LoggerFactory; + +/** + * Class representing an OCCI Resource. + * + * @author Michal Kimle + */ +public class Resource extends Entity { + + public static final String SUMMARY_ATTRIBUTE_NAME = "occi.core.summary"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_CORE_DEFAULT; + public static final String TERM_DEFAULT = "resource"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Resource.class); + private final SetCover links = new SetCover<>(); + private final SetCover actions = new SetCover<>(); + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind resource's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model resource's model + * @param summary resource's summary + * @throws InvalidAttributeValueException in case of invalid id, title or + * summary value + */ + public Resource(String id, Kind kind, String title, Model model, String summary) throws InvalidAttributeValueException { + super(id, kind, title, model); + + addAttribute(SUMMARY_ATTRIBUTE_NAME, summary); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind resource's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public Resource(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns resource's summary. + * + * @return resource's summary + */ + public String getSummary() { + return getValue(SUMMARY_ATTRIBUTE_NAME); + } + + /** + * Sets resource's summary. + * + * @param summary resource's summary + * @throws InvalidAttributeValueException in case of invalid summary value + */ + public void setSummary(String summary) throws InvalidAttributeValueException { + addAttribute(SUMMARY_ATTRIBUTE_NAME, summary); + } + + /** + * Checks whether resource contains given link. + * + * @param link link to be looked up + * @return true is resource contains given link, false otherwise + */ + public boolean containsLink(Link link) { + return links.contains(link); + } + + /** + * Checks whether resource contains link which kind has given term. + * + * @param term term of link's kind + * @return true is resource contains given link, false otherwise + */ + public boolean containsLink(String term) { + for (Link link : links.getSet()) { + if (link.getKind().getTerm().equals(term)) { + return true; + } + } + + return false; + } + + /** + * Checks whether resource contains link which kind has given identifier. + * + * @param identifier identifier of link's kind + * @return true is resource contains given link, false otherwise + */ + public boolean containsLink(URI identifier) { + String identifierString = identifier.toString(); + for (Link link : links.getSet()) { + if (link.getKind().getIdentifier().equals(identifierString)) { + return true; + } + } + + return false; + } + + /** + * Adds link to the resource and automatically sets link's source to + * resource. + * + * @param link to be added + * @return true if addition was successful, false otherwise + */ + public boolean addLink(Link link) { + if (link.getSource() == null) { + try { + link.setSource(this); + } catch (InvalidAttributeValueException ex) { + LOGGER.error("This should not be happening!"); + } + } + return links.add(link); + } + + /** + * Adds links to the resource and automatically sets all links' sources to + * resource. + * + * @param links collections of links to be added + * @return true if addition was successful, false otherwise + */ + public boolean addLinks(Collection links) { + for (Link link : links) { + if (link.getSource() == null) { + try { + link.setSource(this); + } catch (InvalidAttributeValueException ex) { + LOGGER.error("This should not be happening!"); + } + } + } + return this.links.addAll(links); + } + + /** + * Returns resources' links which kind has given term. + * + * @param term term of link's kind + * @return resource's link + */ + public Set getLinks(String term) { + Set set = new HashSet<>(); + for (Link link : links.getSet()) { + if (link.getKind().getTerm().equals(term)) { + set.add(link); + } + } + + return set; + } + + /** + * Returns resources' links which kind has given identifier. + * + * @param identifier identifier of link's kind + * @return resource's link + */ + public Set getLinks(URI identifier) { + String identifierString = identifier.toString(); + Set set = new HashSet<>(); + for (Link link : links.getSet()) { + if (link.getKind().getIdentifier().equals(identifierString)) { + set.add(link); + } + } + + return set; + } + + /** + * Removes link from resource. + * + * @param link link to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeLink(Link link) { + return links.remove(link); + } + + /** + * Removes all links from resource. + */ + public void clearLinks() { + links.clear(); + } + + /** + * Returns all resource's links in form of set. + * + * @return all resource's links in form of set + */ + public Set getLinks() { + return links.getSet(); + } + + /** + * Checks whether resource contains given action. + * + * @param action action to be looked up + * @return true is resource contains given action, false otherwise + */ + public boolean containsAction(Action action) { + return actions.contains(action); + } + + /** + * Checks whether resource contains given action. + * + * @param actionIdentifier identifier of action to be looked up + * @return true is resource contains given action, false otherwise + */ + public boolean containsAction(String actionIdentifier) { + return actions.contains(actionIdentifier); + } + + /** + * Adds action to the resource. + * + * @param action to be added + * @return true if addition was successful, false otherwise + */ + public boolean addAction(Action action) { + return actions.add(action); + } + + /** + * Adds actions to the resource. + * + * @param actions collections of actions to be added + * @return true if addition was successful, false otherwise + */ + public boolean addActions(Collection actions) { + return this.actions.addAll(actions); + } + + /** + * Returns resource's action. + * + * @param actionIdentifier identifier of requested action + * @return resource's action + */ + public Action getAction(String actionIdentifier) { + return actions.get(actionIdentifier); + } + + /** + * Removes action from resource. + * + * @param action action to be removed + * @return true if the removal was successful, false otherwise + */ + public boolean removeAction(Action action) { + return actions.remove(action); + } + + /** + * Removes all actions from resource. + */ + public void clearActions() { + actions.clear(); + } + + /** + * Returns all resource's actions in form of set. + * + * @return all resource's actions in form of set + */ + public Set getActions() { + return actions.getSet(); + } + + /** + * Returns resource's location. + * + * @return resource's location + */ + public String getLocation() { + return getKind().getLocation().toString() + getId(); + } + + /** + * Returns resource's default identifier + * 'http://schemas.ogf.org/occi/core#resource' + * + * @return resource's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Entity.getDefaultAttributes()); + list.add(new Attribute(SUMMARY_ATTRIBUTE_NAME, false, false)); + + return list; + } + + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Resource", URI.create("/resource/"), Resource.getDefaultAttributes()); + return kind; + } + + /** + * Resturns string representation of resource + * + * @see Object#toString() + * @return string representation of resource + */ + @Override + public String toString() { + return "Resource{" + "class=" + getClass().getName() + ", id=" + getId() + ", kind=" + getKind() + ", title=" + getTitle() + ", mixins=" + getMixins() + ", attributes=" + getAttributes() + ", links" + links + '}'; + } + + /** + * Returns a plain text representation of resource instance as described in + * OCCI standard. + * + * @return plain text representation of resource instance + * @throws RenderingException + */ + @Override + public String toText() throws RenderingException { + StringBuilder sb = new StringBuilder(); + + sb.append(getKind().toText(false)); + + List mixinList = new ArrayList<>(getMixins()); + Collections.sort(mixinList); + for (Mixin m : mixinList) { + sb.append("\n"); + sb.append(m.toText(false)); + } + + String attributesString = attributesToPrefixText(); + if (!attributesString.isEmpty()) { + sb.append("\n"); + sb.append(attributesString); + } + + List linkList = new ArrayList<>(getLinks()); + Collections.sort(linkList); + for (Link l : linkList) { + sb.append("\n"); + sb.append(l.toInlineText()); + } + + List actionList = new ArrayList<>(getActions()); + Collections.sort(actionList); + for (Action a : actionList) { + sb.append("\n"); + sb.append(a.toText(getKind().getLocation().toString() + getId())); + } + + return sb.toString(); + } + + /** + * Returns a occi text representation of resource instance as described in + * OCCI standard in form of headers. + * + * @return plain text representation of resource instance + * @throws RenderingException + */ + @Override + public Headers toHeaders() throws RenderingException { + Headers headers = new Headers(); + + headers.putAll(getKind().toHeaders(false)); + + List mixinList = new ArrayList<>(getMixins()); + Collections.sort(mixinList); + for (Mixin m : mixinList) { + Headers mixinHeaders = m.toHeaders(false); + for (String name : mixinHeaders.keySet()) { + for (String value : mixinHeaders.get(name)) { + headers.add(name, value); + } + } + } + + Headers attributeHeaders = attributesToHeaders(); + if (!attributeHeaders.isEmpty()) { + headers.putAll(attributeHeaders); + } + + List linkList = new ArrayList<>(getLinks()); + Collections.sort(linkList); + for (Link l : linkList) { + Headers linkHeaders = l.toInlineHeaders(); + for (String name : linkHeaders.keySet()) { + for (String value : linkHeaders.get(name)) { + headers.add(name, value); + } + } + } + + List actionList = new ArrayList<>(getActions()); + Collections.sort(actionList); + for (Action a : actionList) { + Headers actionHeaders = a.toHeaders(getKind().getLocation().toString() + getId()); + for (String name : actionHeaders.keySet()) { + for (String value : actionHeaders.get(name)) { + headers.add(name, value); + } + } + } + + return headers; + } + + /** + * Returns a JSON representation of resource instance as described in OCCI + * standard. NOT IMPLEMENTED YET! + * + * @return JSON representation of resource instance + */ + @Override + public String toJSON() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/AmbiguousIdentifierException.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/AmbiguousIdentifierException.java new file mode 100644 index 0000000..fc2e206 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/AmbiguousIdentifierException.java @@ -0,0 +1,16 @@ +package cz.cesnet.cloud.occi.exception; + +/** + * + * @author Michal Kimle + */ +public class AmbiguousIdentifierException extends Exception { + + public AmbiguousIdentifierException(String message) { + super(message); + } + + public AmbiguousIdentifierException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeException.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeException.java new file mode 100644 index 0000000..80b0401 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeException.java @@ -0,0 +1,16 @@ +package cz.cesnet.cloud.occi.exception; + +/** + * + * @author Michal Kimle + */ +public class InvalidAttributeException extends Exception { + + public InvalidAttributeException(String message) { + super(message); + } + + public InvalidAttributeException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeValueException.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeValueException.java new file mode 100644 index 0000000..a0c3bcc --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/InvalidAttributeValueException.java @@ -0,0 +1,16 @@ +package cz.cesnet.cloud.occi.exception; + +/** + * + * @author Michal Kimle + */ +public class InvalidAttributeValueException extends Exception { + + public InvalidAttributeValueException(String message) { + super(message); + } + + public InvalidAttributeValueException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/ParsingException.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/ParsingException.java new file mode 100644 index 0000000..84a4b4a --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/ParsingException.java @@ -0,0 +1,16 @@ +package cz.cesnet.cloud.occi.exception; + +/** + * + * @author Michal Kimle + */ +public class ParsingException extends Exception { + + public ParsingException(String message) { + super(message); + } + + public ParsingException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/RenderingException.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/RenderingException.java new file mode 100644 index 0000000..0f4f94e --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/exception/RenderingException.java @@ -0,0 +1,16 @@ +package cz.cesnet.cloud.occi.exception; + +/** + * + * @author Michal Kimle + */ +public class RenderingException extends Exception { + + public RenderingException(String message) { + super(message); + } + + public RenderingException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Compute.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Compute.java new file mode 100644 index 0000000..b3e48d0 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Compute.java @@ -0,0 +1,272 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.ComputeState; +import cz.cesnet.cloud.occi.infrastructure.enumeration.Architecture; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI Compute + * + * @author Michal Kimle + */ +public class Compute extends Resource { + + public static final String ARCHITECTURE_ATTRIBUTE_NAME = "occi.compute.architecture"; + public static final String CORES_ATTRIBUTE_NAME = "occi.compute.cores"; + public static final String HOSTNAME_ATTRIBUTE_NAME = "occi.compute.hostname"; + public static final String SPEED_ATTRIBUTE_NAME = "occi.compute.speed"; + public static final String MEMORY_ATTRIBUTE_NAME = "occi.compute.memory"; + public static final String STATE_ATTRIBUTE_NAME = "occi.compute.state"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_INFRASTRUCTURE_DEFAULT; + public static final String TERM_DEFAULT = "compute"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind compute's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model compute's model + * @param summary compute's summary + * @throws InvalidAttributeValueException in case of invalid id, title or + * summary value + */ + public Compute(String id, Kind kind, String title, Model model, String summary) throws InvalidAttributeValueException { + super(id, kind, title, model, summary); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind compute's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public Compute(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns compute's state (attribute occi.compute.state). + * + * @return compute's state + */ + public String getState() { + return getValue(STATE_ATTRIBUTE_NAME); + } + + /** + * Sets compute's state. + * + * @param state compute's state. Cannot be null. + * @throws InvalidAttributeValueException in case state's value is invalid + */ + public void setState(ComputeState state) throws InvalidAttributeValueException { + if (state == null) { + throw new NullPointerException("state cannot be null"); + } + addAttribute(STATE_ATTRIBUTE_NAME, state.toString()); + } + + /** + * Sets compute's state. + * + * @param stateName compute's state. Cannot be null. + * @throws InvalidAttributeValueException in case state's value is invalid + */ + public void setState(String stateName) throws InvalidAttributeValueException { + addAttribute(STATE_ATTRIBUTE_NAME, stateName); + } + + /** + * Returns compute's memory (attribute occi.compute.memory). + * + * @return compute's memory + */ + public String getMemory() { + return getValue(MEMORY_ATTRIBUTE_NAME); + } + + /** + * Sets compute's memory. + * + * @param memory compute's memory + * @throws InvalidAttributeValueException in case value of memory is invalid + */ + public void setMemory(float memory) throws InvalidAttributeValueException { + addAttribute(MEMORY_ATTRIBUTE_NAME, String.valueOf(memory)); + } + + /** + * Sets compute's memory. + * + * @param memory compute's memory + * @throws InvalidAttributeValueException in case value of memory is invalid + */ + public void setMemory(String memory) throws InvalidAttributeValueException { + addAttribute(MEMORY_ATTRIBUTE_NAME, memory); + } + + /** + * Returns compute's speed (attribute occi.compute.speed). + * + * @return compute's speed + */ + public String getSpeed() { + return getValue(SPEED_ATTRIBUTE_NAME); + } + + /** + * Sets compute's speed. + * + * @param speed compute's speed + * @throws InvalidAttributeValueException in case value of speed is invalid + */ + public void setSpeed(float speed) throws InvalidAttributeValueException { + addAttribute(SPEED_ATTRIBUTE_NAME, String.valueOf(speed)); + } + + /** + * Sets compute's speed. + * + * @param speed compute's speed + * @throws InvalidAttributeValueException in case value of speed is invalid + */ + public void setSpeed(String speed) throws InvalidAttributeValueException { + addAttribute(SPEED_ATTRIBUTE_NAME, speed); + } + + /** + * Returns compute's hostname (attribute occi.compute.hostname). + * + * @return compute's hostname + */ + public String getHostname() { + return getValue(HOSTNAME_ATTRIBUTE_NAME); + } + + /** + * Sets compute's hostname. + * + * @param hostname compute's hostname + * @throws InvalidAttributeValueException in case value of hostname is + * invalid + */ + public void setHostname(String hostname) throws InvalidAttributeValueException { + addAttribute(HOSTNAME_ATTRIBUTE_NAME, hostname); + } + + /** + * Returns number of compute's cores (attribute occi.compute.cores). + * + * @return number of compute's cores + */ + public String getCores() { + return getValue(CORES_ATTRIBUTE_NAME); + } + + /** + * Sets number of compute's cores. + * + * @param cores number of compute's cores + * @throws InvalidAttributeValueException in case value of cores is invalid + */ + public void setCores(int cores) throws InvalidAttributeValueException { + addAttribute(CORES_ATTRIBUTE_NAME, String.valueOf(cores)); + } + + /** + * Sets number of compute's cores. + * + * @param cores number of compute's cores + * @throws InvalidAttributeValueException in case value of cores is invalid + */ + public void setCores(String cores) throws InvalidAttributeValueException { + addAttribute(CORES_ATTRIBUTE_NAME, cores); + } + + /** + * Returns compute's architecture (attribute occi.compute.architecture). + * + * @return compute's architecture + */ + public String getArchitecture() { + return getValue(ARCHITECTURE_ATTRIBUTE_NAME); + } + + /** + * Sets compute's architecture + * + * @param architecture compute's architecture. Cannot be null. + * @throws InvalidAttributeValueException in case value of architecture is + * invalid + */ + public void setArchitecture(Architecture architecture) throws InvalidAttributeValueException { + if (architecture == null) { + throw new NullPointerException("architecture cannot be null"); + } + addAttribute(ARCHITECTURE_ATTRIBUTE_NAME, architecture.toString()); + } + + /** + * Sets compute's architecture + * + * @param architectureName compute's architecture + * @throws InvalidAttributeValueException in case value of architecture is + * invalid + */ + public void setArchitecture(String architectureName) throws InvalidAttributeValueException { + addAttribute(ARCHITECTURE_ATTRIBUTE_NAME, architectureName); + } + + /** + * Returns compute's default identifier + * 'http://schemas.ogf.org/occi/infrastructure#compute' + * + * @return compute's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns compute's default attributes. For Compute class those are + * attributes occi.compute.architecture, occi.compute.cores, + * occi.compute.hostname, occi.compute.speed, occi.compute.memory and + * occi.compute.state. + * + * @return list of compute's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Resource.getDefaultAttributes()); + list.add(new Attribute(ARCHITECTURE_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(CORES_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(HOSTNAME_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(SPEED_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(MEMORY_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(STATE_ATTRIBUTE_NAME, true, true)); + + return list; + } + + /** + * Returns compute's default kind instance. + * + * @return compute's default kind + */ + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Compute Resource", URI.create("/compute/"), Compute.getDefaultAttributes()); + return kind; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetwork.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetwork.java new file mode 100644 index 0000000..6baca6c --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetwork.java @@ -0,0 +1,163 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.Allocation; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI IPNetwork + * + * @author Michal Kimle + */ +public class IPNetwork extends Network { + + public static final String ADDRESS_ATTRIBUTE_NAME = "occi.network.address"; + public static final String GATEWAY_ATTRIBUTE_NAME = "occi.network.gateway"; + public static final String ALLOCATION_ATTRIBUTE_NAME = "occi.network.allocation"; + public static final URI SCHEME_DEFAULT = URI.create("http://schemas.ogf.org/occi/infrastructure/network#"); + public static final String TERM_DEFAULT = "ipnetwork"; + public static final String MIXIN_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind ipnetwork's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model ipnetwork's model + * @param summary ipnetwork's summary + * @throws InvalidAttributeValueException in case of invalid id, title or + * summary value + */ + public IPNetwork(String id, Kind kind, String title, Model model, String summary) throws InvalidAttributeValueException { + super(id, kind, title, model, summary); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind ipnetwork's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public IPNetwork(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns ipnetwork's address (attribute occi.network.address). + * + * @return ipnetwork's address + */ + public String getAddress() { + return getValue(ADDRESS_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork's address. + * + * @param address ipnetwork's address + * @throws InvalidAttributeValueException in case value for address is + * invalid + */ + public void setAddress(String address) throws InvalidAttributeValueException { + addAttribute(ADDRESS_ATTRIBUTE_NAME, address); + } + + /** + * Returns ipnetwork's gateway (attribute occi.network.gateway). + * + * @return ipnetwork's gateway + */ + public String getGateway() { + return getValue(GATEWAY_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork's gateway + * + * @param gateway ipnetwork's gateway + * @throws InvalidAttributeValueException in case value for gateway is + * invalid + */ + public void setGateway(String gateway) throws InvalidAttributeValueException { + addAttribute(GATEWAY_ATTRIBUTE_NAME, gateway); + } + + /** + * Returns ipnetwork's allocation (attribute occi.network.allocation). + * + * @return ipnetwork's allocation + */ + public String getAllocation() { + return getValue(ALLOCATION_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork's allocation. + * + * @param allocation ipnetwork's allocation. Cannot be null. + * @throws InvalidAttributeValueException in case value for allocation is + * invalid + */ + public void setAllocation(Allocation allocation) throws InvalidAttributeValueException { + if (allocation == null) { + throw new NullPointerException("allocation cannot be null"); + } + addAttribute(ALLOCATION_ATTRIBUTE_NAME, allocation.toString()); + } + + /** + * Sets ipnetwork's allocation. + * + * @param allocationName ipnetwork's allocation. Cannot be null. + * @throws InvalidAttributeValueException in case value for allocation is + * invalid + */ + public void setAllocation(String allocationName) throws InvalidAttributeValueException { + addAttribute(ALLOCATION_ATTRIBUTE_NAME, allocationName); + } + + /** + * Returns ipnetwork's default identifier + * 'http://schemas.ogf.org/occi/infrastructure/network#ipnetworking' + * + * @return ipnetwork's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return MIXIN_IDENTIFIER_DEFAULT; + } + + /** + * Returns ipnetwork's default attributes. For IPNetwork class those are + * attributes occi.network.address, occi.network.gateway and + * occi.network.allocation. + * + * @return list of ipnetwork's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.add(new Attribute(ADDRESS_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(GATEWAY_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(ALLOCATION_ATTRIBUTE_NAME, false, false)); + + return list; + } + + /** + * Returns ipnetwork's default mixin instance. + * + * @return ipnetwork's default mixin + */ + public static Mixin getDefaultMixin() { + Mixin mixin = new Mixin(SCHEME_DEFAULT, TERM_DEFAULT, "IP Network Mixin", URI.create("/mixins/ipnetwork/"), IPNetwork.getDefaultAttributes()); + return mixin; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetworkInterface.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetworkInterface.java new file mode 100644 index 0000000..7968178 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/IPNetworkInterface.java @@ -0,0 +1,165 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.Allocation; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI IPNetworkInterface + * + * @author Michal Kimle + */ +public class IPNetworkInterface extends NetworkInterface { + + public static final String ADDRESS_ATTRIBUTE_NAME = "occi.networkinterface.address"; + public static final String GATEWAY_ATTRIBUTE_NAME = "occi.networkinterface.gateway"; + public static final String ALLOCATION_ATTRIBUTE_NAME = "occi.networkinterface.allocation"; + public static final URI SCHEME_DEFAULT = URI.create("http://schemas.ogf.org/occi/infrastructure/networkinterface#"); + public static final String TERM_DEFAULT = "ipnetworkinterface"; + public static final String MIXIN_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind ipnetwork interface's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model network interface's model + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public IPNetworkInterface(String id, Kind kind, String title, Model model) throws InvalidAttributeValueException { + super(id, kind, title, model); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind ipnetwork interface's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public IPNetworkInterface(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns ipnetwork interface's address (attribute + * occi.networkinterface.address). + * + * @return ipnetwork interface's address + */ + public String getAddress() { + return getValue(ADDRESS_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork interface's address. + * + * @param address ipnetwork interface's address + * @throws InvalidAttributeValueException in case value for address is + * invalid + */ + public void setAddress(String address) throws InvalidAttributeValueException { + addAttribute(ADDRESS_ATTRIBUTE_NAME, address); + } + + /** + * Returns ipnetwork interface's gateway (attribute + * occi.networkinterface.gateway). + * + * @return ipnetwork interface's gateway + */ + public String getGateway() { + return getValue(GATEWAY_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork interface's gateway + * + * @param gateway ipnetwork interface's gateway + * @throws InvalidAttributeValueException in case value for gateway is + * invalid + */ + public void setGateway(String gateway) throws InvalidAttributeValueException { + addAttribute(GATEWAY_ATTRIBUTE_NAME, gateway); + } + + /** + * Returns ipnetwork interface's allocation (attribute + * occi.networkinterface.allocation). + * + * @return ipnetwork interface's allocation + */ + public String getAllocation() { + return getValue(ALLOCATION_ATTRIBUTE_NAME); + } + + /** + * Sets ipnetwork interface's allocation. + * + * @param allocation ipnetwork interface's allocation. Cannot be null. + * @throws InvalidAttributeValueException in case value for allocation is + * invalid + */ + public void setAllocation(Allocation allocation) throws InvalidAttributeValueException { + if (allocation == null) { + throw new NullPointerException("allocation cannot be null"); + } + addAttribute(ALLOCATION_ATTRIBUTE_NAME, allocation.toString()); + } + + /** + * Sets ipnetwork interface's allocation. + * + * @param allocationName ipnetwork interface's allocation. Cannot be null. + * @throws InvalidAttributeValueException in case value for allocation is + * invalid + */ + public void setAllocation(String allocationName) throws InvalidAttributeValueException { + addAttribute(ALLOCATION_ATTRIBUTE_NAME, allocationName); + } + + /** + * Returns ipnetworkinterface's default identifier + * 'http://schemas.ogf.org/occi/infrastructure/networkinterface#ipnetworkinterface' + * + * @return ipnetworkinterface's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return MIXIN_IDENTIFIER_DEFAULT; + } + + /** + * Returns ipnetworkinterface's default attributes. For IPNetworkInterface + * class those are attributes occi.networkinterface.address, + * occi.networkinterface.gateway and occi.networkinterface.allocation. + * + * @return list of ipnetworkinterface's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.add(new Attribute(ADDRESS_ATTRIBUTE_NAME, true, false)); + list.add(new Attribute(GATEWAY_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(ALLOCATION_ATTRIBUTE_NAME, true, false)); + + return list; + } + + /** + * Returns ipnetworkinterface's default mixin instance. + * + * @return ipnetworkinterface's default mixin + */ + public static Mixin getDefaultMixin() { + Mixin mixin = new Mixin(SCHEME_DEFAULT, TERM_DEFAULT, "IP Networkinterface Mixin", URI.create("/mixins/ipnetworkinterface/"), IPNetworkInterface.getDefaultAttributes()); + return mixin; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Network.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Network.java new file mode 100644 index 0000000..91d3b48 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Network.java @@ -0,0 +1,170 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.NetworkState; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI Network + * + * @author Michal Kimle + */ +public class Network extends Resource { + + public static final String VLAN_ATTRIBUTE_NAME = "occi.network.vlan"; + public static final String LABEL_ATTRIBUTE_NAME = "occi.network.label"; + public static final String STATE_ATTRIBUTE_NAME = "occi.network.state"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_INFRASTRUCTURE_DEFAULT; + public static final String TERM_DEFAULT = "network"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind network's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model network's model + * @param summary network's summary + * @throws InvalidAttributeValueException in case of invalid id, title or + * summary value + */ + public Network(String id, Kind kind, String title, Model model, String summary) throws InvalidAttributeValueException { + super(id, kind, title, model, summary); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind network's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public Network(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns network's vlan number (attribute occi.network.vlan). + * + * @return network's vlan number + */ + public String getVlan() { + return getValue(VLAN_ATTRIBUTE_NAME); + } + + /** + * Sets network's vlan number. + * + * @param vlan network's vlan number + * @throws InvalidAttributeValueException in case value for vlan is invalid + */ + public void setVlan(int vlan) throws InvalidAttributeValueException { + addAttribute(VLAN_ATTRIBUTE_NAME, String.valueOf(vlan)); + } + + /** + * Sets network's vlan number. + * + * @param vlan network's vlan number + * @throws InvalidAttributeValueException in case value for vlan is invalid + */ + public void setVlan(String vlan) throws InvalidAttributeValueException { + addAttribute(VLAN_ATTRIBUTE_NAME, vlan); + } + + /** + * Returns network's label (attribute occi.network.label). + * + * @return network's label + */ + public String getLabel() { + return getValue(LABEL_ATTRIBUTE_NAME); + } + + /** + * Sets network's label. + * + * @param label network's label + * @throws InvalidAttributeValueException in case value for label is invalid + */ + public void setLabel(String label) throws InvalidAttributeValueException { + addAttribute(LABEL_ATTRIBUTE_NAME, label); + } + + /** + * Returns network's state (attribute occi.network.state). + * + * @return network's state + */ + public String getState() { + return getValue(STATE_ATTRIBUTE_NAME); + } + + /** + * Sets network's state. + * + * @param state network's state. Cannot be null. + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(NetworkState state) throws InvalidAttributeValueException { + if (state == null) { + throw new NullPointerException("state cannot be null"); + } + addAttribute(STATE_ATTRIBUTE_NAME, state.toString()); + } + + /** + * Sets network's state. + * + * @param stateName network's state + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(String stateName) throws InvalidAttributeValueException { + addAttribute(STATE_ATTRIBUTE_NAME, stateName); + } + + /** + * Returns network's default identifier + * 'http://schemas.ogf.org/occi/infrastructure#network' + * + * @return network's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns network's default attributes. For Network class those are + * attributes occi.network.vlan, occi.network.label, occi.network.state. + * + * @return list of network's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Resource.getDefaultAttributes()); + list.add(new Attribute(VLAN_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(LABEL_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(STATE_ATTRIBUTE_NAME, true, true)); + + return list; + } + + /** + * Returns network's default kind instance. + * + * @return network's default kind + */ + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Network Resource", URI.create("/network/"), Network.getDefaultAttributes()); + return kind; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/NetworkInterface.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/NetworkInterface.java new file mode 100644 index 0000000..d8fbaf2 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/NetworkInterface.java @@ -0,0 +1,163 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.NetworkState; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI NetworkInterface + * + * @author Michal Kimle + */ +public class NetworkInterface extends Link { + + public static final String INTERFACE_ATTRIBUTE_NAME = "occi.networkinterface.interface"; + public static final String MAC_ATTRIBUTE_NAME = "occi.networkinterface.mac"; + public static final String STATE_ATTRIBUTE_NAME = "occi.networkinterface.state"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_INFRASTRUCTURE_DEFAULT; + public static final String TERM_DEFAULT = "networkinterface"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind network interface's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model network interface's model + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public NetworkInterface(String id, Kind kind, String title, Model model) throws InvalidAttributeValueException { + super(id, kind, title, model); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind network interface's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public NetworkInterface(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns network interface's interface (attribute + * occi.networkinterface.interface). + * + * @return network interface's interface + */ + public String getNetworkInterface() { + return getValue(INTERFACE_ATTRIBUTE_NAME); + } + + /** + * Sets network interface's interface + * + * @param networkInterface network interface's interface + * @throws InvalidAttributeValueException in case value for interface is + * invalid + */ + public void setNetworkInterface(String networkInterface) throws InvalidAttributeValueException { + addAttribute(INTERFACE_ATTRIBUTE_NAME, networkInterface); + } + + /** + * Returns network interface's mac address. + * + * @return network interface's mac address + */ + public String getMac() { + return getValue(MAC_ATTRIBUTE_NAME); + } + + /** + * Sets network interface's mac address + * + * @param mac network interface's mac address + * @throws InvalidAttributeValueException in case value for mac address is + * invalid + */ + public void setMac(String mac) throws InvalidAttributeValueException { + addAttribute(MAC_ATTRIBUTE_NAME, mac); + } + + /** + * Returns network interface's state. + * + * @return network interface's state + */ + public String getState() { + return getValue(STATE_ATTRIBUTE_NAME); + } + + /** + * Sets network interface's state. + * + * @param state network interface's state. Cannot be null. + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(NetworkState state) throws InvalidAttributeValueException { + if (state == null) { + throw new NullPointerException("state cannot be null"); + } + addAttribute(STATE_ATTRIBUTE_NAME, state.toString()); + } + + /** + * Sets network interface's state. + * + * @param stateName network interface's state. Cannot be null. + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(String stateName) throws InvalidAttributeValueException { + addAttribute(STATE_ATTRIBUTE_NAME, stateName); + } + + /** + * Returns networkinterface's default identifier + * 'http://schemas.ogf.org/occi/infrastructure#networkinterface' + * + * @return networkinterface's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns networkinterface's default attributes. For NetworkInterface class + * those are attributes occi.networkinterface.interface, + * occi.networkinterface.mac and occi.networkinterface.state. + * + * @return list of networkinterface's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Link.getDefaultAttributes()); + list.add(new Attribute(INTERFACE_ATTRIBUTE_NAME, true, true)); + list.add(new Attribute(MAC_ATTRIBUTE_NAME, true, false)); + list.add(new Attribute(STATE_ATTRIBUTE_NAME, true, true)); + + return list; + } + + /** + * Returns networkinterface's default kind instance. + * + * @return networkinterface's default kind + */ + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Networkinterface", URI.create("/networkinterface/"), NetworkInterface.getDefaultAttributes()); + return kind; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Storage.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Storage.java new file mode 100644 index 0000000..5d5a458 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/Storage.java @@ -0,0 +1,168 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.StorageState; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI Storage. + * + * @author Michal Kimle + */ +public class Storage extends Resource { + + public static final String SIZE_ATTRIBUTE_NAME = "occi.storage.size"; + public static final String STATE_ATTRIBUTE_NAME = "occi.storage.state"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_INFRASTRUCTURE_DEFAULT; + public static final String TERM_DEFAULT = "storage"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind storage's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model storage's model + * @param summary storage's summary + * @throws InvalidAttributeValueException in case of invalid id, title or + * summary value + */ + public Storage(String id, Kind kind, String title, Model model, String summary) throws InvalidAttributeValueException { + super(id, kind, title, model, summary); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind storage's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public Storage(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns storage's size (attribute occi.storage.size). + * + * @return storage's size + */ + public String getSize() { + return getValue(SIZE_ATTRIBUTE_NAME); + } + + /** + * Sets storage's size. + * + * @param size storage's size + * @throws InvalidAttributeValueException in case value for size is invalid + */ + public void setSize(float size) throws InvalidAttributeValueException { + addAttribute(SIZE_ATTRIBUTE_NAME, String.valueOf(size)); + } + + /** + * Sets storage's size. + * + * @param size storage's size + * @throws InvalidAttributeValueException in case value for size is invalid + */ + public void setSize(String size) throws InvalidAttributeValueException { + addAttribute(SIZE_ATTRIBUTE_NAME, size); + } + + /** + * Returns storage's state (attribute occi.storage.state). + * + * @return storage's state + */ + public String getState() { + return getValue(STATE_ATTRIBUTE_NAME); + } + + /** + * Sets storage's state. + * + * @param state storage's state. Cannot be null. + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(StorageState state) throws InvalidAttributeValueException { + if (state == null) { + throw new NullPointerException("state cannot be null"); + } + addAttribute(STATE_ATTRIBUTE_NAME, state.toString()); + } + + /** + * Sets storage's state. + * + * @param stateName storage's state + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(String stateName) throws InvalidAttributeValueException { + addAttribute(STATE_ATTRIBUTE_NAME, stateName); + } + + /** + * Returns storage's default scheme + * 'http://schemas.ogf.org/occi/infrastructure#' + * + * @return storage's default scheme + */ + public static URI getSchemeDefault() { + return Category.SCHEME_INFRASTRUCTURE_DEFAULT; + } + + /** + * Returns storage's default term 'storage'. + * + * @return storage's default term + */ + public static String getTermDefault() { + return "storage"; + } + + /** + * Returns storage's default identifier + * 'http://schemas.ogf.org/occi/infrastructure#storage' + * + * @return storage's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns storage's default attributes. For Storage class those are + * attributes occi.storage.size and occi.storage.state. + * + * @return list of storage's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Resource.getDefaultAttributes()); + list.add(new Attribute(SIZE_ATTRIBUTE_NAME, true, false)); + list.add(new Attribute(STATE_ATTRIBUTE_NAME, true, true)); + + return list; + } + + /** + * Returns storage's default kind instance. + * + * @return storage's default kind + */ + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Storage Resource", URI.create("/storage/"), Storage.getDefaultAttributes()); + return kind; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/StorageLink.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/StorageLink.java new file mode 100644 index 0000000..a095f39 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/StorageLink.java @@ -0,0 +1,163 @@ +package cz.cesnet.cloud.occi.infrastructure; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.enumeration.StorageLinkState; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +/** + * Class representing an OCCI StorageLink + * + * @author Michal Kimle + */ +public class StorageLink extends Link { + + public static final String DEVICE_ID_ATTRIBUTE_NAME = "occi.storagelink.deviceid"; + public static final String MOUNTPOINT_ATTRIBUTE_NAME = "occi.storagelink.mountpoint"; + public static final String STATE_ATTRIBUTE_NAME = "occi.storagelink.state"; + public static final URI SCHEME_DEFAULT = Category.SCHEME_INFRASTRUCTURE_DEFAULT; + public static final String TERM_DEFAULT = "storagelink"; + public static final String KIND_IDENTIFIER_DEFAULT = SCHEME_DEFAULT + TERM_DEFAULT; + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind storage link's kind. Cannot be null. + * @param title occi.core.title attribute + * @param model storage link's model + * @throws InvalidAttributeValueException in case of invalid id or title + * value + */ + public StorageLink(String id, Kind kind, String title, Model model) throws InvalidAttributeValueException { + super(id, kind, title, model); + } + + /** + * Constructor. + * + * @param id occi.core.id attribute. Cannot be null. + * @param kind storage link's kind. Cannot be null. + * @throws InvalidAttributeValueException in case of invalid id value + */ + public StorageLink(String id, Kind kind) throws InvalidAttributeValueException { + super(id, kind); + } + + /** + * Returns storage link's device id (attribute occi.storagelink.deviceid). + * + * @return storage link's device id + */ + public String getDeviceId() { + return getValue(DEVICE_ID_ATTRIBUTE_NAME); + } + + /** + * Sets storage link's device id. + * + * @param id storage link's device id + * @throws InvalidAttributeValueException in case value for devide id is + * invalid + */ + public void setDeviceId(String id) throws InvalidAttributeValueException { + addAttribute(DEVICE_ID_ATTRIBUTE_NAME, id); + } + + /** + * Returns storage link's mountpoint (attribute + * occi.storagelink.mountpoint). + * + * @return storage link's mountpoint + */ + public String getMountpoint() { + return getValue(MOUNTPOINT_ATTRIBUTE_NAME); + } + + /** + * Sets storage link's mountpoint + * + * @param mountpoint storage link's mountpoint + * @throws InvalidAttributeValueException in case value for moutnpoint is + * invalid + */ + public void setMountpoint(String mountpoint) throws InvalidAttributeValueException { + addAttribute(MOUNTPOINT_ATTRIBUTE_NAME, mountpoint); + } + + /** + * Returns storage link's state (attribute occi.storagelink.state). + * + * @return storage link's state + */ + public String getState() { + return getValue(STATE_ATTRIBUTE_NAME); + } + + /** + * Sets storage link's state. + * + * @param state storage link's state. Cannot be null. + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(StorageLinkState state) throws InvalidAttributeValueException { + if (state == null) { + throw new NullPointerException("state cannot be null"); + } + addAttribute(STATE_ATTRIBUTE_NAME, state.toString()); + } + + /** + * Sets storage link's state. + * + * @param stateName storage link's state + * @throws InvalidAttributeValueException in case value for state is invalid + */ + public void setState(String stateName) throws InvalidAttributeValueException { + addAttribute(STATE_ATTRIBUTE_NAME, stateName); + } + + /** + * Returns storagelink's default identifier + * 'http://schemas.ogf.org/occi/infrastructure#storagelink' + * + * @return storagelink's default identifier + */ + @Override + public String getDefaultKindIdentifier() { + return KIND_IDENTIFIER_DEFAULT; + } + + /** + * Returns storagelink's default attributes. For StorageLink class those are + * attributes occi.storagelink.deviceid, occi.storagelink.mountpoint and + * occi.storagelink.state. + * + * @return list of storagelink's default attributes + */ + public static List getDefaultAttributes() { + List list = new ArrayList<>(); + list.addAll(Storage.getDefaultAttributes()); + list.add(new Attribute(DEVICE_ID_ATTRIBUTE_NAME, true, false)); + list.add(new Attribute(MOUNTPOINT_ATTRIBUTE_NAME, false, false)); + list.add(new Attribute(STATE_ATTRIBUTE_NAME, true, true)); + + return list; + } + + /** + * Returns storagelink's default kind instance. + * + * @return storagelink's default kind + */ + public static Kind getDefaultKind() { + Kind kind = new Kind(SCHEME_DEFAULT, TERM_DEFAULT, "Storage Link", URI.create("/storagelink/"), StorageLink.getDefaultAttributes()); + return kind; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Allocation.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Allocation.java new file mode 100644 index 0000000..d6779a4 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Allocation.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum Allocation { + + DYNAMIC, STATIC; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Architecture.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Architecture.java new file mode 100644 index 0000000..b52c924 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/Architecture.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum Architecture { + + X_86, X_64; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/ComputeState.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/ComputeState.java new file mode 100644 index 0000000..3adf8d6 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/ComputeState.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum ComputeState { + + ACTIVE, INACTIVE, SUSPENDED; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/NetworkState.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/NetworkState.java new file mode 100644 index 0000000..060cf45 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/NetworkState.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum NetworkState { + + ACTIVE, INACTIVE; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageLinkState.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageLinkState.java new file mode 100644 index 0000000..688ef3a --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageLinkState.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum StorageLinkState { + + ACTIVE, INACTIVE; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageState.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageState.java new file mode 100644 index 0000000..c0949ea --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/infrastructure/enumeration/StorageState.java @@ -0,0 +1,15 @@ +package cz.cesnet.cloud.occi.infrastructure.enumeration; + +/** + * + * @author Michal Kimle + */ +public enum StorageState { + + ONLINE, OFFLINE, BACKUP, SNAPSHOT, RESIZE, DEGRADED; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/CollectionType.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/CollectionType.java new file mode 100644 index 0000000..53a30f4 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/CollectionType.java @@ -0,0 +1,10 @@ +package cz.cesnet.cloud.occi.parser; + +/** + * + * @author Michal Kimle + */ +public enum CollectionType { + + RESOURCE, LINK, ACTION; +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/JSONParser.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/JSONParser.java new file mode 100644 index 0000000..24b04a3 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/JSONParser.java @@ -0,0 +1,30 @@ +package cz.cesnet.cloud.occi.parser; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Collection; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.exception.ParsingException; +import java.net.URI; +import java.util.List; + +/** + * + * @author Michal Kimle + */ +public class JSONParser implements Parser { + + @Override + public Model parseModel(String mediaType, String body, Headers headers) throws ParsingException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Collection parseCollection(String mediaType, String body, Headers headers, CollectionType collectionType) throws ParsingException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List parseLocations(String mediaType, String body, Headers headers) throws ParsingException { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/MediaType.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/MediaType.java new file mode 100644 index 0000000..d07a1e4 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/MediaType.java @@ -0,0 +1,13 @@ +package cz.cesnet.cloud.occi.parser; + +/** + * + * @author Michal Kimle + */ +public class MediaType { + + public static final String APPLICATION_JSON = "application/json"; + public static final String TEXT_OCCI = "text/occi"; + public static final String TEXT_PLAIN = "text/plain"; + public static final String TEXT_URI_LIST = "text/uri-list"; +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/Parser.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/Parser.java new file mode 100644 index 0000000..8e800dd --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/Parser.java @@ -0,0 +1,53 @@ +package cz.cesnet.cloud.occi.parser; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Collection; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.exception.ParsingException; +import java.net.URI; +import java.util.List; + +/** + * Interface for parser of OCCI messages. + * + * @author Michal Kimle + */ +public interface Parser { + + /** + * Parses an OCCI model either from body or headers depending on mediaType. + * + * @param mediaType media type of the parsed server response + * @param body body of the server response + * @param headers headers of the server response + * @return OCCI model + * @throws ParsingException when error occures during the parsing + */ + Model parseModel(String mediaType, String body, Headers headers) throws ParsingException; + + /** + * Parses an OCCI entity either from body or headers depending on mediaType + * and collectionType. + * + * @param mediaType media type of the parsed server response + * @param body body of the server response + * @param headers headers of the server response + * @param collectionType collection type representing entities that will be + * parsed from the response + * @return collection of parsed entities + * @throws ParsingException when error occures during the parsing + */ + Collection parseCollection(String mediaType, String body, Headers headers, CollectionType collectionType) throws ParsingException; + + /** + * Parses a list of locations either from body or headers depending on + * mediaType. + * + * @param mediaType media type of the parsed server response + * @param body body of the server response + * @param headers headers of the server response + * @return list of locations + * @throws ParsingException when error occures during the parsing + */ + List parseLocations(String mediaType, String body, Headers headers) throws ParsingException; +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/TextParser.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/TextParser.java new file mode 100644 index 0000000..c968b11 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/parser/TextParser.java @@ -0,0 +1,916 @@ +package cz.cesnet.cloud.occi.parser; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Collection; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.ActionInstance; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Category; +import cz.cesnet.cloud.occi.core.Entity; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.exception.ParsingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Michal Kimle + */ +public class TextParser implements Parser { + + //regular expression groups + public static final String GROUP_TERM = "term"; + public static final String GROUP_SCHEME = "scheme"; + public static final String GROUP_CLASS = "class"; + public static final String GROUP_TITLE = "title"; + public static final String GROUP_REL = "rel"; + public static final String GROUP_LOCATION = "location"; + public static final String GROUP_ATTRIBUTES = "attributes"; + public static final String GROUP_ACTIONS = "actions"; + public static final String GROUP_URI = "uri"; + public static final String GROUP_SELF = "self"; + public static final String GROUP_CATEGORY = "category"; + + //regular expressions + public static final String REGEXP_LOALPHA = "[a-z]"; + public static final String REGEXP_ALPHA = "[a-zA-Z]"; + public static final String REGEXP_DIGIT = "[0-9]"; + public static final String REGEXP_INT = REGEXP_DIGIT + "+"; + public static final String REGEXP_FLOAT = REGEXP_INT + "\\." + REGEXP_INT; + public static final String REGEXP_NUMBER = REGEXP_FLOAT + "|" + REGEXP_INT; + public static final String REGEXP_BOOL = "\\b(?" + REGEXP_TERM + ")" // term (mandatory) + + ";\\s*scheme=\"(?<" + GROUP_SCHEME + ">" + REGEXP_SCHEME + ")(?:" + REGEXP_TERM + ")?\"" // scheme (mandatory) + + ";\\s*class=\"?(?<" + GROUP_CLASS + ">" + REGEXP_CLASS + ")\"?" // class (mandatory) + + "(;\\s*title=\"(?<" + GROUP_TITLE + ">" + REGEXP_QUOTED_STRING + ")\")?" // title (optional) + + "(;\\s*rel=\"(?<" + GROUP_REL + ">" + REGEXP_TYPE_IDENTIFIER_LIST + ")\")?" // rel (optional) + + "(;\\s*location=\"(?<" + GROUP_LOCATION + ">" + REGEXP_URI_REF + ")\")?" // location (optional) + + "(;\\s*attributes=\"(?<" + GROUP_ATTRIBUTES + ">" + REGEXP_ATTRIBUTE_LIST + ")\")?" // attributes (optional) + + "(;\\s*actions=\"(?<" + GROUP_ACTIONS + ">" + REGEXP_ACTION_LIST + ")\")?" // actions (optional) + + ";?"; // additional semicolon at the end (not specified, for interoperability) + + public static final String REGEXP_ATTRIBUTES = "(" + REGEXP_ATTRIBUTE_DEF + ")"; + + public static final String REGEXP_LINK = "\\<(?<" + GROUP_URI + ">" + REGEXP_URI_REF + ")\\>" // uri (mandatory) + + ";\\s*rel=\"(?<" + GROUP_REL + ">" + REGEXP_RESOURCE_TYPE + ")\"" // rel (mandatory) + + "(;\\s*self=\"(?<" + GROUP_SELF + ">" + REGEXP_LINK_INSTANCE + ")\")?" // self (optional) + + "(;\\s*category=\"(?<" + GROUP_CATEGORY + ">(;?\\s*(" + REGEXP_LINK_TYPE + "))+)\")?" // category (optional) + + "(;\\s*(?<" + GROUP_ATTRIBUTES + ">(;?\\s*" + REGEXP_ATTRIBUTE_REPR + ")*))?" // attributes (optional) + + ";?"; // additional semicolon at the end (not specified, for interoperability) + + public static final Pattern PATTERN_CATEGORY = Pattern.compile(REGEXP_CATEGORY); + public static final Pattern PATTERN_ATTRIBUTES = Pattern.compile(REGEXP_ATTRIBUTES); + public static final Pattern PATTERN_LINK = Pattern.compile(REGEXP_LINK); + + public static final String CATEGORY_HEADER = "category"; + public static final String LINK_HEADER = "link"; + public static final String ATTRIBUTE_HEADER = "x-occi-attribute"; + public static final String LOCATION_HEADER = "location"; + + private static final Logger LOGGER = LoggerFactory.getLogger(TextParser.class); + + /** + * @see Parser#parseModel(java.lang.String, java.lang.String, + * com.sun.net.httpserver.Headers) + */ + @Override + public Model parseModel(String mediaType, String body, Headers headers) throws ParsingException { + LOGGER.debug("Parsing model..."); + + switch (mediaType) { + case MediaType.TEXT_OCCI: + return parseModelFromHeaders(headers); + case MediaType.TEXT_PLAIN: + return parseModelFromBody(body); + default: + throw new ParsingException("Unknown media type '" + mediaType + "'."); + } + } + + private Model parseModelFromBody(String body) throws ParsingException { + LOGGER.debug("Reading response body."); + + body = body.trim(); + String replaced = Pattern.compile("Category:\\s*", Pattern.CASE_INSENSITIVE).matcher(body).replaceAll(""); + + String[] lines = replaced.split("[\\r\\n]+"); + return parseModelFromArray(lines); + } + + private Model parseModelFromHeaders(Headers headers) throws ParsingException { + LOGGER.debug("Reading response headers."); + + if (!headers.containsKey(CATEGORY_HEADER)) { + throw new ParsingException("No header '" + CATEGORY_HEADER + "' among headers."); + } + + String[] categories = headers.getFirst(CATEGORY_HEADER).split(","); + return parseModelFromArray(categories); + } + + private Model parseModelFromArray(String[] lines) throws ParsingException { + Model model = new Model(); + Map> kindMapping = new HashMap<>(); + Map> mixinMapping = new HashMap<>(); + + for (String line : lines) { + LOGGER.debug("Matching line '{}' against category pattern.", line); + Matcher matcher = PATTERN_CATEGORY.matcher(line); + if (!matcher.find()) { + throw new ParsingException("Invalid line: " + line); + } + String term = matcher.group(GROUP_TERM); + String scheme = matcher.group(GROUP_SCHEME); + String categoryClass = matcher.group(GROUP_CLASS); + String location = matcher.group(GROUP_LOCATION); + LOGGER.debug("Match: term={}, scheme={}, class={}, title={}, rel={}, location={}, attributes={}, actions={}", + term, scheme, categoryClass, matcher.group(GROUP_TITLE), matcher.group(GROUP_REL), location, matcher.group(GROUP_ATTRIBUTES), matcher.group(GROUP_ACTIONS)); + + if (term == null || term.isEmpty()) { + throw new ParsingException("No term found."); + } + if (scheme == null || scheme.isEmpty()) { + throw new ParsingException("No scheme found."); + } + if (categoryClass == null || categoryClass.isEmpty()) { + throw new ParsingException("No class found."); + } + + switch (categoryClass) { + case "kind": + if (location == null || location.isEmpty()) { + throw new ParsingException("No location found."); + } + model = addKind(matcher, kindMapping, model); + break; + case "mixin": + model = addMixin(matcher, mixinMapping, model); + break; + case "action": + model = addAction(matcher, model); + break; + default: + throw new ParsingException("Unknown class type."); + } + } + + if (!kindMapping.isEmpty()) { + List defaultKinds = createDefaultKinds(); + for (Kind kind : defaultKinds) { + if (model.containsKind(kind)) { + continue; + } + + model.addKind(kind); + + for (String identifier : kindMapping.keySet()) { + if (identifier.equals(kind.getIdentifier())) { + List kinds = kindMapping.remove(identifier); + for (Kind k : kinds) { + k.setParentKind(kind); + k.addRelation(kind); + } + } + } + } + + if (!kindMapping.isEmpty()) { + throw new ParsingException("Unknown kind relations found: " + kindMapping); + } + } + + if (!mixinMapping.isEmpty()) { + throw new ParsingException("Unknown mixins relations found: " + mixinMapping); + } + + return model; + } + + private Model addKind(Matcher matcher, Map> mapping, Model model) throws ParsingException { + LOGGER.debug("Adding kind..."); + String actions = matcher.group(GROUP_ACTIONS); + String rel = matcher.group(GROUP_REL); + String term = matcher.group(GROUP_TERM); + + Kind kind = createKind(matcher); + kind = (Kind) connectActions(actions, kind, model); + + if (rel != null && !rel.isEmpty()) { + if (!model.containsKind(rel)) { + LOGGER.debug("Unexpected relation " + rel + " in kind " + term + ". Storing for later mapping"); + if (mapping.containsKey(rel)) { + List kinds = mapping.get(rel); + kinds.add(kind); + } else { + List kinds = new ArrayList<>(); + kinds.add(kind); + mapping.put(rel, kinds); + } + } else { + Kind k = model.getKind(rel); + LOGGER.debug("Creating relation between {} and {}.", kind, k); + kind.setParentKind(k); + kind.addRelation(k); + } + } + + String identifier = kind.getIdentifier(); + if (mapping.containsKey(identifier)) { + List kinds = mapping.remove(identifier); + for (Kind k : kinds) { + k.setParentKind(kind); + k.addRelation(kind); + } + } + + model.addKind(kind); + return model; + } + + private Model addMixin(Matcher matcher, Map> mapping, Model model) throws ParsingException { + LOGGER.debug("Adding mixin..."); + String actions = matcher.group(GROUP_ACTIONS); + String rel = matcher.group(GROUP_REL); + String term = matcher.group(GROUP_TERM); + + Mixin mixin = createMixin(matcher); + mixin = (Mixin) connectActions(actions, mixin, model); + + if (rel != null && !rel.isEmpty()) { + if (!model.containsMixin(rel)) { + LOGGER.debug("Unexpected relation " + rel + " in mixin " + term + ". Storing for later mapping"); + if (mapping.containsKey(rel)) { + List mixins = mapping.get(rel); + mixins.add(mixin); + } else { + List mixins = new ArrayList<>(); + mixins.add(mixin); + mapping.put(rel, mixins); + } + } else { + Mixin m = model.getMixin(rel); + LOGGER.debug("Creating relation between {} and {}.", mixin, m); + mixin.addRelation(m); + } + } + + String identifier = mixin.getIdentifier(); + if (mapping.containsKey(identifier)) { + List mixins = mapping.remove(identifier); + for (Mixin m : mixins) { + m.addRelation(mixin); + } + } + + model.addMixin(mixin); + return model; + } + + private Model addAction(Matcher matcher, Model model) throws ParsingException { + LOGGER.debug("Adding action..."); + String term = matcher.group(GROUP_TERM); + String scheme = matcher.group(GROUP_SCHEME); + String title = matcher.group(GROUP_TITLE); + String attributes = matcher.group(GROUP_ATTRIBUTES); + + String actionIdentifier = scheme + term; + if (model.containsAction(actionIdentifier)) { + Set parsedAttributes = parseAttributes(attributes); + + Action action = model.getAction(actionIdentifier); + action.setTitle(title); + for (Attribute attribute : parsedAttributes) { + action.addAttribute(attribute); + } + } else { + Action action = createAction(matcher); + model.addAction(action); + } + + return model; + } + + private Category connectActions(String actions, Category category, Model model) throws ParsingException { + LOGGER.debug("Connecting actions..."); + if (actions == null || actions.isEmpty()) { + return category; + } + + String[] splitedActions = actions.split("\\s+"); + for (String actionIdentifier : splitedActions) { + LOGGER.debug("Action identifier: {}", actionIdentifier); + Action action; + if (model != null && model.containsAction(actionIdentifier)) { + action = model.getAction(actionIdentifier); + } else { + try { + String[] splitedAction = actionIdentifier.split("#"); + if (splitedAction.length != 2) { + throw new ParsingException("Invalid action identifier: " + actionIdentifier + "."); + } + action = new Action(new URI(splitedAction[0] + "#"), splitedAction[1]); + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid category scheme: " + actionIdentifier + ".", ex); + } + } + + category.addAction(action); + } + + return category; + } + + private Set parseAttributes(String attributes) { + LOGGER.debug("Parsing attributes: {}", attributes); + Set attributeSet = new HashSet<>(); + if (attributes == null || attributes.isEmpty()) { + return attributeSet; + } + + Matcher matcher = PATTERN_ATTRIBUTES.matcher(attributes); + while (matcher.find()) { + String attributeString = matcher.group(); + LOGGER.debug("Found attribute represented by string: {}", attributeString); + Attribute attribute = parseAttribute(attributeString); + attributeSet.add(attribute); + } + + return attributeSet; + } + + private Attribute parseAttribute(String attributeString) { + String[] splitedAttribute = attributeString.split("\\{"); + Attribute attribute = new Attribute(splitedAttribute[0]); + if (splitedAttribute.length == 2) { + if (splitedAttribute[1].contains("immutable")) { + attribute.setImmutable(true); + } + if (splitedAttribute[1].contains("required")) { + attribute.setRequired(true); + } + } + + LOGGER.debug("New attribute: {}", attribute); + return attribute; + } + + private List createDefaultKinds() { + List defaultKinds = new ArrayList<>(); + + Set attributes = new HashSet<>(); + attributes.add(new Attribute(Entity.ID_ATTRIBUTE_NAME, true, true)); + attributes.add(new Attribute(Entity.TITLE_ATTRIBUTE_NAME, false, false)); + Kind entity = new Kind(Entity.SCHEME_DEFAULT, Entity.TERM_DEFAULT, "Entity", URI.create("/entity/"), attributes); + defaultKinds.add(entity); + + attributes = new HashSet<>(); + attributes.add(new Attribute(Resource.SUMMARY_ATTRIBUTE_NAME, false, false)); + Kind resource = new Kind(Resource.SCHEME_DEFAULT, Resource.TERM_DEFAULT, "Resource", URI.create("/resource/"), attributes); + resource.setParentKind(entity); + resource.addRelation(entity); + defaultKinds.add(resource); + + attributes = new HashSet<>(); + attributes.add(new Attribute(Link.SOURCE_ATTRIBUTE_NAME, true, false)); + attributes.add(new Attribute(Link.TARGET_ATTRIBUTE_NAME, true, false)); + Kind link = new Kind(Link.SCHEME_DEFAULT, Link.TERM_DEFAULT, "Link", URI.create("/link/"), attributes); + link.setParentKind(entity); + link.addRelation(entity); + defaultKinds.add(link); + + return defaultKinds; + } + + /** + * @see Parser#parseLocations(java.lang.String, java.lang.String, + * com.sun.net.httpserver.Headers) + */ + @Override + public List parseLocations(String mediaType, String body, Headers headers) throws ParsingException { + LOGGER.debug("Parsing location..."); + + switch (mediaType) { + case MediaType.TEXT_OCCI: + return parseLocationsFromHeaders(headers); + case MediaType.TEXT_URI_LIST: + case MediaType.TEXT_PLAIN: + return parseLocationsFromBody(body); + default: + throw new ParsingException("Unknown media type '" + mediaType + "'."); + } + } + + private List parseLocationsFromHeaders(Headers headers) throws ParsingException { + LOGGER.debug("Reading response headers."); + + if (!headers.containsKey(LOCATION_HEADER)) { + throw new ParsingException("No header '" + LOCATION_HEADER + "' among headers."); + } + + String[] locations = headers.getFirst(LOCATION_HEADER).split(","); + return makeURIList(locations); + } + + private List parseLocationsFromBody(String body) throws ParsingException { + LOGGER.debug("Reading response body."); + + body = body.trim(); + String replaced = Pattern.compile("X-OCCI-Location:\\s*", Pattern.CASE_INSENSITIVE).matcher(body).replaceAll(""); + String[] lines = replaced.split("[\\r\\n]+"); + return makeURIList(lines); + } + + private List makeURIList(String[] locations) throws ParsingException { + + List locationsURI = new ArrayList<>(); + for (String location : locations) { + try { + locationsURI.add(new URI(location)); + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid location: " + location + ".", ex); + } + } + + return locationsURI; + } + + /** + * @see Parser#parseCollection(java.lang.String, java.lang.String, + * com.sun.net.httpserver.Headers, + * cz.cesnet.cloud.occi.parser.CollectionType) + */ + @Override + public Collection parseCollection(String mediaType, String body, Headers headers, CollectionType collectionType) throws ParsingException { + LOGGER.debug("Parsing collection..."); + + switch (mediaType) { + case MediaType.TEXT_OCCI: + return parseCollectionFromHeaders(headers, collectionType); + case MediaType.TEXT_PLAIN: + return parseCollectionFromBody(body, collectionType); + default: + throw new ParsingException("Unknown media type '" + mediaType + "'."); + } + } + + private Collection parseCollectionFromHeaders(Headers headers, CollectionType collectionType) throws ParsingException { + LOGGER.debug("Reading headers."); + + if (!headers.containsKey(CATEGORY_HEADER)) { + throw new ParsingException("No '" + CATEGORY_HEADER + "' header."); + } + + List lines = new ArrayList<>(); + lines.addAll(Arrays.asList(headers.getFirst(CATEGORY_HEADER).split(","))); + + if (headers.containsKey(ATTRIBUTE_HEADER)) { + lines.addAll(Arrays.asList(headers.getFirst(ATTRIBUTE_HEADER).split(","))); + } + + if (headers.containsKey(LINK_HEADER)) { + lines.addAll(Arrays.asList(headers.getFirst(LINK_HEADER).split(","))); + } + + return parseCollectionFromArray(lines.toArray(new String[0]), collectionType); + } + + private Collection parseCollectionFromBody(String body, CollectionType collectionType) throws ParsingException { + LOGGER.debug("Reading body."); + + body = body.trim(); + String replaced = Pattern.compile("Category:\\s*", Pattern.CASE_INSENSITIVE).matcher(body).replaceAll(""); + replaced = Pattern.compile("Link:\\s*", Pattern.CASE_INSENSITIVE).matcher(body).replaceAll(""); + replaced = Pattern.compile("X-OCCI-Attribute:\\s*", Pattern.CASE_INSENSITIVE).matcher(body).replaceAll(""); + String[] lines = replaced.split("[\\r\\n]+"); + + return parseCollectionFromArray(lines, collectionType); + } + + private Collection parseCollectionFromArray(String[] lines, CollectionType collectionType) throws ParsingException { + Collection collection = new Collection(); + Kind kind; + Set mixins = new HashSet<>(); + List rawAttributes = new ArrayList<>(); + Map attributesWithValues = null; + + switch (collectionType) { + //expecting resource instance + case RESOURCE: + Set links = new HashSet<>(); + Set actionLinks = new HashSet<>(); + + kind = lookForKind(lines[0]); + lines = Arrays.copyOfRange(lines, 1, lines.length); + + for (String line : lines) { + //looking for mixin lines + if (lookForMixins(line, mixins)) { + continue; + } + //looking for attribute lines + if (lookForAttributes(line, rawAttributes)) { + continue; + } + //looking for link lines + lookForLinks(line, links, actionLinks); + } + + attributesWithValues = parseAttributesWithValues(rawAttributes.toArray(new String[0])); + if (!attributesWithValues.containsKey(Resource.ID_ATTRIBUTE_NAME)) { + throw new ParsingException("No id found. Cannot construct a resource."); + } + + Resource resource = null; + try { + resource = new Resource(attributesWithValues.get(Entity.ID_ATTRIBUTE_NAME), kind); + + attributesWithValues.remove(Entity.ID_ATTRIBUTE_NAME); + resource.addMixins(mixins); + resource.addLinks(links); + resource.addActions(actionLinks); + resource.addAttributes(attributesWithValues); + } catch (InvalidAttributeValueException ex) { + throw new ParsingException("Invalid attribute value found", ex); + } + collection.addResource(resource); + + break; + case LINK: + kind = lookForKind(lines[0]); + lines = Arrays.copyOfRange(lines, 1, lines.length); + + for (String line : lines) { + //looking for mixin lines + if (lookForMixins(line, mixins)) { + continue; + } + //looking for attribute lines + lookForAttributes(line, rawAttributes); + } + + attributesWithValues = parseAttributesWithValues(rawAttributes.toArray(new String[0])); + if (!attributesWithValues.containsKey(Resource.ID_ATTRIBUTE_NAME)) { + throw new ParsingException("No id found. Cannot construct a resource."); + } + + Link link = null; + try { + link = new Link(attributesWithValues.get(Entity.ID_ATTRIBUTE_NAME), kind); + + attributesWithValues.remove(Entity.ID_ATTRIBUTE_NAME); + link.addMixins(mixins); + link.addAttributes(attributesWithValues); + } catch (InvalidAttributeValueException ex) { + throw new ParsingException("Invalid attribute value found", ex); + } + collection.addLink(link); + break; + case ACTION: + ActionInstance actionInstance = lookForActionInstance(lines[0]); + lines = Arrays.copyOfRange(lines, 1, lines.length); + + for (String line : lines) { + //looking for attribute lines + lookForAttributes(line, rawAttributes); + } + + attributesWithValues = parseAttributesWithValues(rawAttributes.toArray(new String[0])); + actionInstance.addAttributes(attributesWithValues); + + collection.addAction(actionInstance); + break; + default: + throw new ParsingException("Unknown collection type'" + collectionType + "'."); + } + + return collection; + } + + private Kind lookForKind(String line) throws ParsingException { + LOGGER.debug("Matching line '{}' against category pattern.", line); + Matcher matcher = PATTERN_CATEGORY.matcher(line); + + if (!matcher.find()) { + throw new ParsingException("No kind specification found."); + } + + LOGGER.debug("Match: term={}, scheme={}, class={}, title={}, rel={}, location={}, attributes={}, actions={}", + matcher.group(GROUP_TERM), matcher.group(GROUP_SCHEME), + matcher.group(GROUP_CLASS), matcher.group(GROUP_TITLE), + matcher.group(GROUP_REL), matcher.group(GROUP_LOCATION), + matcher.group(GROUP_ATTRIBUTES), matcher.group(GROUP_ACTIONS)); + + String actions = matcher.group(GROUP_ACTIONS); + String categoryClass = matcher.group(GROUP_CLASS); + + if (!categoryClass.equals("kind")) { + throw new ParsingException("No kind specification found."); + } + + Kind kind = createKind(matcher); + connectActions(actions, kind, null); + + return kind; + } + + private boolean lookForMixins(String line, Set mixins) throws ParsingException { + LOGGER.debug("Matching line '{}' against category pattern.", line); + Matcher matcher = PATTERN_CATEGORY.matcher(line); + + if (matcher.find()) { + LOGGER.debug("Match: term={}, scheme={}, class={}, title={}, rel={}, location={}, attributes={}, actions={}", + matcher.group(GROUP_TERM), matcher.group(GROUP_SCHEME), + matcher.group(GROUP_CLASS), matcher.group(GROUP_TITLE), + matcher.group(GROUP_REL), matcher.group(GROUP_LOCATION), + matcher.group(GROUP_ATTRIBUTES), matcher.group(GROUP_ACTIONS)); + + String categoryClass = matcher.group(GROUP_CLASS); + String actions = matcher.group(GROUP_ACTIONS); + + switch (categoryClass) { + case "mixin": + Mixin mixin = createMixin(matcher); + connectActions(actions, mixin, null); + mixins.add(mixin); + break; + default: + throw new ParsingException("Unknown category class '" + categoryClass + "'."); + } + + return true; + } + + return false; + } + + private boolean lookForAttributes(String line, List attributes) { + LOGGER.debug("Matching line '{}' against attribute pattern.", line); + if (line.matches(REGEXP_ATTRIBUTE_REPR)) { + attributes.add(line); + return true; + } + + return false; + } + + private void lookForLinks(String line, Set links, Set actionLinks) throws ParsingException { + LOGGER.debug("Matching line '{}' against link pattern.", line); + Matcher matcher = PATTERN_LINK.matcher(line); + + if (matcher.find()) { + LOGGER.debug("Match: uri={}, rel={}, self={}, category={}, attributes={}", + matcher.group(GROUP_URI), matcher.group(GROUP_REL), + matcher.group(GROUP_SELF), matcher.group(GROUP_CATEGORY), + matcher.group(GROUP_ATTRIBUTES)); + + if (matcher.group(GROUP_URI).contains("?action=")) { + Action action = createAction(matcher.group(GROUP_REL)); + actionLinks.add(action); + } else { + Link link = createLink(matcher); + links.add(link); + } + } + } + + private ActionInstance lookForActionInstance(String line) throws ParsingException { + LOGGER.debug("Matching line '{}' against category pattern.", line); + Matcher matcher = PATTERN_CATEGORY.matcher(line); + + if (!matcher.find()) { + throw new ParsingException("No action specification found."); + } + + LOGGER.debug("Match: term={}, scheme={}, class={}, title={}, rel={}, location={}, attributes={}, actions={}", + matcher.group(GROUP_TERM), matcher.group(GROUP_SCHEME), + matcher.group(GROUP_CLASS), matcher.group(GROUP_TITLE), + matcher.group(GROUP_REL), matcher.group(GROUP_LOCATION), + matcher.group(GROUP_ATTRIBUTES), matcher.group(GROUP_ACTIONS)); + + String categoryClass = matcher.group(GROUP_CLASS); + + if (!categoryClass.equals("action")) { + throw new ParsingException("No action specification found."); + } + + Action action = createAction(matcher); + ActionInstance actionInstance = new ActionInstance(action); + + return actionInstance; + } + + private Map parseAttributesWithValues(String[] attributes) throws ParsingException { + LOGGER.debug("Parsing attributes with values"); + Map result = new HashMap<>(); + + for (String attribute : attributes) { + String trimmedAttribute = attribute.trim(); + LOGGER.debug("Attribute represented by string: {}", trimmedAttribute); + String[] parts = trimmedAttribute.split("=", 2); + if (parts.length != 2) { + throw new ParsingException("Wrong attribute format."); + } + + String name = parts[0]; + String value = parts[1].replaceAll("\"", ""); + if (value.endsWith(";")) { + value = value.substring(0, value.length() - 1); + } + + result.put(name, value); + } + + return result; + } + + private Kind createKind(Matcher matcher) throws ParsingException { + String term = matcher.group(GROUP_TERM); + String scheme = matcher.group(GROUP_SCHEME); + String title = matcher.group(GROUP_TITLE); + String location = matcher.group(GROUP_LOCATION); + String attributes = matcher.group(GROUP_ATTRIBUTES); + + try { + Set parsedAttributes = parseAttributes(attributes); + URI locationUri = null; + if (location != null) { + locationUri = new URI(location); + locationUri = new URI(locationUri.getPath()); + } + Kind kind = new Kind(new URI(scheme), term, title, locationUri, parsedAttributes); + + return kind; + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid shceme or location.", ex); + } + } + + private Mixin createMixin(Matcher matcher) throws ParsingException { + String term = matcher.group(GROUP_TERM); + String scheme = matcher.group(GROUP_SCHEME); + String title = matcher.group(GROUP_TITLE); + String location = matcher.group(GROUP_LOCATION); + String attributes = matcher.group(GROUP_ATTRIBUTES); + + try { + URI locationUri = null; + if (location == null || location.isEmpty()) { + locationUri = new URI("/mixin/" + term); + locationUri = new URI(locationUri.getPath()); + } else { + locationUri = new URI(location); + locationUri = new URI(locationUri.getPath()); + } + Set parsedAttributes = parseAttributes(attributes); + Mixin mixin = new Mixin(new URI(scheme), term, title, locationUri, parsedAttributes); + + return mixin; + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid shceme or location.", ex); + } + } + + private Link createLink(Matcher matcher) throws ParsingException { + String uri = matcher.group(GROUP_URI); + String rel = matcher.group(GROUP_REL); + String self = matcher.group(GROUP_SELF); + String category = matcher.group(GROUP_CATEGORY); + String attributes = matcher.group(GROUP_ATTRIBUTES); + + try { + Kind kind; + List mixins = new ArrayList<>(); + if (category != null && !category.isEmpty()) { + String[] categories = category.split(" "); + String[] kindCategory = categories[0].split("#"); + if (kindCategory.length != 2) { + throw new ParsingException("Invalid link category: " + category); + } + kind = new Kind(new URI(kindCategory[0] + "#"), kindCategory[1]); + + if (categories.length > 1) { + for (int i = 1; i < categories.length; i++) { + String[] splitedCategory = categories[i].split("#"); + if (splitedCategory.length != 2) { + throw new ParsingException("Invalid link category: " + category); + } + Mixin mixin = new Mixin(new URI(splitedCategory[0] + "#"), splitedCategory[1]); + mixins.add(mixin); + } + } + } else { + kind = new Kind(Link.SCHEME_DEFAULT, Link.TERM_DEFAULT); + } + + Link link; + if (self != null && !self.isEmpty()) { + String[] splitedSelf = divideUriByLastSegment(self); + kind.setLocation(new URI(splitedSelf[1])); + link = new Link(splitedSelf[0], kind); + } else { + link = new Link(UUID.randomUUID().toString(), kind); + } + + link.addMixins(mixins); + + link.setTarget(uri); + link.setRelation(rel); + Map attributesWithValues = parseAttributesWithValues(attributes.split(";")); + for (String name : attributesWithValues.keySet()) { + link.addAttribute(name, attributesWithValues.get(name)); + // ***********HACK********* + if (name.equals("occi.core.id")) { + String value = attributesWithValues.get(name); + value = value.substring(value.lastIndexOf('/') + 1); + link.addAttribute(name, value); + } + // ***********HACK********* + } + + return link; + } catch (InvalidAttributeValueException ex) { + throw new ParsingException("Invalid attribute value found", ex); + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid shceme or location.", ex); + } + } + + private Action createAction(String rel) throws ParsingException { + if (rel == null || rel.isEmpty()) { + throw new ParsingException("Link for action is missing 'rel' element."); + } + + String[] splited = rel.split("#"); + if (splited.length != 2) { + throw new ParsingException("Invalid relation specification: " + rel); + } + + return createAction(splited[0] + "#", splited[1], null, null); + } + + private Action createAction(Matcher matcher) throws ParsingException { + String term = matcher.group(GROUP_TERM); + String scheme = matcher.group(GROUP_SCHEME); + String title = matcher.group(GROUP_TITLE); + String attributes = matcher.group(GROUP_ATTRIBUTES); + + return createAction(scheme, term, title, attributes); + } + + private Action createAction(String scheme, String term, String title, String attributes) throws ParsingException { + Set parsedAttributes = parseAttributes(attributes); + Action action = null; + try { + action = new Action(new URI(scheme), term, title, parsedAttributes); + } catch (URISyntaxException ex) { + throw new ParsingException("Invalid URI.", ex); + } + return action; + } + + public static String[] divideUriByLastSegment(String uri) { + String[] parts = new String[2]; + parts[0] = uri.substring(uri.lastIndexOf('/') + 1); + parts[1] = uri.substring(0, uri.lastIndexOf('/') + 1); + + return parts; + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/renderer/TextRenderer.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/renderer/TextRenderer.java new file mode 100644 index 0000000..3895605 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/renderer/TextRenderer.java @@ -0,0 +1,35 @@ +package cz.cesnet.cloud.occi.renderer; + +/** + * Helper class for rendering specific methods. + * + * @author Michal Kimle + */ +public class TextRenderer { + + /** + * Surrounds given string with prefix '="' and suffix '";'. + * + * @param string string to apply prefix and suffix to + * @return modified string + */ + public static String surroundString(String string) { + return surroundString(string, "=\"", "\";"); + } + + /** + * Surround given string with given prefix and suffix. + * + * @param string string to apply prefix and suffix to + * @param prefix prefix to apply + * @param suffix suffix to apply + * @return modified string + */ + public static String surroundString(String string, String prefix, String suffix) { + StringBuilder sb = new StringBuilder(string); + sb.append(suffix); + sb.insert(0, prefix); + + return sb.toString(); + } +} diff --git a/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/type/Identifiable.java b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/type/Identifiable.java new file mode 100644 index 0000000..92b1ee1 --- /dev/null +++ b/jOCCI-core/src/main/java/cz/cesnet/cloud/occi/type/Identifiable.java @@ -0,0 +1,14 @@ +package cz.cesnet.cloud.occi.type; + +/** + * @author Michal Kimle + */ +public interface Identifiable { + + /** + * Returns identifier by which the object is recognized. + * + * @return object's identifier + */ + public String getIdentifier(); +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/CollectionTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/CollectionTest.java new file mode 100644 index 0000000..6ae9585 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/CollectionTest.java @@ -0,0 +1,38 @@ +package cz.cesnet.cloud.occi; + +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.ActionInstance; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Resource; +import java.net.URI; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class CollectionTest { + + public CollectionTest() { + } + + @Test + public void testSetModel() throws Exception { + Kind kind = new Kind(new URI("http://dummy.kind"), "term"); + Resource resource = new Resource("resource_id", kind); + Link link = new Link("link_id", kind); + ActionInstance ai = new ActionInstance(new Action(new URI("http://dummy.action"), "term")); + + Collection collection = new Collection(); + collection.addAction(ai); + collection.addLink(link); + collection.addResource(resource); + + Model model = new Model(); + model.addKind(kind); + + collection.setModel(model); + + assertEquals(model, resource.getModel()); + assertEquals(model, link.getModel()); + assertEquals(model, ai.getModel()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/DataGenerator.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/DataGenerator.java new file mode 100644 index 0000000..ab93406 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/DataGenerator.java @@ -0,0 +1,295 @@ +package cz.cesnet.cloud.occi; + +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.ActionInstance; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Entity; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.Compute; +import cz.cesnet.cloud.occi.infrastructure.NetworkInterface; +import cz.cesnet.cloud.occi.infrastructure.StorageLink; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class DataGenerator { + + public static List getMinimalKind() throws URISyntaxException { + List kinds = new ArrayList<>(); + Kind kind = new Kind(new URI("http://schemas.ogf.org/occi/core#"), "entity"); + kind.setLocation(new URI("/entity/")); + kinds.add(kind); + + return kinds; + } + + public static List getFiveKinds() throws URISyntaxException { + Set attributes = new HashSet<>(); + List kinds = new ArrayList<>(); + + Attribute a = new Attribute("occi.core.id"); + attributes.add(a); + a = new Attribute("occi.core.title"); + attributes.add(a); + Kind entity = new Kind(new URI("http://schemas.ogf.org/occi/core#"), "entity", "Entity", new URI("/entity/"), attributes); + kinds.add(entity); + + attributes.clear(); + a = new Attribute("occi.core.summary"); + attributes.add(a); + Kind resource = new Kind(new URI("http://schemas.ogf.org/occi/core#"), "resource", "Resource", new URI("/resource/"), attributes); + resource.addRelation(entity); + resource.setParentKind(entity); + kinds.add(resource); + + attributes.clear(); + a = new Attribute("occi.core.target"); + attributes.add(a); + a = new Attribute("occi.core.source"); + attributes.add(a); + Kind link = new Kind(new URI("http://schemas.ogf.org/occi/core#"), "link", "Link", new URI("/link/"), attributes); + link.addRelation(entity); + link.setParentKind(entity); + kinds.add(link); + + attributes.clear(); + a = new Attribute("occi.compute.architecture", false, true); + attributes.add(a); + a = new Attribute("occi.compute.cores"); + attributes.add(a); + a = new Attribute("occi.compute.hostname"); + attributes.add(a); + a = new Attribute("occi.compute.speed"); + attributes.add(a); + a = new Attribute("occi.compute.memory"); + attributes.add(a); + a = new Attribute("occi.compute.state"); + attributes.add(a); + Kind k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "compute", "Compute Resource", new URI("/compute/"), attributes); + Action ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + k.addAction(ac); + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop"); + k.addAction(ac); + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "restart"); + k.addAction(ac); + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "suspend"); + k.addAction(ac); + k.addRelation(resource); + k.setParentKind(resource); + kinds.add(k); + + attributes.clear(); + a = new Attribute("occi.storagelink.deviceid", true, false); + attributes.add(a); + a = new Attribute("occi.storagelink.mountpoint"); + attributes.add(a); + a = new Attribute("occi.storagelink.state", true, true); + attributes.add(a); + k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "storagelink", "Storage Link", new URI("/storagelink/"), attributes); + k.addRelation(link); + k.setParentKind(link); + kinds.add(k); + + return kinds; + } + + public static List getMinimalMixin() throws URISyntaxException { + List mixins = new ArrayList<>(); + Mixin ostpl = new Mixin(new URI("http://schemas.ogf.org/occi/infrastructure#"), "os_tpl"); + ostpl.setLocation(new URI("/mixins/os_tpl/")); + mixins.add(ostpl); + + return mixins; + } + + public static List getFiveMixins() throws URISyntaxException { + Set attributes = new HashSet<>(); + List mixins = new ArrayList<>(); + + Mixin ostpl = new Mixin(new URI("http://schemas.ogf.org/occi/infrastructure#"), "os_tpl", "Operating System Template", new URI("/mixins/os_tpl/"), attributes); + mixins.add(ostpl); + + attributes.clear(); + Attribute a = new Attribute("occi.network.address", true, false); + attributes.add(a); + a = new Attribute("occi.network.gateway"); + attributes.add(a); + a = new Attribute("occi.network.allocation"); + attributes.add(a); + a = new Attribute("occi.network.state"); + attributes.add(a); + Mixin m = new Mixin(new URI("http://schemas.ogf.org/occi/infrastructure/network#"), "ipnetwork", "IP Network Mixin", new URI("/mixins/ipnetwork/"), attributes); + mixins.add(m); + + attributes.clear(); + Mixin resourcetpl = new Mixin(new URI("http://schemas.ogf.org/occi/infrastructure#"), "resource_tpl", "Resource Template", new URI("/mixins/resource_tpl/"), attributes); + mixins.add(resourcetpl); + + attributes.clear(); + a = new Attribute("occi.compute.architecture"); + attributes.add(a); + a = new Attribute("occi.compute.cores", true, true); + attributes.add(a); + a = new Attribute("occi.compute.speed"); + attributes.add(a); + a = new Attribute("occi.compute.memory", false, true); + attributes.add(a); + m = new Mixin(new URI("https://occi.localhost/occi/infrastructure/resource_tpl#"), "larger", "Larger Instance - 4 cores and 10 GB of RAM", new URI("/mixins/larger/"), attributes); + m.addRelation(resourcetpl); + mixins.add(m); + + attributes.clear(); + m = new Mixin(new URI("https://occi.localhost/occi/infrastructure/os_tpl#"), "debianvm", "debianvm", new URI("/mixins/debianvm/"), attributes); + m.addRelation(ostpl); + mixins.add(m); + + return mixins; + } + + public static List getMinimalAction() throws URISyntaxException { + List actions = new ArrayList<>(); + Action ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/network/action#"), "up"); + actions.add(ac); + + return actions; + } + + public static List getFiveActions() throws URISyntaxException { + List actions = new ArrayList<>(); + Set attributes = new HashSet<>(); + + attributes.clear(); + Attribute a = new Attribute("method"); + attributes.add(a); + Action ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "restart", "Restart Compute instance", attributes); + actions.add(ac); + + attributes.clear(); + a = new Attribute("method"); + attributes.add(a); + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "suspend", "Suspend Compute instance", attributes); + actions.add(ac); + + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/network/action#"), "up", "Activate network", null); + actions.add(ac); + + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/network/action#"), "down", "Deactivate network", null); + actions.add(ac); + + ac = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/storage/action#"), "backup", "Backup Storage", null); + actions.add(ac); + + return actions; + } + + public static List getLocations() throws URISyntaxException { + List locations = new ArrayList<>(); + locations.add(new URI("http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9")); + locations.add(new URI("http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360")); + locations.add(new URI("http://rocci-server-1-1-x.herokuapp.com:80/compute/509afbd3-abff-427c-9b25-7913d17e5102")); + + return locations; + } + + public static Resource getResource() throws InvalidAttributeValueException, URISyntaxException { + Kind k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "compute", "compute resource", new URI("/compute/"), null); + Resource r = new Resource("87f3bfc3-42d4-4474-b45c-757e55e093e9", k); + r.setTitle("compute1"); + r.addAttribute(Compute.ARCHITECTURE_ATTRIBUTE_NAME, "x86"); + r.addAttribute(Compute.HOSTNAME_ATTRIBUTE_NAME, "compute1.example.org"); + r.addAttribute(Compute.MEMORY_ATTRIBUTE_NAME, "1.7"); + r.addAttribute(Compute.SPEED_ATTRIBUTE_NAME, "1.0"); + r.addAttribute(Compute.STATE_ATTRIBUTE_NAME, "active"); + + List mixins = getFiveMixins(); + for (Mixin mixin : mixins) { + r.addMixin(mixin); + } + + List links = getLinks(); + for (Link link : links) { + link.setSource(r); + r.addLink(link); + } + + List actions = getActions(); + for (Action action : actions) { + r.addAction(action); + } + + return r; + } + + public static List getActions() throws URISyntaxException { + List actions = new ArrayList<>(); + actions.add(new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start")); + actions.add(new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop")); + + return actions; + } + + public static List getLinks() throws URISyntaxException, InvalidAttributeValueException { + List links = new ArrayList<>(); + + Kind k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "networkinterface", null, new URI("/link/networkinterface/"), null); + Link l = new Link("456", k); + l.addAttribute(NetworkInterface.INTERFACE_ATTRIBUTE_NAME, "eth0"); + l.addAttribute(NetworkInterface.MAC_ATTRIBUTE_NAME, "00:11:22:33:44:55"); + l.addAttribute(NetworkInterface.STATE_ATTRIBUTE_NAME, "active"); + l.setTarget("/network/123"); + l.setRelation("http://schemas.ogf.org/occi/infrastructure#network"); + links.add(l); + + k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "storagelink", null, new URI("/link/storagelink/"), null); + l = new Link("789", k); + l.addAttribute(StorageLink.DEVICE_ID_ATTRIBUTE_NAME, "1234qwerty"); + l.addAttribute(StorageLink.MOUNTPOINT_ATTRIBUTE_NAME, "/mnt/somewhere/"); + l.addAttribute(StorageLink.STATE_ATTRIBUTE_NAME, "active"); + l.setTarget("/storage/852"); + l.setRelation("http://schemas.ogf.org/occi/infrastructure#storage"); + + Mixin m = new Mixin(new URI("http://opennebula.org/occi/infrastructure#"), "storagelink"); + l.addMixin(m); + + links.add(l); + + return links; + } + + public static Link getLink() throws InvalidAttributeValueException, URISyntaxException { + Kind k = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure#"), "networkinterface", null, null, null); + Link l = new Link("87f3bfc3-42d4-4474-b45c-757e55e093e9", k); + l.addAttribute(NetworkInterface.INTERFACE_ATTRIBUTE_NAME, "eth0"); + l.addAttribute(NetworkInterface.MAC_ATTRIBUTE_NAME, "00:11:22:33:44:55"); + l.addAttribute(NetworkInterface.STATE_ATTRIBUTE_NAME, "active"); + l.setSource("/vms/foo/vm1"); + l.setTarget("/network/123"); + + List mixins = getFiveMixins(); + for (Mixin mixin : mixins) { + l.addMixin(mixin); + } + + return l; + } + + public static ActionInstance getAction() throws InvalidAttributeValueException, URISyntaxException { + Action a = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/storage/action#"), "backup", "Backup Storage", null); + ActionInstance ai = new ActionInstance(a); + ai.addAttribute(new Attribute(Entity.ID_ATTRIBUTE_NAME), "87f3bfc3-42d4-4474-b45c-757e55e093e9"); + ai.addAttribute(new Attribute(NetworkInterface.INTERFACE_ATTRIBUTE_NAME), "eth0"); + ai.addAttribute(new Attribute(NetworkInterface.MAC_ATTRIBUTE_NAME), "00:11:22:33:44:55"); + ai.addAttribute(new Attribute(NetworkInterface.STATE_ATTRIBUTE_NAME), "active"); + ai.addAttribute(new Attribute(Link.SOURCE_ATTRIBUTE_NAME), "/vms/foo/vm1"); + ai.addAttribute(new Attribute(Link.TARGET_ATTRIBUTE_NAME), "/network/123"); + + return ai; + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/ModelTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/ModelTest.java new file mode 100644 index 0000000..b006158 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/ModelTest.java @@ -0,0 +1,252 @@ +package cz.cesnet.cloud.occi; + +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.exception.AmbiguousIdentifierException; +import cz.cesnet.cloud.occi.parser.CollectionType; +import java.net.URI; +import static java.util.Collections.list; +import java.util.HashSet; +import java.util.Set; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; +import org.junit.Before; +import org.junit.Test; + +public class ModelTest { + + private Model model; + + public ModelTest() { + } + + @Before + public void setUp() throws Exception { + model = new Model(); + + for (Kind kind : DataGenerator.getFiveKinds()) { + model.addKind(kind); + } + + for (Mixin mixin : DataGenerator.getFiveMixins()) { + model.addMixin(mixin); + } + + for (Action action : DataGenerator.getFiveActions()) { + model.addAction(action); + } + } + + @Test + public void testFindKindWithURI() throws Exception { + assertEquals(DataGenerator.getFiveKinds().get(2), model.findKind(URI.create("http://schemas.ogf.org/occi/core#link"))); + assertNull(model.findKind(URI.create("http://nonexisting.abc.org/icco/core#link"))); + } + + @Test + public void testFindKindWithString() throws Exception { + assertEquals(DataGenerator.getFiveKinds().get(2), model.findKind("link")); + assertNull(model.findKind("nonexisting")); + } + + @Test + public void testInvalidFindKindWithString() throws Exception { + Kind link = new Kind(new URI("http://different.uri.same/term/core#"), "link", "Link", new URI("/link/"), null); + model.addKind(link); + + try { + model.findKind("link"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindRelatedKindsWithURI() throws Exception { + Set set = new HashSet<>(); + set.add(DataGenerator.getFiveKinds().get(1)); + set.add(DataGenerator.getFiveKinds().get(2)); + + assertEquals(set, new HashSet(model.findRelatedKinds(URI.create("http://schemas.ogf.org/occi/core#entity")))); + } + + @Test + public void testFindRelatedKindsWithString() throws Exception { + Set set = new HashSet<>(); + set.add(DataGenerator.getFiveKinds().get(1)); + set.add(DataGenerator.getFiveKinds().get(2)); + + assertEquals(set, new HashSet(model.findRelatedKinds("entity"))); + } + + @Test + public void testInvalidFindRelatedKindsWithString() throws Exception { + Kind kind = new Kind(new URI("http://different.uri.same/term/core#"), "entity", "Entity", new URI("/entity/"), null); + model.addKind(kind); + + try { + model.findRelatedKinds("entity"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindKindTypeWithKind() throws Exception { + assertNull(model.findKindType(DataGenerator.getFiveKinds().get(0))); + assertEquals(CollectionType.RESOURCE, model.findKindType(DataGenerator.getFiveKinds().get(1))); + assertEquals(CollectionType.LINK, model.findKindType(DataGenerator.getFiveKinds().get(2))); + assertEquals(CollectionType.RESOURCE, model.findKindType(DataGenerator.getFiveKinds().get(3))); + assertEquals(CollectionType.LINK, model.findKindType(DataGenerator.getFiveKinds().get(4))); + } + + @Test + public void testFindKindTypeWithString() throws Exception { + assertNull(model.findKindType("/entity/")); + assertEquals(CollectionType.RESOURCE, model.findKindType("/resource/")); + assertEquals(CollectionType.LINK, model.findKindType("/link/")); + assertEquals(CollectionType.RESOURCE, model.findKindType("/compute/")); + assertEquals(CollectionType.LINK, model.findKindType("/storagelink/")); + } + + @Test + public void testFindMixinWithURI() throws Exception { + assertEquals(DataGenerator.getFiveMixins().get(2), model.findMixin(URI.create("http://schemas.ogf.org/occi/infrastructure#resource_tpl"))); + assertNull(model.findMixin(URI.create("http://nonexisting.abc.org/icco/core#mixin"))); + } + + @Test + public void testFindMixinWithString() throws Exception { + assertEquals(DataGenerator.getFiveMixins().get(2), model.findMixin("resource_tpl")); + assertNull(model.findMixin("nonexisting")); + } + + @Test + public void testInvalidFindMixinWithString() throws Exception { + Mixin resourcetpl = new Mixin(new URI("http://different.uri.same/term/core#"), "resource_tpl", "Resource Template", new URI("/mixins/resource_tpl/"), null); + model.addMixin(resourcetpl); + + try { + model.findMixin("resource_tpl"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindMixinWithStringAndString() throws Exception { + assertEquals(DataGenerator.getFiveMixins().get(3), model.findMixin("larger", "resource_tpl")); + assertNull(model.findMixin("larger", "nonexisting")); + assertNull(model.findMixin("nonexisting", "resource_tpl")); + } + + @Test + public void testInvalidFindMixinWithStringAndString() throws Exception { + try { + Mixin m = new Mixin(new URI("http://different.uri.same/term/resource_tpl#"), "larger", "Larger Instance - 4 cores and 10 GB of RAM", new URI("/mixins/larger/"), null); + m.addRelation(model.findMixin("resource_tpl")); + model.addMixin(m); + model.findMixin("larger", "resource_tpl"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + + try { + setUp(); + Mixin resourcetpl = new Mixin(new URI("http://different.uri.same/term/core#"), "resource_tpl", "Resource Template", new URI("/mixins/resource_tpl/"), null); + model.addMixin(resourcetpl); + model.findMixin("larger", "resource_tpl"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindMixinWithStringAndURI() throws Exception { + assertEquals(DataGenerator.getFiveMixins().get(3), model.findMixin("larger", URI.create("http://schemas.ogf.org/occi/infrastructure#resource_tpl"))); + assertNull(model.findMixin("larger", URI.create("http://nonexisting.abc.org/icco/core#mixin"))); + assertNull(model.findMixin("nonexisting", URI.create("http://schemas.ogf.org/occi/infrastructure#resource_tpl"))); + } + + @Test + public void testInvalidFindMixinWithStringAndURI() throws Exception { + try { + Mixin m = new Mixin(new URI("http://different.uri.same/term/resource_tpl#"), "larger", "Larger Instance - 4 cores and 10 GB of RAM", new URI("/mixins/larger/"), null); + m.addRelation(model.findMixin("resource_tpl")); + model.addMixin(m); + model.findMixin("larger", "resource_tpl"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindRelatedMixinsWithURI() throws Exception { + Set set = new HashSet<>(); + set.add(DataGenerator.getFiveMixins().get(4)); + Mixin m = new Mixin(new URI("https://occi.localhost/occi/infrastructure/os_tpl#"), "archlinux", "archlinux", new URI("/mixins/archlinux/"), null); + m.addRelation(model.findMixin("os_tpl")); + model.addMixin(m); + set.add(m); + + assertEquals(set, new HashSet(model.findRelatedMixins(URI.create("http://schemas.ogf.org/occi/infrastructure#os_tpl")))); + } + + @Test + public void testFindRelatedMixinsWithString() throws Exception { + Set set = new HashSet<>(); + set.add(DataGenerator.getFiveMixins().get(4)); + Mixin m = new Mixin(new URI("https://occi.localhost/occi/infrastructure/os_tpl#"), "archlinux", "archlinux", new URI("/mixins/archlinux/"), null); + m.addRelation(model.findMixin("os_tpl")); + model.addMixin(m); + set.add(m); + + assertEquals(set, new HashSet(model.findRelatedMixins("os_tpl"))); + } + + @Test + public void testInvalidFindRelatedMixinsWithString() throws Exception { + Mixin mixin = new Mixin(new URI("http://different.uri.same/term/core#"), "os_tpl", "Operating System Template", new URI("/mixins/os_tpl/"), null); + model.addMixin(mixin); + + try { + model.findRelatedMixins("os_tpl"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindActionWithString() throws Exception { + assertEquals(DataGenerator.getFiveActions().get(2), model.findAction("up")); + assertNull(model.findAction("nonexisting")); + } + + @Test + public void testInvalidFindActionWithString() throws Exception { + Action ac = new Action(new URI("http://different.uri.same/term/network/action#"), "up", "Activate network", null); + model.addAction(ac); + + try { + model.findAction("up"); + fail(); + } catch (AmbiguousIdentifierException ex) { + //cool + } + } + + @Test + public void testFindActionWithURI() throws Exception { + assertEquals(DataGenerator.getFiveActions().get(2), model.findAction(URI.create("http://schemas.ogf.org/occi/infrastructure/network/action#up"))); + assertNull(model.findAction(URI.create("http://nonexisting.abc.org/icco/core#action"))); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/TestHelper.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/TestHelper.java new file mode 100644 index 0000000..d2dda36 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/TestHelper.java @@ -0,0 +1,14 @@ +package cz.cesnet.cloud.occi; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class TestHelper { + + public static String readFile(String filename) throws IOException { + File f = new File(filename); + String fileContent = new String(Files.readAllBytes(f.toPath())); + return fileContent; + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/AttributeMapCoverTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/AttributeMapCoverTest.java new file mode 100644 index 0000000..07d775b --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/AttributeMapCoverTest.java @@ -0,0 +1,142 @@ +package cz.cesnet.cloud.occi.collection; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.core.Attribute; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import static org.junit.Assert.*; +import org.junit.Before; + +public class AttributeMapCoverTest { + + private final AttributeMapCover attrMap = new AttributeMapCover(); + + @Before + public void setUp() { + attrMap.add(new Attribute("occi.core.id"), "87f3bfc3-42d4-4474-b45c-757e55e093e9"); + attrMap.add(new Attribute("occi.core.title"), "compute1"); + attrMap.add(new Attribute("occi.compute.architecture"), "x86"); + attrMap.add(new Attribute("occi.compute.hostname"), "compute1.example.org"); + attrMap.add(new Attribute("occi.compute.memory"), "1.7"); + attrMap.add(new Attribute("occi.compute.speed"), "1.0"); + } + + @Test + public void testAdd() { + AttributeMapCover instance = new AttributeMapCover(); + assertEquals(0, instance.size()); + instance.add(new Attribute("name"), "value"); + assertEquals(1, instance.size()); + assertTrue(instance.containsAttribute("name")); + } + + @Test + public void testInvalidAdd() { + AttributeMapCover instance = new AttributeMapCover(); + try { + instance.add(null, "aaa"); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + instance.add(new Attribute("aaa"), null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testRemoveWithAttribute() { + assertEquals(6, attrMap.size()); + attrMap.remove(new Attribute("occi.core.id")); + assertEquals(5, attrMap.size()); + assertFalse(attrMap.containsAttribute("occi.core.id")); + } + + @Test + public void testRemoveWithString() { + assertEquals(6, attrMap.size()); + attrMap.remove("occi.core.id"); + assertEquals(5, attrMap.size()); + assertFalse(attrMap.containsAttribute("occi.core.id")); + } + + @Test + public void testContainsAttributeWithAttribute() { + assertTrue(attrMap.containsAttribute(new Attribute("occi.core.id"))); + assertTrue(attrMap.containsAttribute(new Attribute("occi.compute.architecture"))); + assertFalse(attrMap.containsAttribute(new Attribute("nonexisting_attribute"))); + } + + @Test + public void testContainsAttributeWithString() { + assertTrue(attrMap.containsAttribute("occi.core.id")); + assertTrue(attrMap.containsAttribute("occi.compute.architecture")); + assertFalse(attrMap.containsAttribute("nonexisting_attribute")); + } + + @Test + public void testGetValueWithAttribute() { + assertEquals("compute1", attrMap.getValue(new Attribute("occi.core.title"))); + assertEquals("x86", attrMap.getValue(new Attribute("occi.compute.architecture"))); + assertNull(attrMap.getValue(new Attribute("nonexisting_attribute"))); + } + + @Test + public void testGetValueWithString() { + assertEquals("compute1", attrMap.getValue("occi.core.title")); + assertEquals("x86", attrMap.getValue("occi.compute.architecture")); + assertNull(attrMap.getValue("nonexisting_attribute")); + } + + @Test + public void testGetAttributes() { + Map map = new HashMap<>(); + map.put(new Attribute("occi.core.id"), "87f3bfc3-42d4-4474-b45c-757e55e093e9"); + map.put(new Attribute("occi.core.title"), "compute1"); + map.put(new Attribute("occi.compute.architecture"), "x86"); + map.put(new Attribute("occi.compute.hostname"), "compute1.example.org"); + map.put(new Attribute("occi.compute.memory"), "1.7"); + map.put(new Attribute("occi.compute.speed"), "1.0"); + + assertEquals(map, attrMap.getAttributes()); + } + + @Test + public void testClear() { + assertEquals(6, attrMap.size()); + attrMap.clear(); + assertEquals(0, attrMap.size()); + } + + @Test + public void testToOneLineText() { + String line = "occi.compute.architecture=\"x86\";occi.compute.hostname=\"compute1.example.org\";occi.compute.memory=1.7;occi.compute.speed=1.0;occi.core.id=\"87f3bfc3-42d4-4474-b45c-757e55e093e9\";occi.core.title=\"compute1\";"; + + assertEquals(line, attrMap.toOneLineText()); + } + + @Test + public void testToPrefixText() { + String line = "X-OCCI-Attribute: occi.compute.architecture=\"x86\"\nX-OCCI-Attribute: occi.compute.hostname=\"compute1.example.org\"\nX-OCCI-Attribute: occi.compute.memory=1.7\nX-OCCI-Attribute: occi.compute.speed=1.0\nX-OCCI-Attribute: occi.core.id=\"87f3bfc3-42d4-4474-b45c-757e55e093e9\"\nX-OCCI-Attribute: occi.core.title=\"compute1\""; + + assertEquals(line, attrMap.toPrefixText()); + } + + @Test + public void testToHeaders() { + Headers headers = new Headers(); + headers.add("X-OCCI-Attribute", "occi.compute.architecture=\"x86\""); + headers.add("X-OCCI-Attribute", "occi.compute.hostname=\"compute1.example.org\""); + headers.add("X-OCCI-Attribute", "occi.compute.memory=1.7"); + headers.add("X-OCCI-Attribute", "occi.compute.speed=1.0"); + headers.add("X-OCCI-Attribute", "occi.core.id=\"87f3bfc3-42d4-4474-b45c-757e55e093e9\""); + headers.add("X-OCCI-Attribute", "occi.core.title=\"compute1\""); + + assertEquals(headers, attrMap.toHeaders()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/SetCoverTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/SetCoverTest.java new file mode 100644 index 0000000..01b6709 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/collection/SetCoverTest.java @@ -0,0 +1,132 @@ +package cz.cesnet.cloud.occi.collection; + +import cz.cesnet.cloud.occi.core.Mixin; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.*; +import org.junit.Before; + +public class SetCoverTest { + + private SetCover set = new SetCover<>(); + + @Before + public void setUp() throws Exception { + set.add(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + set.add(new Mixin(new URI("http://dummy.mixin2/"), "term2")); + set.add(new Mixin(new URI("http://dummy.mixin3/"), "term3")); + } + + @Test + public void testContainsWithGenericType() throws Exception { + assertTrue(set.contains(new Mixin(new URI("http://dummy.mixin1/"), "term1"))); + assertFalse(set.contains(new Mixin(new URI("http://nonexisting.mixin/"), "aaa"))); + } + + @Test + public void testContainsWithString() { + assertTrue(set.contains("http://dummy.mixin1/term1")); + assertFalse(set.contains("http://nonexisting.mixin/aaa")); + } + + @Test + public void testAdd() throws Exception { + SetCover set = new SetCover<>(); + assertEquals(0, set.size()); + set.add(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + assertEquals(1, set.size()); + assertTrue(set.contains("http://dummy.mixin1/term1")); + } + + @Test + public void testInvalidAdd() { + try { + set.add(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testAddAll() throws Exception { + List list = new ArrayList<>(); + list.add(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + list.add(new Mixin(new URI("http://dummy.mixin2/"), "term2")); + list.add(new Mixin(new URI("http://dummy.mixin3/"), "term3")); + + SetCover set = new SetCover<>(); + assertEquals(0, set.size()); + set.addAll(list); + assertEquals(3, set.size()); + } + + @Test + public void testInvalidAddAll() throws Exception { + List list = new ArrayList<>(); + list.add(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + list.add(null); + list.add(new Mixin(new URI("http://dummy.mixin3/"), "term3")); + + try { + set.addAll(list); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testGet() throws Exception { + assertEquals(new Mixin(new URI("http://dummy.mixin1/"), "term1"), set.get("http://dummy.mixin1/term1")); + assertNull(set.get("nonexisting_element")); + } + + @Test + public void testRemove() throws Exception { + assertEquals(3, set.size()); + set.remove(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + assertEquals(2, set.size()); + assertFalse(set.contains("http://dummy.mixin1/term1")); + } + + @Test + public void testInvalidRemove() { + try { + set.remove(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testClear() { + assertEquals(3, set.size()); + set.clear(); + assertEquals(0, set.size()); + } + + @Test + public void testGetSet() throws Exception { + Set expected = new HashSet<>(); + expected.add(new Mixin(new URI("http://dummy.mixin1/"), "term1")); + expected.add(new Mixin(new URI("http://dummy.mixin2/"), "term2")); + expected.add(new Mixin(new URI("http://dummy.mixin3/"), "term3")); + + assertEquals(expected, set.getSet()); + } + + @Test + public void testSize() throws Exception { + assertEquals(3, set.size()); + set.add(new Mixin(new URI("http://dummy.mixin4/"), "term4")); + assertEquals(4, set.size()); + set.remove(new Mixin(new URI("http://dummy.mixin2/"), "term2")); + assertEquals(3, set.size()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionInstanceTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionInstanceTest.java new file mode 100644 index 0000000..3b9bc2a --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionInstanceTest.java @@ -0,0 +1,70 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.DataGenerator; +import cz.cesnet.cloud.occi.TestHelper; +import java.io.BufferedReader; +import java.io.FileReader; +import java.net.URI; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ActionInstanceTest { + + private static final String RESOURCE_PATH = "src/test/resources/rendering/text/"; + + @Test + public void testConstructor() throws Exception { + Action action = new Action(new URI("http://dummy.action/"), "term"); + ActionInstance ai = new ActionInstance(action); + assertEquals(action, ai.getAction()); + } + + @Test + public void testInvalidConstructor() { + try { + ActionInstance ai = new ActionInstance(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testInvalidSetAction() throws Exception { + try { + Action action = new Action(new URI("http://dummy.action/"), "term"); + ActionInstance ai = new ActionInstance(action); + ai.setAction(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testToText() throws Exception { + String expected = TestHelper.readFile(RESOURCE_PATH + "action_plain.txt"); + ActionInstance ai = DataGenerator.getAction(); + + assertEquals(expected, ai.toText()); + } + + @Test + public void testToHeaders() throws Exception { + Headers headers = new Headers(); + ActionInstance ai = DataGenerator.getAction(); + + headers.add("Category", TestHelper.readFile(RESOURCE_PATH + "action_headers_category.txt")); + + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "action_headers_attributes.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("X-OCCI-Attribute", line); + line = br.readLine(); + } + } + + assertEquals(headers, ai.toHeaders()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionTest.java new file mode 100644 index 0000000..b87e6ef --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ActionTest.java @@ -0,0 +1,77 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.infrastructure.Compute; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ActionTest { + + @Test + public void testFullConstructor() throws URISyntaxException { + Set attributes = new HashSet<>(); + attributes.add(new Attribute("aaa")); + attributes.add(new Attribute("bbb")); + attributes.add(new Attribute("ccc")); + Action action = new Action(Compute.SCHEME_DEFAULT, "start", "Start", attributes); + + assertEquals(action.getAttributes(), attributes); + assertEquals(action.getScheme(), Compute.SCHEME_DEFAULT); + assertEquals(action.getTerm(), "start"); + assertEquals(action.getTitle(), "Start"); + } + + @Test + public void testMinimalConstructor() throws URISyntaxException { + Action action = new Action(Compute.SCHEME_DEFAULT, "start"); + + assertEquals(action.getScheme(), Compute.SCHEME_DEFAULT); + assertEquals(action.getTerm(), "start"); + } + + @Test + public void testInvalidConstructor() throws URISyntaxException { + try { + Action action = new Action(null, Entity.TERM_DEFAULT); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Action action = new Action(Category.SCHEME_CORE_DEFAULT, null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Action action = new Action(Category.SCHEME_CORE_DEFAULT, ""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testToText() throws Exception { + String expected = "Link: ;rel=\"http://schemas.ogf.org/occi/infrastructure/compute/action#start\";"; + Action action = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + + assertEquals(expected, action.toText("/compute/123")); + } + + @Test + public void testToHeaders() throws Exception { + Headers headers = new Headers(); + headers.add("Link", ";rel=\"http://schemas.ogf.org/occi/infrastructure/compute/action#start\";"); + + Action action = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + + assertEquals(headers, action.toHeaders("/compute/123")); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/AttributeTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/AttributeTest.java new file mode 100644 index 0000000..034f04f --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/AttributeTest.java @@ -0,0 +1,74 @@ +package cz.cesnet.cloud.occi.core; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class AttributeTest { + + @Test + public void testConstructor() { + Attribute a = new Attribute("name", true, false, "type", "pattern", "defaultValue", "description"); + + assertEquals("name", a.getName()); + assertEquals("type", a.getType()); + assertEquals("pattern", a.getPattern()); + assertEquals("defaultValue", a.getDefaultValue()); + assertEquals("description", a.getDescription()); + assertTrue(a.isRequired()); + assertFalse(a.isImmutable()); + + a = new Attribute("name", true, false, "type", null, "defaultValue", "description"); + assertEquals(".*", a.getPattern()); + } + + @Test + public void testInvalidConstructor() { + try { + Attribute a = new Attribute(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Attribute a = new Attribute(""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testInvalidSetName() { + try { + Attribute a = new Attribute("name"); + a.setName(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Attribute a = new Attribute("name"); + a.setName(""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testToText() { + Attribute a = new Attribute("attribute_name"); + assertEquals(a.toText(), "attribute_name"); + + a.setRequired(true); + assertEquals(a.toText(), "attribute_name{required}"); + + a.setImmutable(true); + assertEquals(a.toText(), "attribute_name{required immutable}"); + + a.setRequired(false); + assertEquals(a.toText(), "attribute_name{immutable}"); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/CategoryTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/CategoryTest.java new file mode 100644 index 0000000..db73516 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/CategoryTest.java @@ -0,0 +1,42 @@ +package cz.cesnet.cloud.occi.core; + +import static org.junit.Assert.fail; +import org.junit.Test; +import org.junit.Before; + +public class CategoryTest { + + private Category category; + + @Before + public void setUp() { + category = new Category(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + } + + @Test + public void testInvalidSetTerm() { + try { + category.setTerm(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + category.setTerm(""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testInvalidSetScheme() { + try { + category.setScheme(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/EntityTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/EntityTest.java new file mode 100644 index 0000000..f2bdaed --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/EntityTest.java @@ -0,0 +1,118 @@ +package cz.cesnet.cloud.occi.core; + +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.infrastructure.NetworkInterface; +import org.junit.Test; +import static org.junit.Assert.*; +import org.junit.Before; + +public class EntityTest { + + private Entity entity; + private Kind kind; + private Model model; + private Mixin mixin; + + @Before + public void setUp() throws Exception { + kind = new Kind(Entity.SCHEME_DEFAULT, Entity.TERM_DEFAULT); + mixin = new Mixin(NetworkInterface.SCHEME_DEFAULT, NetworkInterface.TERM_DEFAULT); + model = new Model(); + model.addKind(kind); + entity = new Link("link_id", kind); + } + + @Test + public void testConstructor() throws Exception { + Entity entity = new Link("entity_id", kind, "title", model); + + assertEquals("entity_id", entity.getId()); + assertEquals(kind, entity.getKind()); + assertEquals("title", entity.getTitle()); + assertEquals(model, entity.getModel()); + } + + @Test + public void testInvalidConstructor() throws Exception { + try { + Entity entity = new Link(null, kind, "title", model); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Entity entity = new Link("entity_id", null, "title", model); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testInvalidSetId() throws Exception { + try { + entity.setId(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testInvalidSetKind() throws Exception { + try { + entity.setKind(null); + fail(); + } catch (NullPointerException ex) { + //cool + } + } + + @Test + public void testAddAttribute() throws Exception { + Attribute attrKind = new Attribute("attrKind"); + attrKind.setPattern("xyz"); + kind.addAttribute(attrKind); + Attribute attrMixin = new Attribute("attrMixin"); + attrMixin.setPattern("abc"); + mixin.addAttribute(attrMixin); + entity.addMixin(mixin); + + entity.addAttribute("attrKind", "xyz"); + entity.addAttribute("attrMixin", "abc"); + entity.addAttribute("nonexistingAttribute", "value"); + + assertEquals("xyz", entity.getValue("attrKind")); + assertEquals("xyz", entity.getValue(attrKind)); + assertEquals("abc", entity.getValue("attrMixin")); + assertEquals("abc", entity.getValue(attrMixin)); + assertEquals("value", entity.getValue("nonexistingAttribute")); + } + + @Test + public void testInvalidAddAttribute() { + Attribute attrKind = new Attribute("attrKind"); + attrKind.setPattern("xyz"); + kind.addAttribute(attrKind); + Attribute attrMixin = new Attribute("attrMixin"); + attrMixin.setPattern("abc"); + mixin.addAttribute(attrMixin); + entity.addMixin(mixin); + + try { + entity.addAttribute("attrKind", "abc"); + fail(); + } catch (InvalidAttributeValueException ex) { + //cool + } + + try { + entity.addAttribute("attrMixin", "xyz"); + fail(); + } catch (InvalidAttributeValueException ex) { + //cool + } + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/KindTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/KindTest.java new file mode 100644 index 0000000..b3df037 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/KindTest.java @@ -0,0 +1,171 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.TestHelper; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.*; + +public class KindTest { + + private static final String RESOURCE_PATH = "src/test/resources/rendering/text/"; + + @Test + public void testFullConstructor() throws URISyntaxException { + Set attributes = new HashSet<>(); + attributes.add(new Attribute("aaa")); + attributes.add(new Attribute("bbb")); + attributes.add(new Attribute("ccc")); + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT, "title", new URI("/location/"), attributes); + + assertEquals(kind.getAttributes(), attributes); + assertEquals(kind.getLocation(), new URI("/location/")); + assertEquals(kind.getScheme(), Category.SCHEME_CORE_DEFAULT); + assertEquals(kind.getTerm(), Entity.TERM_DEFAULT); + assertEquals(kind.getTitle(), "title"); + } + + @Test + public void testMinimalConstructor() throws URISyntaxException { + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + + assertEquals(kind.getScheme(), Category.SCHEME_CORE_DEFAULT); + assertEquals(kind.getTerm(), Entity.TERM_DEFAULT); + } + + @Test + public void testInvalidConstructor() throws URISyntaxException { + try { + Kind kind = new Kind(null, Entity.TERM_DEFAULT); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, ""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testToText() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "kind_plain.txt").split("\n"); + Attribute at1 = new Attribute(Entity.ID_ATTRIBUTE_NAME); + Attribute at2 = new Attribute(Entity.TITLE_ATTRIBUTE_NAME); + + Action a1 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + Action a2 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop"); + + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + assertEquals(lines[0], kind.toText()); + + kind.setTitle("Entity"); + assertEquals(lines[1], kind.toText()); + + kind.setTitle(null); + kind.setLocation(new URI("/entity/")); + assertEquals(lines[2], kind.toText()); + + kind.setLocation(null); + kind.addAttribute(at1); + kind.addAttribute(at2); + assertEquals(lines[3], kind.toText()); + + kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + kind.addAction(a1); + kind.addAction(a2); + assertEquals(lines[4], kind.toText()); + + kind.addAttribute(at1); + kind.addAttribute(at2); + kind.setTitle("Entity"); + kind.setLocation(new URI("/entity/")); + assertEquals(lines[5], kind.toText()); + + kind.getAttribute(Entity.ID_ATTRIBUTE_NAME).setRequired(true); + assertEquals(lines[6], kind.toText()); + + kind.getAttribute(Entity.ID_ATTRIBUTE_NAME).setImmutable(true); + assertEquals(lines[7], kind.toText()); + + kind.getAttribute(Entity.TITLE_ATTRIBUTE_NAME).setImmutable(true); + assertEquals(lines[8], kind.toText()); + } + + @Test + public void testToHeaders() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "kind_headers.txt").split("\n"); + Attribute at1 = new Attribute(Entity.ID_ATTRIBUTE_NAME); + Attribute at2 = new Attribute(Entity.TITLE_ATTRIBUTE_NAME); + + Action a1 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + Action a2 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop"); + + Headers headers = new Headers(); + + Kind kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + headers.add("Category", lines[0]); + assertEquals(headers, kind.toHeaders()); + + kind.setTitle("Entity"); + headers.clear(); + headers.add("Category", lines[1]); + assertEquals(headers, kind.toHeaders()); + + kind.setTitle(null); + kind.setLocation(new URI("/entity/")); + headers.clear(); + headers.add("Category", lines[2]); + assertEquals(headers, kind.toHeaders()); + + kind.setLocation(null); + kind.addAttribute(at1); + kind.addAttribute(at2); + headers.clear(); + headers.add("Category", lines[3]); + assertEquals(headers, kind.toHeaders()); + + kind = new Kind(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + kind.addAction(a1); + kind.addAction(a2); + headers.clear(); + headers.add("Category", lines[4]); + assertEquals(headers, kind.toHeaders()); + + kind.addAttribute(at1); + kind.addAttribute(at2); + kind.setTitle("Entity"); + kind.setLocation(new URI("/entity/")); + headers.clear(); + headers.add("Category", lines[5]); + assertEquals(headers, kind.toHeaders()); + + kind.getAttribute(Entity.ID_ATTRIBUTE_NAME).setRequired(true); + headers.clear(); + headers.add("Category", lines[6]); + assertEquals(headers, kind.toHeaders()); + + kind.getAttribute(Entity.ID_ATTRIBUTE_NAME).setImmutable(true); + headers.clear(); + headers.add("Category", lines[7]); + assertEquals(headers, kind.toHeaders()); + + kind.getAttribute(Entity.TITLE_ATTRIBUTE_NAME).setImmutable(true); + headers.clear(); + headers.add("Category", lines[8]); + assertEquals(headers, kind.toHeaders()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/LinkTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/LinkTest.java new file mode 100644 index 0000000..6de3da4 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/LinkTest.java @@ -0,0 +1,156 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.TestHelper; +import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException; +import cz.cesnet.cloud.occi.exception.RenderingException; +import cz.cesnet.cloud.occi.infrastructure.Compute; +import cz.cesnet.cloud.occi.infrastructure.NetworkInterface; +import java.io.BufferedReader; +import java.io.FileReader; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class LinkTest { + + private static final String RESOURCE_PATH = "src/test/resources/rendering/text/"; + + @Test + public void testToText() throws Exception { + String expected = TestHelper.readFile(RESOURCE_PATH + "link_plain.txt"); + Link link = prepareLink(); + + assertEquals(expected, link.toText()); + } + + @Test + public void testToHeaders() throws Exception { + Headers headers = new Headers(); + Link link = prepareLink(); + + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "link_headers_categories.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("Category", line); + line = br.readLine(); + } + } + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "link_headers_attributes.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("X-OCCI-Attribute", line); + line = br.readLine(); + } + } + + assertEquals(headers, link.toHeaders()); + } + + private Link prepareLink() throws Exception { + Kind rel = new Kind(Category.SCHEME_CORE_DEFAULT, Link.TERM_DEFAULT); + Kind kind = new Kind(new URI("http://schemas.ogf.org/occi/infrastructure/compute#"), "console", "Link to the VM's console", new URI("/console/"), null); + kind.addRelation(rel); + + List attributes = new ArrayList<>(); + attributes.add(new Attribute("occi.network.address")); + attributes.add(new Attribute("occi.network.gateway")); + attributes.add(new Attribute("occi.network.allocation")); + attributes.add(new Attribute("occi.network.state")); + Mixin m1 = new Mixin(new URI("http://schemas.ogf.org/occi/infrastructure/network#"), "ipnetwork", "IP Network Mixin", new URI("/mixins/ipnetwork/"), attributes); + Mixin m2 = new Mixin(Category.SCHEME_INFRASTRUCTURE_DEFAULT, "os_tpl", "Operating System Template", new URI("/mixins/os_tpl/"), null); + Mixin m3 = new Mixin(Category.SCHEME_INFRASTRUCTURE_DEFAULT, "resource_tpl", "Resource Template", new URI("/mixins/resource_tpl/"), null); + + Link link = new Link("87f3bfc3-42d4-4474-b45c-757e55e093e9", kind, "compute1", null); + link.addMixin(m1); + link.addMixin(m2); + link.addMixin(m3); + link.addAttribute(Compute.ARCHITECTURE_ATTRIBUTE_NAME, "x86"); + link.addAttribute(Compute.HOSTNAME_ATTRIBUTE_NAME, "compute1.example.org"); + link.addAttribute(Compute.MEMORY_ATTRIBUTE_NAME, "1.7"); + link.addAttribute(Compute.SPEED_ATTRIBUTE_NAME, "1.0"); + link.addAttribute(Compute.STATE_ATTRIBUTE_NAME, "active"); + + return link; + } + + @Test + public void testToInlineText() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "inline_link_plain.txt").split("\n"); + + Kind kind = new Kind(NetworkInterface.SCHEME_DEFAULT, NetworkInterface.TERM_DEFAULT); + Link link = new Link("456", kind); + link.setRelation("http://schemas.ogf.org/occi/infrastructure#network"); + link.setTarget("/network/123"); + assertEquals(lines[0], link.toInlineText()); + + link.getKind().setLocation(new URI("/link/networkinterface/")); + assertEquals(lines[1], link.toInlineText()); + + link.getKind().setLocation(null); + link.addAttribute("occi.networkinterface.interface", "eth0"); + link.addAttribute("occi.networkinterface.mac", "00:11:22:33:44:55"); + link.addAttribute("occi.networkinterface.state", "active"); + assertEquals(lines[2], link.toInlineText()); + + link.getKind().setLocation(new URI("/link/networkinterface/")); + assertEquals(lines[3], link.toInlineText()); + } + + @Test + public void testToInlineHeaders() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "inline_link_headers.txt").split("\n"); + Headers headers = new Headers(); + + Kind kind = new Kind(NetworkInterface.SCHEME_DEFAULT, NetworkInterface.TERM_DEFAULT); + Link link = new Link("456", kind); + link.setRelation("http://schemas.ogf.org/occi/infrastructure#network"); + link.setTarget("/network/123"); + headers.add("Link", lines[0]); + assertEquals(headers, link.toInlineHeaders()); + + link.getKind().setLocation(new URI("/link/networkinterface/")); + headers.clear(); + headers.add("Link", lines[1]); + assertEquals(headers, link.toInlineHeaders()); + + link.getKind().setLocation(null); + link.addAttribute("occi.networkinterface.interface", "eth0"); + link.addAttribute("occi.networkinterface.mac", "00:11:22:33:44:55"); + link.addAttribute("occi.networkinterface.state", "active"); + headers.clear(); + headers.add("Link", lines[2]); + assertEquals(headers, link.toInlineHeaders()); + + link.getKind().setLocation(new URI("/link/networkinterface/")); + headers.clear(); + headers.add("Link", lines[3]); + assertEquals(headers, link.toInlineHeaders()); + } + + @Test + public void testInvalidToInlineText() throws InvalidAttributeValueException { + try { + Kind kind = new Kind(NetworkInterface.SCHEME_DEFAULT, NetworkInterface.TERM_DEFAULT); + Link link = new Link("456", kind); + link.setRelation("http://schemas.ogf.org/occi/infrastructure#network"); + link.toInlineText(); + fail(); + } catch (RenderingException ex) { + //cool + } + + try { + Kind kind = new Kind(NetworkInterface.SCHEME_DEFAULT, NetworkInterface.TERM_DEFAULT); + Link link = new Link("456", kind); + link.setTarget("/network/123"); + link.toInlineText(); + fail(); + } catch (RenderingException ex) { + //cool + } + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/MixinTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/MixinTest.java new file mode 100644 index 0000000..769caad --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/MixinTest.java @@ -0,0 +1,166 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.TestHelper; +import cz.cesnet.cloud.occi.infrastructure.IPNetwork; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.*; + +public class MixinTest { + + private static final String RESOURCE_PATH = "src/test/resources/rendering/text/"; + + @Test + public void testFullConstructor() throws URISyntaxException { + Set attributes = new HashSet<>(); + attributes.add(new Attribute("aaa")); + attributes.add(new Attribute("bbb")); + attributes.add(new Attribute("ccc")); + Mixin mixin = new Mixin(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT, "title", new URI("/location/"), attributes); + + assertEquals(mixin.getAttributes(), attributes); + assertEquals(mixin.getLocation(), new URI("/location/")); + assertEquals(mixin.getScheme(), Category.SCHEME_CORE_DEFAULT); + assertEquals(mixin.getTerm(), Entity.TERM_DEFAULT); + assertEquals(mixin.getTitle(), "title"); + } + + @Test + public void testMinimalConstructor() throws URISyntaxException { + Mixin mixin = new Mixin(Category.SCHEME_CORE_DEFAULT, Entity.TERM_DEFAULT); + + assertEquals(mixin.getScheme(), Category.SCHEME_CORE_DEFAULT); + assertEquals(mixin.getTerm(), Entity.TERM_DEFAULT); + } + + @Test + public void testInvalidConstructor() throws URISyntaxException { + try { + Mixin mixin = new Mixin(null, Entity.TERM_DEFAULT); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Mixin mixin = new Mixin(Category.SCHEME_CORE_DEFAULT, null); + fail(); + } catch (NullPointerException ex) { + //cool + } + + try { + Mixin mixin = new Mixin(Category.SCHEME_CORE_DEFAULT, ""); + fail(); + } catch (IllegalArgumentException ex) { + //cool + } + } + + @Test + public void testToText() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "mixin_plain.txt").split("\n"); + Attribute at1 = new Attribute(IPNetwork.ADDRESS_ATTRIBUTE_NAME); + Attribute at2 = new Attribute(IPNetwork.GATEWAY_ATTRIBUTE_NAME); + Attribute at3 = new Attribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME); + Attribute at4 = new Attribute(IPNetwork.STATE_ATTRIBUTE_NAME); + Action a1 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + Action a2 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop"); + + Mixin mixin = new Mixin(IPNetwork.SCHEME_DEFAULT, IPNetwork.TERM_DEFAULT); + assertEquals(mixin.toText(), lines[0]); + + mixin.setTitle("IP Network Mixin"); + assertEquals(mixin.toText(), lines[1]); + + mixin.setTitle(null); + mixin.setLocation(new URI("/mixins/ipnetwork/")); + assertEquals(mixin.toText(), lines[2]); + + mixin.setLocation(null); + mixin.addAttribute(at1); + mixin.addAttribute(at2); + mixin.addAttribute(at3); + mixin.addAttribute(at4); + assertEquals(mixin.toText(), lines[3]); + + mixin = new Mixin(IPNetwork.SCHEME_DEFAULT, IPNetwork.TERM_DEFAULT); + mixin.addAction(a1); + mixin.addAction(a2); + assertEquals(mixin.toText(), lines[4]); + + mixin.addAttribute(at1); + mixin.addAttribute(at2); + mixin.addAttribute(at3); + mixin.addAttribute(at4); + mixin.getAttribute(IPNetwork.ADDRESS_ATTRIBUTE_NAME).setRequired(true); + mixin.getAttribute(IPNetwork.GATEWAY_ATTRIBUTE_NAME).setImmutable(true); + mixin.getAttribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME).setRequired(true); + mixin.getAttribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME).setImmutable(true); + mixin.setTitle("IP Network Mixin"); + mixin.setLocation(new URI("/mixins/ipnetwork/")); + assertEquals(mixin.toText(), lines[5]); + } + + @Test + public void testToHeaders() throws Exception { + String[] lines = TestHelper.readFile(RESOURCE_PATH + "mixin_headers.txt").split("\n"); + Attribute at1 = new Attribute(IPNetwork.ADDRESS_ATTRIBUTE_NAME); + Attribute at2 = new Attribute(IPNetwork.GATEWAY_ATTRIBUTE_NAME); + Attribute at3 = new Attribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME); + Attribute at4 = new Attribute(IPNetwork.STATE_ATTRIBUTE_NAME); + Action a1 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "start"); + Action a2 = new Action(new URI("http://schemas.ogf.org/occi/infrastructure/compute/action#"), "stop"); + + Headers headers = new Headers(); + + Mixin mixin = new Mixin(IPNetwork.SCHEME_DEFAULT, IPNetwork.TERM_DEFAULT); + headers.add("Category", lines[0]); + assertEquals(headers, mixin.toHeaders()); + + mixin.setTitle("IP Network Mixin"); + headers.clear(); + headers.add("Category", lines[1]); + assertEquals(headers, mixin.toHeaders()); + + mixin.setTitle(null); + mixin.setLocation(new URI("/mixins/ipnetwork/")); + headers.clear(); + headers.add("Category", lines[2]); + assertEquals(headers, mixin.toHeaders()); + + mixin.setLocation(null); + mixin.addAttribute(at1); + mixin.addAttribute(at2); + mixin.addAttribute(at3); + mixin.addAttribute(at4); + headers.clear(); + headers.add("Category", lines[3]); + assertEquals(headers, mixin.toHeaders()); + + mixin = new Mixin(IPNetwork.SCHEME_DEFAULT, IPNetwork.TERM_DEFAULT); + mixin.addAction(a1); + mixin.addAction(a2); + headers.clear(); + headers.add("Category", lines[4]); + assertEquals(headers, mixin.toHeaders()); + + mixin.addAttribute(at1); + mixin.addAttribute(at2); + mixin.addAttribute(at3); + mixin.addAttribute(at4); + mixin.getAttribute(IPNetwork.ADDRESS_ATTRIBUTE_NAME).setRequired(true); + mixin.getAttribute(IPNetwork.GATEWAY_ATTRIBUTE_NAME).setImmutable(true); + mixin.getAttribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME).setRequired(true); + mixin.getAttribute(IPNetwork.ALLOCATION_ATTRIBUTE_NAME).setImmutable(true); + mixin.setTitle("IP Network Mixin"); + mixin.setLocation(new URI("/mixins/ipnetwork/")); + headers.clear(); + headers.add("Category", lines[5]); + assertEquals(headers, mixin.toHeaders()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ResourceTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ResourceTest.java new file mode 100644 index 0000000..317000f --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/core/ResourceTest.java @@ -0,0 +1,61 @@ +package cz.cesnet.cloud.occi.core; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.DataGenerator; +import cz.cesnet.cloud.occi.TestHelper; +import java.io.BufferedReader; +import java.io.FileReader; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ResourceTest { + + private static final String RESOURCE_PATH = "src/test/resources/rendering/text/"; + + @Test + public void testToText() throws Exception { + String expected = TestHelper.readFile(RESOURCE_PATH + "resource_plain.txt"); + Resource resource = DataGenerator.getResource(); + + assertEquals(expected, resource.toText()); + } + + @Test + public void testToHeaders() throws Exception { + Headers headers = new Headers(); + Resource resource = DataGenerator.getResource(); + + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "resource_headers_categories.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("Category", line); + line = br.readLine(); + } + } + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "resource_headers_attributes.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("X-OCCI-Attribute", line); + line = br.readLine(); + } + } + try (BufferedReader br = new BufferedReader(new FileReader(RESOURCE_PATH + "resource_headers_links.txt"))) { + String line = br.readLine(); + while (line != null) { + headers.add("Link", line); + line = br.readLine(); + } + } + + for (String name : headers.keySet()) { + System.out.println(name); + System.out.println(headers.get(name)); + } + for (String name : resource.toHeaders().keySet()) { + System.out.println(name); + System.out.println(resource.toHeaders().get(name)); + } + + assertEquals(headers, resource.toHeaders()); + } +} diff --git a/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/parser/TextParserTest.java b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/parser/TextParserTest.java new file mode 100644 index 0000000..43c9f46 --- /dev/null +++ b/jOCCI-core/src/test/java/cz/cesnet/cloud/occi/parser/TextParserTest.java @@ -0,0 +1,1357 @@ +package cz.cesnet.cloud.occi.parser; + +import com.sun.net.httpserver.Headers; +import cz.cesnet.cloud.occi.Collection; +import cz.cesnet.cloud.occi.DataGenerator; +import cz.cesnet.cloud.occi.Model; +import cz.cesnet.cloud.occi.TestHelper; +import cz.cesnet.cloud.occi.core.Action; +import cz.cesnet.cloud.occi.core.ActionInstance; +import cz.cesnet.cloud.occi.core.Attribute; +import cz.cesnet.cloud.occi.core.Kind; +import cz.cesnet.cloud.occi.core.Link; +import cz.cesnet.cloud.occi.core.Mixin; +import cz.cesnet.cloud.occi.core.Resource; +import cz.cesnet.cloud.occi.exception.ParsingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class TextParserTest { + + private static final String RESOURCE_PATH = "src/test/resources/parser/text/"; + + private Model populateModelWithKinds(List kinds, Model initialModel) { + Model model; + if (initialModel == null) { + model = new Model(); + } else { + model = initialModel; + } + + for (Kind k : kinds) { + model.addKind(k); + } + + return model; + } + + private Model populateModelWithMixins(List mixins, Model initialModel) { + Model model; + if (initialModel == null) { + model = new Model(); + } else { + model = initialModel; + } + + for (Mixin k : mixins) { + model.addMixin(k); + } + + return model; + } + + private Model populateModelWithActions(List actions, Model initialModel) { + Model model; + if (initialModel == null) { + model = new Model(); + } else { + model = initialModel; + } + + for (Action k : actions) { + model.addAction(k); + } + + return model; + } + + @Test + public void testParseModelPlainKindsMinimal() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_kinds_minimal.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getMinimalKind(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + } + + @Test + public void testParseModelPlainKindsFull() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_kinds_full.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getFiveKinds(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + } + + @Test + public void testInvalidParseModelPlainKind() { + TextParser instance = new TextParser(); + + //kind without location + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with empty location + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with illegal scheme + try { + String body = "Category: entity;scheme=\"/\\/_)#@564...,p,pkl\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with illegal location + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"/\\/_)#@564...,p,pkl\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelPlainMixinsMinimal() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_mixins_minimal.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithMixins(DataGenerator.getMinimalMixin(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + } + + @Test + public void testParseModelPlainMixinsFull() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_mixins_full.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithMixins(DataGenerator.getFiveMixins(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + } + + @Test + public void testInvalidParseModelPlainMixin() { + TextParser instance = new TextParser(); + //mixin with illegal scheme + try { + String body = "Category: ipnetwork;scheme=\"/\\/_)#@564...,p,pkl\";class=\"mixin\";title=\"IP Network Mixin\";location=\"/mixins/ipnetwork/\";attributes=\"occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelPlainActionsMinimal() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_actions_minimal.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithActions(DataGenerator.getMinimalAction(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testParseModelPlainActionsFull() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_actions_full.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithActions(DataGenerator.getFiveActions(), null); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseModelPlainAction() { + TextParser instance = new TextParser(); + + //action with illegal scheme + try { + String body = "Category: restart;scheme=\"/\\/_)#@564...,p,pkl\";class=\"action\";title=\"Restart Compute instance\";attributes=\"method\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelPlainAll() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "model_plain_all.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getFiveKinds(), null); + expResult = populateModelWithMixins(DataGenerator.getFiveMixins(), expResult); + expResult = populateModelWithActions(DataGenerator.getFiveActions(), expResult); + Model result = instance.parseModel(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseModelPlain() { + TextParser instance = new TextParser(); + + try { + String body = "nonmatching_line"; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without term + try { + String body = "Category: ;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without scheme + try { + String body = "Category: entity;class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with empty scheme + try { + String body = "Category: entity;scheme=\"\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without class + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with empty class + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with unknown class + try { + String body = "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"nonexisting_class\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""; + instance.parseModel(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + + } + + private Headers createDefaultHeaders() { + Headers headers = new Headers(); + headers.add("Status Code", "200 OK"); + headers.add("Cache-Control", "no-cache"); + headers.add("Connection", "keep-alive"); + headers.add("Content-Length", "0"); + headers.add("Content-Type", "text/occi; charset=utf-8"); + headers.add("Date", "Thu, 06 Nov 2014 19:11:38 GMT"); + headers.add("Server", "WEBrick/1.3.1 (Ruby/2.0.0/2014-09-19)"); + headers.add("Via", "1.1 vegur"); + headers.add("X-Frame-Options", "SAMEORIGIN"); + headers.add("X-Request-Id", "3191d404-a8f5-4bda-97d6-1069e71fc418"); + headers.add("X-Runtime", "0.025947"); + headers.add("X-XSS-Protection", "1; mode=block"); + headers.add("x-content-type-options", "nosniff"); + + return headers; + } + + @Test + public void testParseModelOcciKindsMinimal() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_kinds_minimal.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getMinimalKind(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + } + + @Test + public void testParseModelOcciKindsFull() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_kinds_full.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getFiveKinds(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + } + + @Test + public void testInvalidParseModelOcciKind() { + TextParser instance = new TextParser(); + Headers headers = createDefaultHeaders(); + + //kind without location + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with empty location + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with illegal scheme + try { + headers.add("Category", "Category: entity;scheme=\"/\\/_)#@564...,p,pkl\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //kind with illegal location + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"/\\/_)#@564...,p,pkl\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelOcciMixinsMinimal() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_mixins_minimal.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithMixins(DataGenerator.getMinimalMixin(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + } + + @Test + public void testParseModelOcciMixinsFull() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_mixins_full.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithMixins(DataGenerator.getFiveMixins(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + } + + @Test + public void testInvalidParseModelOcciMixin() { + TextParser instance = new TextParser(); + Headers headers = createDefaultHeaders(); + + //mixin with illegal scheme + try { + headers.add("Category", "Category: ipnetwork;scheme=\"/\\/_)#@564...,p,pkl\";class=\"mixin\";title=\"IP Network Mixin\";location=\"/mixins/ipnetwork/\";attributes=\"occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //mixin with illegal location + try { + headers.add("Category", "Category: ipnetwork;scheme=\"http://schemas.ogf.org/occi/infrastructure/network#\";class=\"mixin\";title=\"IP Network Mixin\";location=\"/\\/_)#@564...,p,pkl\";attributes=\"occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelOcciActionsMinimal() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_actions_minimal.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithActions(DataGenerator.getMinimalAction(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testParseModelOcciActionsFull() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_actions_full.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithActions(DataGenerator.getFiveActions(), null); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseModelOcciAction() { + TextParser instance = new TextParser(); + Headers headers = createDefaultHeaders(); + + //action with illegal scheme + try { + headers.add("Category", "Category: restart;scheme=\"/\\/_)#@564...,p,pkl\";class=\"action\";title=\"Restart Compute instance\";attributes=\"method\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseModelOcciAll() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "model_occi_all.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + TextParser instance = new TextParser(); + Model expResult = populateModelWithKinds(DataGenerator.getFiveKinds(), null); + expResult = populateModelWithMixins(DataGenerator.getFiveMixins(), expResult); + expResult = populateModelWithActions(DataGenerator.getFiveActions(), expResult); + Model result = instance.parseModel(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + assertKindsEqual(expResult.getKinds(), result.getKinds()); + assertMixinsEqual(expResult.getMixins(), result.getMixins()); + assertActionsEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseModelOcci() { + TextParser instance = new TextParser(); + Headers headers = createDefaultHeaders(); + + //missing category header + try { + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + try { + headers.add("Category", "nonmatching_line"); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without term + try { + headers.add("Category", "Category: ;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without scheme + try { + headers.add("Category", "Category: entity;class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with empty scheme + try { + headers.add("Category", "Category: entity;scheme=\"\";class=\"kind\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //without class + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with empty class + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + //with unknown class + try { + headers.add("Category", "Category: entity;scheme=\"http://schemas.ogf.org/occi/core#\";class=\"nonexisting_class\";title=\"Entity\";location=\"/entity/\";attributes=\"occi.core.id occi.core.title\""); + instance.parseModel(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + } + + @Test + public void testParseLocationsPlain() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "locations_plain.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + List expResult = DataGenerator.getLocations(); + List result = instance.parseLocations(MediaType.TEXT_PLAIN, body, headers); + assertEquals(expResult, result); + } + + @Test + public void testInvalidParseLocationsPlain() { + TextParser instance = new TextParser(); + String body = "X-OCCI-Location: http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9\n" + + "!@#$%^&||}?:{}|\n" + + "X-OCCI-Location: http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360"; + + try { + instance.parseLocations(MediaType.TEXT_PLAIN, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseLocationsUriList() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "locations_uri-list.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + List expResult = DataGenerator.getLocations(); + List result = instance.parseLocations(MediaType.TEXT_URI_LIST, body, headers); + assertEquals(expResult, result); + } + + @Test + public void testInvalidParseLocationsUriList() { + TextParser instance = new TextParser(); + String body = "http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9\n" + + "!@#$%^&||}?:{}|\n" + + "http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360"; + + try { + instance.parseLocations(MediaType.TEXT_URI_LIST, body, null); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseLocationsOcci() throws Exception { + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Location", "http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9,http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360,http://rocci-server-1-1-x.herokuapp.com:80/compute/509afbd3-abff-427c-9b25-7913d17e5102"); + TextParser instance = new TextParser(); + List expResult = DataGenerator.getLocations(); + List result = instance.parseLocations(MediaType.TEXT_OCCI, body, headers); + assertEquals(expResult, result); + } + + @Test + public void testInvalidParseLocationsOcci() { + TextParser instance = new TextParser(); + Headers headers = createDefaultHeaders(); + + try { + instance.parseLocations(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + + try { + headers.add("Location", "http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9,!@#$%^&||}?:{}|,http://rocci-server-1-1-x.herokuapp.com:80/compute/509afbd3-abff-427c-9b25-7913d17e5102"); + instance.parseLocations(MediaType.TEXT_OCCI, null, headers); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionPlainResource() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "collection_plain_resource.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + + Collection expResult = new Collection(); + expResult.addResource(DataGenerator.getResource()); + Collection result = instance.parseCollection(MediaType.TEXT_PLAIN, body, headers, CollectionType.RESOURCE); + assertEquals(expResult, result); + assertResourcesEqual(expResult.getResources(), result.getResources()); + } + + @Test + public void testInvalidParseCollectionPlainRersource() { + TextParser instance = new TextParser(); + String body; + + try { + body = "no kind specification on the first line"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";location=\"/compute/\";title=\"compute resource\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind scheme + try { + body = "Category: compute;scheme=\"!@#$%^&||}?:{}|\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind location + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"!@#$%^&||}?:{}|\";title=\"compute resource\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Category: os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin scheme + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Category: os_tpl;scheme=\"!@#$%^&||}?:{}|\";class=\"mixin\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin location + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Category: os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"mixin\";title=\"Operating System Template\";location=\"!@#$%^&||}?:{}|\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing action link rel + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Link: "; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid action link relation + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Link: ;rel=\"!@$%^&||}?:{}|\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid link category + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Link: ;rel=\"http://schemas.ogf.org/occi/infrastructure#network\";self=\"/link/networkinterface/456\";category=\"!@$%^&||}?:{}|\";occi.networkinterface.interface=\"eth0\";occi.networkinterface.mac=\"00:11:22:33:44:55\";occi.networkinterface.state=\"active\";"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid link location + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "Link: ;rel=\"http://schemas.ogf.org/occi/infrastructure#network\";self=\"!@$%^&||}?:{}|\";category=\"http://schemas.ogf.org/occi/infrastructure#networkinterface\";occi.networkinterface.interface=\"eth0\";occi.networkinterface.mac=\"00:11:22:33:44:55\";occi.networkinterface.state=\"active\";"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing id attribute + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "X-OCCI-Attribute: occi.core.title=\"compute1\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionPlainLink() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "collection_plain_link.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + + Collection expResult = new Collection(); + expResult.addLink(DataGenerator.getLink()); + Collection result = instance.parseCollection(MediaType.TEXT_PLAIN, body, headers, CollectionType.LINK); + assertEquals(expResult, result); + assertLinksEqual(expResult.getLinks(), result.getLinks()); + } + + @Test + public void testInvalidParseCollectionPlainLink() { + TextParser instance = new TextParser(); + String body; + + try { + body = "no kind specification on the first line"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + body = "Category: networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind scheme + try { + body = "Category: networkinterface;scheme=\"!@$%^&||}?:{}|\";class=\"kind\";"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + body = "Category: networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "Category: os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin scheme + try { + body = "Category: networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "Category: os_tpl;scheme=\"!@#$%^&||}?:{}|\";class=\"mixin\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin location + try { + body = "Category: networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "Category: os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"mixin\";title=\"Operating System Template\";location=\"!@#$%^&||}?:{}|\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing id attribute + try { + body = "Category: compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "X-OCCI-Attribute: occi.networkinterface.interface=\"eth0\";"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionPlainAction() throws Exception { + String body = TestHelper.readFile(RESOURCE_PATH + "collection_plain_action.txt"); + Headers headers = null; + TextParser instance = new TextParser(); + + Collection expResult = new Collection(); + expResult.addAction(DataGenerator.getAction()); + Collection result = instance.parseCollection(MediaType.TEXT_PLAIN, body, headers, CollectionType.ACTION); + assertEquals(expResult, result); + assertActionInstancesEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseCollectionPlainAction() { + TextParser instance = new TextParser(); + String body; + + try { + body = "no action specification on the first line"; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + body = "Category: backup;scheme=\"http://schemas.ogf.org/occi/infrastructure/storage/action#\";class=\"unknown_class\";title=\"Backup Storage\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid action scheme + try { + body = "Category: backup;scheme=\"!@#$%^&||}?:{}|\";class=\"action\";title=\"Backup Storage\""; + instance.parseCollection(MediaType.TEXT_PLAIN, body, null, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionOcciResource() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_resource_category.txt"); + String attributeHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_resource_attribute.txt"); + String linkHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_resource_link.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + headers.add("X-Occi-Attribute", attributeHeader); + headers.add("Link", linkHeader); + TextParser instance = new TextParser(); + Collection expResult = new Collection(); + expResult.addResource(DataGenerator.getResource()); + Collection result = instance.parseCollection(MediaType.TEXT_OCCI, body, headers, CollectionType.RESOURCE); + assertEquals(expResult, result); + assertResourcesEqual(expResult.getResources(), result.getResources()); + } + + @Test + public void testInvalidParseCollectionOcciResource() { + TextParser instance = new TextParser(); + Headers headers = new Headers(); + + try { + headers.add("Category", "no kind specification on the first line"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";location=\"/compute/\";title=\"compute resource\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind scheme + try { + headers.add("Category", "compute;scheme=\"!@#$%^&||}?:{}|\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind location + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"!@#$%^&||}?:{}|\";title=\"compute resource\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin scheme + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"\n" + + "os_tpl;scheme=\"!@#$%^&||}?:{}|\";class=\"mixin\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin location + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\"" + + "os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"mixin\";title=\"Operating System Template\";location=\"!@#$%^&||}?:{}|\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing action link rel + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("Link", ""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid action link relation + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("Link", ";rel=\"!@$%^&||}?:{}|\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid link category + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("Link", ";rel=\"http://schemas.ogf.org/occi/infrastructure#network\";self=\"/link/networkinterface/456\";category=\"!@$%^&||}?:{}|\";occi.networkinterface.interface=\"eth0\";occi.networkinterface.mac=\"00:11:22:33:44:55\";occi.networkinterface.state=\"active\";"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid link location + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("Link", ";rel=\"http://schemas.ogf.org/occi/infrastructure#network\";self=\"!@$%^&||}?:{}|\";category=\"http://schemas.ogf.org/occi/infrastructure#networkinterface\";occi.networkinterface.interface=\"eth0\";occi.networkinterface.mac=\"00:11:22:33:44:55\";occi.networkinterface.state=\"active\";"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing id attribute + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("X-Occi-Attribute", "occi.core.title=\"compute1\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.RESOURCE); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionOcciLink() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_link_category.txt"); + String attributeHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_link_attribute.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + headers.add("X-Occi-Attribute", attributeHeader); + TextParser instance = new TextParser(); + Collection expResult = new Collection(); + expResult.addLink(DataGenerator.getLink()); + Collection result = instance.parseCollection(MediaType.TEXT_OCCI, body, headers, CollectionType.LINK); + assertEquals(expResult, result); + assertLinksEqual(expResult.getLinks(), result.getLinks()); + } + + @Test + public void testInvalidParseCollectionOcciLink() { + TextParser instance = new TextParser(); + Headers headers = new Headers(); + + try { + headers.add("Category", "no kind specification on the first line"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + headers.add("Category", "networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid kind scheme + try { + headers.add("Category", "networkinterface;scheme=\"!@$%^&||}?:{}|\";class=\"kind\";"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + headers.add("Category", "networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"unknown_class\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin scheme + try { + headers.add("Category", "networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "os_tpl;scheme=\"!@#$%^&||}?:{}|\";class=\"mixin\";title=\"Operating System Template\";location=\"/mixins/os_tpl/\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid mixin location + try { + headers.add("Category", "networkinterface;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";\n" + + "os_tpl;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"mixin\";title=\"Operating System Template\";location=\"!@#$%^&||}?:{}|\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + + //missing id attribute + try { + headers.add("Category", "compute;scheme=\"http://schemas.ogf.org/occi/infrastructure#\";class=\"kind\";location=\"/compute/\";title=\"compute resource\""); + headers.add("X-Occi-Attribute", "occi.networkinterface.interface=\"eth0\";"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.LINK); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + @Test + public void testParseCollectionOcciAction() throws Exception { + String categoryHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_action_category.txt"); + String attributeHeader = TestHelper.readFile(RESOURCE_PATH + "collection_occi_action_attribute.txt"); + String body = null; + Headers headers = createDefaultHeaders(); + headers.add("Category", categoryHeader); + headers.add("X-Occi-Attribute", attributeHeader); + TextParser instance = new TextParser(); + Collection expResult = new Collection(); + expResult.addAction(DataGenerator.getAction()); + Collection result = instance.parseCollection(MediaType.TEXT_OCCI, body, headers, CollectionType.ACTION); + assertEquals(expResult, result); + assertActionInstancesEqual(expResult.getActions(), result.getActions()); + } + + @Test + public void testInvalidParseCollectionOcciAction() { + TextParser instance = new TextParser(); + Headers headers = new Headers(); + + try { + headers.add("Category", "no action specification on the first line"); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + + //unknown class + try { + headers.add("Category", "backup;scheme=\"http://schemas.ogf.org/occi/infrastructure/storage/action#\";class=\"unknown_class\";title=\"Backup Storage\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + + //invalid action scheme + try { + headers.add("Category", "backup;scheme=\"!@#$%^&||}?:{}|\";class=\"action\";title=\"Backup Storage\""); + instance.parseCollection(MediaType.TEXT_OCCI, null, headers, CollectionType.ACTION); + fail(); + } catch (ParsingException ex) { + //cool + } + } + + private void assertKindsEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertKindDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertKindDeepEquals(Kind expected, Kind result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertEquals(expected.getTitle(), result.getTitle()); + assertEquals(expected.getLocation(), result.getLocation()); + assertEquals(expected.getRelations(), result.getRelations()); + assertAttributesEqual(expected.getAttributes(), result.getAttributes()); + } + + private void assertMixinsEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertMixinDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertMixinDeepEquals(Mixin expected, Mixin result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertEquals(expected.getTitle(), result.getTitle()); + assertEquals(expected.getLocation(), result.getLocation()); + assertEquals(expected.getRelations(), result.getRelations()); + assertAttributesEqual(expected.getAttributes(), result.getAttributes()); + } + + private void assertActionsEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertActionDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertActionDeepEquals(Action expected, Action result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertEquals(expected.getTitle(), result.getTitle()); + assertAttributesEqual(expected.getAttributes(), result.getAttributes()); + } + + private void assertActionInstancesEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertActionInstanceDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertActionInstanceDeepEquals(ActionInstance expected, ActionInstance result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertActionDeepEquals(expected.getAction(), result.getAction()); + for (Attribute expAttr : expected.getAttributes().keySet()) { + if (!result.getAttributes().containsKey(expAttr)) { + fail(); + } + assertEquals(expected.getAttributes().get(expAttr), result.getAttributes().get(expAttr)); + } + assertEquals(expected.getAttributes(), result.getAttributes()); + } + + private void assertLinksEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + System.out.println("expected links: " + expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + System.out.println("result links: " + resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertLinkDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertLinkDeepEquals(Link expected, Link result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertEquals(expected.getTitle(), result.getTitle()); + assertEquals(expected.getRelation(), result.getRelation()); + assertEquals(expected.getMixins(), result.getMixins()); + assertEquals(expected.getAttributes(), result.getAttributes()); + } + + private void assertResourcesEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertResourceDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertResourceDeepEquals(Resource expected, Resource result) { + System.out.println("comparing " + expected + " with " + result); + assertEquals(expected, result); + + assertEquals(expected.getTitle(), result.getTitle()); + assertEquals(expected.getMixins(), result.getMixins()); + assertEquals(expected.getAttributes(), result.getAttributes()); + assertEquals(expected.getActions(), result.getActions()); + assertLinksEqual(expected.getLinks(), result.getLinks()); + } + + private void assertAttributesEqual(Set expected, Set result) { + assertEquals(expected.size(), result.size()); + + List expectedList = new ArrayList<>(); + expectedList.addAll(expected); + Collections.sort(expectedList); + List resultList = new ArrayList<>(); + resultList.addAll(result); + Collections.sort(resultList); + for (int i = 0; i < expectedList.size(); i++) { + assertAttributeDeepEquals(expectedList.get(i), resultList.get(i)); + } + } + + private void assertAttributeDeepEquals(Attribute expected, Attribute result) { + assertEquals(expected, result); + + assertEquals(expected.isRequired(), result.isRequired()); + assertEquals(expected.isImmutable(), result.isImmutable()); + assertEquals(expected.getType(), result.getType()); + assertEquals(expected.getPattern(), result.getPattern()); + assertEquals(expected.getDefaultValue(), result.getDefaultValue()); + assertEquals(expected.getDescription(), result.getDescription()); + } +} diff --git a/jOCCI-core/src/test/resources/log4j.properties b/jOCCI-core/src/test/resources/log4j.properties new file mode 100644 index 0000000..2fbe356 --- /dev/null +++ b/jOCCI-core/src/test/resources/log4j.properties @@ -0,0 +1,8 @@ +# Root logger option +log4j.rootLogger=DEBUG, stdout + +# Redirect log messages to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_action_attribute.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_action_attribute.txt new file mode 100644 index 0000000..922d0bb --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_action_attribute.txt @@ -0,0 +1 @@ +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9",occi.networkinterface.interface="eth0";,occi.networkinterface.mac="00:11:22:33:44:55";,occi.networkinterface.state="active";,occi.core.source="/vms/foo/vm1",occi.core.target="/network/123" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_action_category.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_action_category.txt new file mode 100644 index 0000000..b85b713 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_action_category.txt @@ -0,0 +1 @@ +backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_link_attribute.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_link_attribute.txt new file mode 100644 index 0000000..8d7b694 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_link_attribute.txt @@ -0,0 +1 @@ +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9",occi.networkinterface.interface="eth0",occi.networkinterface.mac="00:11:22:33:44:55",occi.networkinterface.state="active",occi.core.source="/vms/foo/vm1",occi.core.target="/network/123" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_link_category.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_link_category.txt new file mode 100644 index 0000000..39d4e8a --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_link_category.txt @@ -0,0 +1 @@ +networkinterface;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind",os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/",ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state",resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/",larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}",debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_attribute.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_attribute.txt new file mode 100644 index 0000000..711e772 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_attribute.txt @@ -0,0 +1 @@ +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9",occi.core.title="compute1",occi.compute.architecture="x86",occi.compute.hostname="compute1.example.org",occi.compute.memory=1.7,occi.compute.speed=1.0,occi.compute.state="active" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_category.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_category.txt new file mode 100644 index 0000000..f03b4fb --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_category.txt @@ -0,0 +1 @@ +compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";location="/compute/";title="compute resource",os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/",ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state",resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/",larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}",debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_link.txt b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_link.txt new file mode 100644 index 0000000..e2f6e37 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_occi_resource_link.txt @@ -0,0 +1 @@ +;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active",;rel="http://schemas.ogf.org/occi/infrastructure#storage";self="/link/storagelink/789";category="http://schemas.ogf.org/occi/infrastructure#storagelink http://opennebula.org/occi/infrastructure#storagelink";occi.storagelink.deviceid="1234qwerty"; occi.storagelink.mountpoint="/mnt/somewhere/"; occi.storagelink.state="active",;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#start",;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#stop"; \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_plain_action.txt b/jOCCI-core/src/test/resources/parser/text/collection_plain_action.txt new file mode 100644 index 0000000..97c058f --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_plain_action.txt @@ -0,0 +1,7 @@ +CATEGORY: backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" +X-occi-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.networkinterface.interface="eth0"; +X-oCcI-AtTriBute: occi.networkinterface.mac="00:11:22:33:44:55"; +X-OCCI-Attribute: occi.networkinterface.state="active"; +x-occi-attribute: occi.core.source="/vms/foo/vm1" +X-OCCI-Attribute: occi.core.target="/network/123" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/collection_plain_link.txt b/jOCCI-core/src/test/resources/parser/text/collection_plain_link.txt new file mode 100644 index 0000000..4e76104 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_plain_link.txt @@ -0,0 +1,12 @@ +Category: networkinterface;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind"; +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state" +Category: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/" +Category: larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}" +Category: debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" +X-OCCI-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.networkinterface.interface="eth0"; +X-OCCI-Attribute: occi.networkinterface.mac="00:11:22:33:44:55"; +X-OCCI-Attribute: occi.networkinterface.state="active"; +X-OCCI-Attribute: occi.core.source="/vms/foo/vm1" +X-OCCI-Attribute: occi.core.target="/network/123" diff --git a/jOCCI-core/src/test/resources/parser/text/collection_plain_resource.txt b/jOCCI-core/src/test/resources/parser/text/collection_plain_resource.txt new file mode 100644 index 0000000..f31b61f --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/collection_plain_resource.txt @@ -0,0 +1,17 @@ +Category: compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";location="/compute/";title="compute resource" +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state" +CATEGORY: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/" +category: larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}" +Category: debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" +X-OCCI-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.core.title="compute1" +X-OCCI-Attribute: occi.compute.architecture="x86" +X-OCCI-Attribute: occi.compute.hostname="compute1.example.org" +X-OCCI-Attribute: occi.compute.memory=1.7 +X-OCCI-Attribute: occi.compute.speed=1.0 +X-OCCI-Attribute: occi.compute.state="active" +LINK: ;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; +link: ;rel="http://schemas.ogf.org/occi/infrastructure#storage";self="/link/storagelink/789";category="http://schemas.ogf.org/occi/infrastructure#storagelink http://opennebula.org/occi/infrastructure#storagelink";occi.storagelink.deviceid="1234qwerty"; occi.storagelink.mountpoint="/mnt/somewhere/"; occi.storagelink.state="active"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#start" +Link: ;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#stop" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/locations_plain.txt b/jOCCI-core/src/test/resources/parser/text/locations_plain.txt new file mode 100644 index 0000000..bd51d2b --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/locations_plain.txt @@ -0,0 +1,3 @@ +X-OCCI-Location: http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9 +X-OCCI-Location: http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360 +X-OCCI-Location: http://rocci-server-1-1-x.herokuapp.com:80/compute/509afbd3-abff-427c-9b25-7913d17e5102 \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/locations_uri-list.txt b/jOCCI-core/src/test/resources/parser/text/locations_uri-list.txt new file mode 100644 index 0000000..e6a44d6 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/locations_uri-list.txt @@ -0,0 +1,3 @@ +http://rocci-server-1-1-x.herokuapp.com:80/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9 +http://rocci-server-1-1-x.herokuapp.com:80/compute/17679ebd-975f-4ea0-b42b-47405178c360 +http://rocci-server-1-1-x.herokuapp.com:80/compute/509afbd3-abff-427c-9b25-7913d17e5102 \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_actions_full.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_actions_full.txt new file mode 100644 index 0000000..db89fea --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_actions_full.txt @@ -0,0 +1 @@ +restart;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Restart Compute instance";attributes="method",suspend;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Suspend Compute instance";attributes="method",up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action";title="Activate network",down;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#up";class="action";title="Deactivate network",backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_actions_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_actions_minimal.txt new file mode 100644 index 0000000..b011e1f --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_actions_minimal.txt @@ -0,0 +1 @@ +up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_all.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_all.txt new file mode 100644 index 0000000..c603e9b --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_all.txt @@ -0,0 +1 @@ +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title",resource;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Resource";rel="http://schemas.ogf.org/occi/core#entity";location="/resource/";attributes="occi.core.summary",link;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Link";rel="http://schemas.ogf.org/occi/core#entity";location="/link/";attributes="occi.core.target occi.core.source",compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Compute Resource";rel="http://schemas.ogf.org/occi/core#resource";location="/compute/";attributes="occi.compute.architecture{immutable} occi.compute.cores occi.compute.hostname occi.compute.speed occi.compute.memory occi.compute.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop http://schemas.ogf.org/occi/infrastructure/compute/action#restart http://schemas.ogf.org/occi/infrastructure/compute/action#suspend",storagelink;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Storage Link";rel="http://schemas.ogf.org/occi/core#link";location="/storagelink/";attributes="occi.storagelink.deviceid{required} occi.storagelink.mountpoint occi.storagelink.state{required immutable}",os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/",ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state",resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/",larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}",debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/",restart;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Restart Compute instance";attributes="method",suspend;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Suspend Compute instance";attributes="method",up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action";title="Activate network",down;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#up";class="action";title="Deactivate network",backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_full.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_full.txt new file mode 100644 index 0000000..dd48141 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_full.txt @@ -0,0 +1 @@ +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title",resource;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Resource";rel="http://schemas.ogf.org/occi/core#entity";location="/resource/";attributes="occi.core.summary",link;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Link";rel="http://schemas.ogf.org/occi/core#entity";location="/link/";attributes="occi.core.target occi.core.source",compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Compute Resource";rel="http://schemas.ogf.org/occi/core#resource";location="/compute/";attributes="occi.compute.architecture{immutable} occi.compute.cores occi.compute.hostname occi.compute.speed occi.compute.memory occi.compute.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop http://schemas.ogf.org/occi/infrastructure/compute/action#restart http://schemas.ogf.org/occi/infrastructure/compute/action#suspend",storagelink;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Storage Link";rel="http://schemas.ogf.org/occi/core#link";location="/storagelink/";attributes="occi.storagelink.deviceid{required} occi.storagelink.mountpoint occi.storagelink.state{required immutable}" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_minimal.txt new file mode 100644 index 0000000..b90e322 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_kinds_minimal.txt @@ -0,0 +1 @@ +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";location="/entity/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_full.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_full.txt new file mode 100644 index 0000000..ceef2af --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_full.txt @@ -0,0 +1 @@ +os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/",ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state",resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/",larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}",debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_minimal.txt new file mode 100644 index 0000000..c5d79e7 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_occi_mixins_minimal.txt @@ -0,0 +1 @@ +os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";location="/mixins/os_tpl/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_actions_full.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_actions_full.txt new file mode 100644 index 0000000..3e9d175 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_actions_full.txt @@ -0,0 +1,5 @@ +Category: restart;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Restart Compute instance";attributes="method" +Category: suspend;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Suspend Compute instance";attributes="method" +Category: up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action";title="Activate network" +Category: down;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#up";class="action";title="Deactivate network" +Category: backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_actions_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_actions_minimal.txt new file mode 100644 index 0000000..82a14ba --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_actions_minimal.txt @@ -0,0 +1 @@ +category: up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_all.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_all.txt new file mode 100644 index 0000000..9575383 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_all.txt @@ -0,0 +1,15 @@ +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title" +Category: resource;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Resource";rel="http://schemas.ogf.org/occi/core#entity";location="/resource/";attributes="occi.core.summary" +Category: link;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Link";rel="http://schemas.ogf.org/occi/core#entity";location="/link/";attributes="occi.core.target occi.core.source" +Category: compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Compute Resource";rel="http://schemas.ogf.org/occi/core#resource";location="/compute/";attributes="occi.compute.architecture{immutable} occi.compute.cores occi.compute.hostname occi.compute.speed occi.compute.memory occi.compute.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop http://schemas.ogf.org/occi/infrastructure/compute/action#restart http://schemas.ogf.org/occi/infrastructure/compute/action#suspend" +category: storagelink;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Storage Link";rel="http://schemas.ogf.org/occi/core#link";location="/storagelink/";attributes="occi.storagelink.deviceid{required} occi.storagelink.mountpoint occi.storagelink.state{required immutable}" +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state" +Category: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/" +Category: larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}" +cAtEgOrY: debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" +Category: restart;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Restart Compute instance";attributes="method" +Category: suspend;scheme="http://schemas.ogf.org/occi/infrastructure/compute/action#";class="action";title="Suspend Compute instance";attributes="method" +Category: up;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#";class="action";title="Activate network" +Category: down;scheme="http://schemas.ogf.org/occi/infrastructure/network/action#up";class="action";title="Deactivate network" +Category: backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_full.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_full.txt new file mode 100644 index 0000000..30028df --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_full.txt @@ -0,0 +1,5 @@ +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title" +Category: resource;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Resource";rel="http://schemas.ogf.org/occi/core#entity";location="/resource/";attributes="occi.core.summary" +Category: link;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Link";rel="http://schemas.ogf.org/occi/core#entity";location="/link/";attributes="occi.core.target occi.core.source" +Category: compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Compute Resource";rel="http://schemas.ogf.org/occi/core#resource";location="/compute/";attributes="occi.compute.architecture{immutable} occi.compute.cores occi.compute.hostname occi.compute.speed occi.compute.memory occi.compute.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop http://schemas.ogf.org/occi/infrastructure/compute/action#restart http://schemas.ogf.org/occi/infrastructure/compute/action#suspend" +Category: storagelink;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind";title="Storage Link";rel="http://schemas.ogf.org/occi/core#link";location="/storagelink/";attributes="occi.storagelink.deviceid{required} occi.storagelink.mountpoint occi.storagelink.state{required immutable}" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_minimal.txt new file mode 100644 index 0000000..b0d0133 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_kinds_minimal.txt @@ -0,0 +1 @@ +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";location="/entity/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_full.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_full.txt new file mode 100644 index 0000000..a4e41e7 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_full.txt @@ -0,0 +1,5 @@ +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Operating System Template";location="/mixins/os_tpl/" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.gateway occi.network.allocation occi.network.state" +Category: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";title="Resource Template";location="/mixins/resource_tpl/" +Category: larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin";title="Larger Instance - 4 cores and 10 GB of RAM";rel="http://schemas.ogf.org/occi/infrastructure#resource_tpl";location="/mixins/larger/";attributes="occi.compute.architecture occi.compute.cores{immutable required} occi.compute.speed occi.compute.memory{immutable}" +Category: debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin";title="debianvm";rel="http://schemas.ogf.org/occi/infrastructure#os_tpl";location="/mixins/debianvm/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_minimal.txt b/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_minimal.txt new file mode 100644 index 0000000..7f94506 --- /dev/null +++ b/jOCCI-core/src/test/resources/parser/text/model_plain_mixins_minimal.txt @@ -0,0 +1 @@ +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin";location="/mixins/os_tpl/" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/action_headers_attributes.txt b/jOCCI-core/src/test/resources/rendering/text/action_headers_attributes.txt new file mode 100644 index 0000000..094b686 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/action_headers_attributes.txt @@ -0,0 +1,6 @@ +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +occi.core.source="/vms/foo/vm1" +occi.core.target="/network/123" +occi.networkinterface.interface="eth0" +occi.networkinterface.mac="00:11:22:33:44:55" +occi.networkinterface.state="active" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/action_headers_category.txt b/jOCCI-core/src/test/resources/rendering/text/action_headers_category.txt new file mode 100644 index 0000000..eb854da --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/action_headers_category.txt @@ -0,0 +1 @@ +backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage"; \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/action_plain.txt b/jOCCI-core/src/test/resources/rendering/text/action_plain.txt new file mode 100644 index 0000000..9586333 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/action_plain.txt @@ -0,0 +1,7 @@ +Category: backup;scheme="http://schemas.ogf.org/occi/infrastructure/storage/action#";class="action";title="Backup Storage"; +X-OCCI-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.core.source="/vms/foo/vm1" +X-OCCI-Attribute: occi.core.target="/network/123" +X-OCCI-Attribute: occi.networkinterface.interface="eth0" +X-OCCI-Attribute: occi.networkinterface.mac="00:11:22:33:44:55" +X-OCCI-Attribute: occi.networkinterface.state="active" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/inline_link_headers.txt b/jOCCI-core/src/test/resources/rendering/text/inline_link_headers.txt new file mode 100644 index 0000000..1a1e9d4 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/inline_link_headers.txt @@ -0,0 +1,4 @@ +;rel="http://schemas.ogf.org/occi/infrastructure#network";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123"; +;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123"; +;rel="http://schemas.ogf.org/occi/infrastructure#network";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; +;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; diff --git a/jOCCI-core/src/test/resources/rendering/text/inline_link_plain.txt b/jOCCI-core/src/test/resources/rendering/text/inline_link_plain.txt new file mode 100644 index 0000000..fff7318 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/inline_link_plain.txt @@ -0,0 +1,4 @@ +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#network";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#network";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; diff --git a/jOCCI-core/src/test/resources/rendering/text/kind_headers.txt b/jOCCI-core/src/test/resources/rendering/text/kind_headers.txt new file mode 100644 index 0000000..c4fedf9 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/kind_headers.txt @@ -0,0 +1,9 @@ +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";location="/entity/" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";attributes="occi.core.id occi.core.title" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required} occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required immutable} occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required immutable} occi.core.title{immutable}";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/kind_plain.txt b/jOCCI-core/src/test/resources/rendering/text/kind_plain.txt new file mode 100644 index 0000000..fa790f6 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/kind_plain.txt @@ -0,0 +1,9 @@ +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";location="/entity/" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";attributes="occi.core.id occi.core.title" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required} occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required immutable} occi.core.title";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +Category: entity;scheme="http://schemas.ogf.org/occi/core#";class="kind";title="Entity";location="/entity/";attributes="occi.core.id{required immutable} occi.core.title{immutable}";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/link_headers_attributes.txt b/jOCCI-core/src/test/resources/rendering/text/link_headers_attributes.txt new file mode 100644 index 0000000..67af30e --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/link_headers_attributes.txt @@ -0,0 +1,7 @@ +occi.compute.architecture="x86" +occi.compute.hostname="compute1.example.org" +occi.compute.memory=1.7 +occi.compute.speed=1.0 +occi.compute.state="active" +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +occi.core.title="compute1" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/link_headers_categories.txt b/jOCCI-core/src/test/resources/rendering/text/link_headers_categories.txt new file mode 100644 index 0000000..895b9c2 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/link_headers_categories.txt @@ -0,0 +1,4 @@ +console;scheme="http://schemas.ogf.org/occi/infrastructure/compute#";class="kind" +os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/link_plain.txt b/jOCCI-core/src/test/resources/rendering/text/link_plain.txt new file mode 100644 index 0000000..5a26b2e --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/link_plain.txt @@ -0,0 +1,11 @@ +Category: console;scheme="http://schemas.ogf.org/occi/infrastructure/compute#";class="kind" +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +Category: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" +X-OCCI-Attribute: occi.compute.architecture="x86" +X-OCCI-Attribute: occi.compute.hostname="compute1.example.org" +X-OCCI-Attribute: occi.compute.memory=1.7 +X-OCCI-Attribute: occi.compute.speed=1.0 +X-OCCI-Attribute: occi.compute.state="active" +X-OCCI-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.core.title="compute1" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/mixin_headers.txt b/jOCCI-core/src/test/resources/rendering/text/mixin_headers.txt new file mode 100644 index 0000000..6479bd4 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/mixin_headers.txt @@ -0,0 +1,6 @@ +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";location="/mixins/ipnetwork/" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";attributes="occi.network.address occi.network.allocation occi.network.gateway occi.network.state" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.allocation{required immutable} occi.network.gateway{immutable} occi.network.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/mixin_plain.txt b/jOCCI-core/src/test/resources/rendering/text/mixin_plain.txt new file mode 100644 index 0000000..afb74cc --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/mixin_plain.txt @@ -0,0 +1,6 @@ +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";location="/mixins/ipnetwork/" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";attributes="occi.network.address occi.network.allocation occi.network.gateway occi.network.state" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin";title="IP Network Mixin";location="/mixins/ipnetwork/";attributes="occi.network.address{required} occi.network.allocation{required immutable} occi.network.gateway{immutable} occi.network.state";actions="http://schemas.ogf.org/occi/infrastructure/compute/action#start http://schemas.ogf.org/occi/infrastructure/compute/action#stop" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/resource_headers_attributes.txt b/jOCCI-core/src/test/resources/rendering/text/resource_headers_attributes.txt new file mode 100644 index 0000000..67af30e --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/resource_headers_attributes.txt @@ -0,0 +1,7 @@ +occi.compute.architecture="x86" +occi.compute.hostname="compute1.example.org" +occi.compute.memory=1.7 +occi.compute.speed=1.0 +occi.compute.state="active" +occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +occi.core.title="compute1" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/resource_headers_categories.txt b/jOCCI-core/src/test/resources/rendering/text/resource_headers_categories.txt new file mode 100644 index 0000000..7300378 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/resource_headers_categories.txt @@ -0,0 +1,6 @@ +compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind" +os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" +debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin" +larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin" \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/resource_headers_links.txt b/jOCCI-core/src/test/resources/rendering/text/resource_headers_links.txt new file mode 100644 index 0000000..a973138 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/resource_headers_links.txt @@ -0,0 +1,4 @@ +;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.source="/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9";occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; +;rel="http://schemas.ogf.org/occi/infrastructure#storage";self="/link/storagelink/789";category="http://schemas.ogf.org/occi/infrastructure#storagelink http://opennebula.org/occi/infrastructure#storagelink";occi.core.id=789;occi.core.source="/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9";occi.core.target="/storage/852";occi.storagelink.deviceid="1234qwerty";occi.storagelink.mountpoint="/mnt/somewhere/";occi.storagelink.state="active"; +;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#start"; +;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#stop"; \ No newline at end of file diff --git a/jOCCI-core/src/test/resources/rendering/text/resource_plain.txt b/jOCCI-core/src/test/resources/rendering/text/resource_plain.txt new file mode 100644 index 0000000..9dce174 --- /dev/null +++ b/jOCCI-core/src/test/resources/rendering/text/resource_plain.txt @@ -0,0 +1,17 @@ +Category: compute;scheme="http://schemas.ogf.org/occi/infrastructure#";class="kind" +Category: os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +Category: resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin" +Category: ipnetwork;scheme="http://schemas.ogf.org/occi/infrastructure/network#";class="mixin" +Category: debianvm;scheme="https://occi.localhost/occi/infrastructure/os_tpl#";class="mixin" +Category: larger;scheme="https://occi.localhost/occi/infrastructure/resource_tpl#";class="mixin" +X-OCCI-Attribute: occi.compute.architecture="x86" +X-OCCI-Attribute: occi.compute.hostname="compute1.example.org" +X-OCCI-Attribute: occi.compute.memory=1.7 +X-OCCI-Attribute: occi.compute.speed=1.0 +X-OCCI-Attribute: occi.compute.state="active" +X-OCCI-Attribute: occi.core.id="87f3bfc3-42d4-4474-b45c-757e55e093e9" +X-OCCI-Attribute: occi.core.title="compute1" +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#network";self="/link/networkinterface/456";category="http://schemas.ogf.org/occi/infrastructure#networkinterface";occi.core.id=456;occi.core.source="/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9";occi.core.target="/network/123";occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure#storage";self="/link/storagelink/789";category="http://schemas.ogf.org/occi/infrastructure#storagelink http://opennebula.org/occi/infrastructure#storagelink";occi.core.id=789;occi.core.source="/compute/87f3bfc3-42d4-4474-b45c-757e55e093e9";occi.core.target="/storage/852";occi.storagelink.deviceid="1234qwerty";occi.storagelink.mountpoint="/mnt/somewhere/";occi.storagelink.state="active"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#start"; +Link: ;rel="http://schemas.ogf.org/occi/infrastructure/compute/action#stop"; \ No newline at end of file -- 1.8.2.3