diff --git a/.gitignore b/.gitignore
index 03f837719..73dabe242 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,12 +10,8 @@ hs_err_pid*
# JavaScript
main/src/main/webapp/bower_components
main/src/main/webapp/node_modules
-main/src/main/webapp/app/app.js
-main/src/main/webapp/app/templates.js
-
-# CSS
-main/src/main/webapp/app/style.min.css
-main/src/main/webapp/app/stylesheets/style.css
+main/src/main/webapp/dist
+main/src/main/webapp/tests/coverage
# Auto Generated Swagger Doc
main/src/main/webapp/restdocs/docs
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..db03e88fe
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,191 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+Copyright 2016 TU Dortmund
+
+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.
\ No newline at end of file
diff --git a/README.md b/README.md
index a1ee9591e..b3e436fce 100644
--- a/README.md
+++ b/README.md
@@ -1,72 +1,126 @@
-Automata Learning Experience (ALEX)
-===================================
+
+
+
-Getting Started
----------------
-To build ALEX [Java][], [Maven][], [Node.JS][nodejs] and the [Grunt CLI][grunt] must be installed.
-If all this tools are available, the fastest and easiest way to get started is to run the following commands:
+# ALEX
- # the next line must only be done once!
- mvn install
+Automata Learning Experience (ALEX) is a web application that allows you run automated tests on web applications and JSON-based REST services using Active Automata Learning.
- # start the server
- cd main
- mvn jetty:run
+## How it works
-These commands will download all required dependencies and then build ALEX.
-If the build process was successful and the server has started, ALEX is available
-at [localhost](http://localhost:8080/).
+Let us take a look at the example of an authentication system.
+For an integration test you would probably write tests using Selenium or something else that check the following behavior:
+* register > login > logout _should work_
+* logout _should not work_
+* register > logout _should not work_
+* ...
-Building a Release
-------------------
-To create a release archive please make sure that all requirements are fulfilled and that you can successfully build
-ALEX. If this is the case just run:
+With increasing complexity and feature set of an application, integration tests might be hard to maintain if all possible and impossible combinations of features should be tested.
+With ALEX, we follow a different, more automated approach that
- mvn clean package site
- mvn -P release assembly:single
+1. does not require any knowledge about the implementation of an application,
+2. does not require any experience in programming and
+3. separates the language specific tests from the application to test.
-Afterwards the *ALEX-xxx.tar.gz* and the *ALEX-xxx.tar.zip archive are created in the `target` directory.
+Assume the authentication system mentioned above has the following features: _register_, _login_ and _logout_.
+Then, we model each feature independent of each other using e.g. [Selenium](http://www.seleniumhq.org/).
+In Active Automata Learning, this set of testable features is called **alphabet** where the elements of the alphabet are called **symbols**.
+A sequence of symbols is called a **word**.
+We then pass the learning alphabet to a **learner** that uses specific algorithms to create a model of the underlying application and how it behaves based on the given symbols.
+Therefore, words are executed on the real system under learning and its reactions are observed.
+Finally, the learner creates a **hypothesis** as an output that is modeled as a [Mealy machine](https://en.wikipedia.org/wiki/Mealy_machine).
+In this example, it would hopefully look like this:
-Docker
-------
-Another way to test and / or release ALEX involves the tool [Docker](https://www.docker.com).
-Please make sure that Docker is installed on your machine and that you have the right permissions to use it.
-If this is the case just run:
+![Hypothesis](assets/images/hypothesis.jpg)
- # the next line must only be done once!
- mvn install
-
- cd main
- mvn docker:build
+As it can be seen, the learner has learned the application and all features work as intended.
+From here on, more symbols can be added and learned.
-Afterwards a new Docker image is created and you use it like any other Docker image, e.g.
-
- # lets take a look at all images
- docker images
-
- # run ALEX at http://localhost:8000
- docker run -d -p 8000:8080 alex:1.0-SNAPSHOT
+It can be that the learner has not learned the application correctly, i.e. there is a word in the model that has a different output than the actual application.
+In fact, one can never be a 100% sure if the model actually represents the system under learning.
+How to check for and handle these mistakes is described in the user manual.
-More Documentation
-------------------
-Further documentation is provided through the *site* feature of maven.
-To Create the documentation simply run:
+If you want to know more about Active Automata Learning, you can find some resources at [Google Scholar](https://scholar.google.de/scholar?hl=de&q=active+automata+learning) or the homepage of the [LearnLib](http://learnlib.de/).
- mvn site
+## Installation and first login
-Afterwards the documentation is in the `target/site` folders of every module.
+We developed and tested ALEX using either Windows 8.1 and higher and Linux Ubuntu 14.10 and higher.
+As the application runs on JAVA, any other system with an installed JVM should do fine.
+We also advise to use a modern web browser like Google Chrome >= v46, Mozilla Firefox >= v42 or Microsoft Edge with JavaScript enabled in order to run the front-end properly.
+After the first start, you can login as admin backend using the account below.
-Maintainers
------------
+Email: *admin@alex.example*
+Password: *admin*
-* [Alexander Bainczyk](mailto:alexander.bainczyk@tu-dortmund.de)
-* [Alexander Schieweck](mailto:alexander.schieweck@tu-dortmund.de)
+#### Using the packaged version
+Make sure you have Java 8 installed on your system.
+
+1. Download the latest version from here.
+2. Open a terminal and start the war archive using `java -jar ALEX.war [--port=XXXX]`
+3. Open *http://localhost:8000* in a web browser
+
+#### From source
+
+For the Installation from the source files make sure your system matches the following system requirements:
+
+* Java JDK 8
+* Maven 3
+* Node.js v4.2.* and the NPM
+* Bower `npm install -g bower`
+* Grunt and Grund-Cli `npm install -g grunt grunt-cli`
+
+To install and run ALEX, execute the following commands in a directory of your choice:
+
+1. `git clone https://github.com/LearnLib/alex.git`
+2. `cd alex`
+3. `mvn install [-DskipTests]`
+4. `cd main`
+5. `mvn spring-boot:run [-Dport=XXXX]`
+6. open *http://localhost:8000* in a web browser
+
+## Further reading
+
+* Frontend user manual
+* REST API documentation
+* Screencasts
+* Developer docs
+
+## FAQs
+
+**Is ALEX ready for production use?**
+ALEX has already been used by a class at the TU Dortmund University as a tool to test a student project.
+As far as we are concerned, we used the application to learn applications like Bugzilla and parts of the famous Wordpress.
+
+**Could I potentially learn any available application that is accessible over the internet?**
+Yes, you could, but really should not do that, since testing usually takes a lot of traffic, and your test targets may not like it.
+But we do not programmatically prohibit it either.
+The primary use case is to use ALEX for testing applications that are installed locally or in the same network.
+
+**Do I really not have to have any programming experience?**
+Yes and no, it depends on how you define programming experience.
+We made the best efforts to abstract all necessary steps to test a web application with ease.
+While modelling Selenium tests, it may eventually be helpful to have basic understanding of HTML and CSS.
+The same goes for modelling REST tests where it is needed that you can write JSON documents.
+But to our understanding neither JSON, HTML nor CSS are programming languages.
+
+**How potent does my system have to be to run tests?**
+Learning is a CPU and memory intense process, but we cannot really tell you an lower bound for your system specs.
+From our own observations, it is advised to have at least 2Gb of RAM and a relatively modern Dual Core CPU to run tests at a satisfiable performance.
+The more power your system has, the faster your tests should execute.
+But feel free to test it on your Raspberry PI.
+
+**I want to learn a specific feature of my application but ALEX does not provide a way to model it. What can I do?**
+Initially, we did not develop ALEX as a solution to all situations that may occur in a web application, but to the most common ones.
+If you think a key feature is missing, feel free to submit an issue and we will see what we can do.
+
+*Note: Surprisingly, neither of the above questions have been asked at any point in time. But it it still a neat way to package information that do not fit anywhere else in the documentation.*
[java]: https://java.com
[maven]: https://maven.apache.org
[nodejs]: https://nodejs.org
[grunt]: http://gruntjs.com
+[bower]: http://bower.io
diff --git a/api/pom.xml b/api/pom.xml
index 45557f477..0652392d9 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -7,7 +7,7 @@
de.learnlib.alexalex-parent
- 1.0-SNAPSHOT
+ 1.0../pom.xml
@@ -26,22 +26,4 @@
-
-
-
-
- org.apache.maven.plugins
- maven-project-info-reports-plugin
- ${reports-plugin.version}
-
-
-
- index
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/api/src/main/java/de/learnlib/alex/algorithms/LearnAlgorithmFactory.java b/api/src/main/java/de/learnlib/alex/algorithms/LearnAlgorithmFactory.java
index d0ec3f09e..ff09796a1 100644
--- a/api/src/main/java/de/learnlib/alex/algorithms/LearnAlgorithmFactory.java
+++ b/api/src/main/java/de/learnlib/alex/algorithms/LearnAlgorithmFactory.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.algorithms;
import de.learnlib.api.LearningAlgorithm;
diff --git a/api/src/main/java/de/learnlib/alex/algorithms/package-info.java b/api/src/main/java/de/learnlib/alex/algorithms/package-info.java
index 54d85449f..59b5a4865 100644
--- a/api/src/main/java/de/learnlib/alex/algorithms/package-info.java
+++ b/api/src/main/java/de/learnlib/alex/algorithms/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
/**
* Package that holds the API around algorithms.
*/
diff --git a/api/src/main/java/de/learnlib/alex/annotations/LearnAlgorithm.java b/api/src/main/java/de/learnlib/alex/annotations/LearnAlgorithm.java
index 2690b72f7..8f6c64e10 100644
--- a/api/src/main/java/de/learnlib/alex/annotations/LearnAlgorithm.java
+++ b/api/src/main/java/de/learnlib/alex/annotations/LearnAlgorithm.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.annotations;
/**
diff --git a/api/src/main/java/de/learnlib/alex/annotations/package-info.java b/api/src/main/java/de/learnlib/alex/annotations/package-info.java
index db3ee438b..e9af40ba5 100644
--- a/api/src/main/java/de/learnlib/alex/annotations/package-info.java
+++ b/api/src/main/java/de/learnlib/alex/annotations/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
/**
* Package for all the annotations.
*/
diff --git a/api/src/main/java/de/learnlib/alex/exceptions/LearnerException.java b/api/src/main/java/de/learnlib/alex/exceptions/LearnerException.java
index ab24914a3..aca98c338 100644
--- a/api/src/main/java/de/learnlib/alex/exceptions/LearnerException.java
+++ b/api/src/main/java/de/learnlib/alex/exceptions/LearnerException.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.exceptions;
/**
diff --git a/api/src/main/java/de/learnlib/alex/exceptions/NotFoundException.java b/api/src/main/java/de/learnlib/alex/exceptions/NotFoundException.java
index 99fc06b0e..14148c4e4 100644
--- a/api/src/main/java/de/learnlib/alex/exceptions/NotFoundException.java
+++ b/api/src/main/java/de/learnlib/alex/exceptions/NotFoundException.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.exceptions;
public class NotFoundException extends Exception {
diff --git a/api/src/site/resources/css/bootstrap-responsive.min.css b/api/src/site/resources/css/bootstrap-responsive.min.css
deleted file mode 120000
index a4d199547..000000000
--- a/api/src/site/resources/css/bootstrap-responsive.min.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../src/site/resources/css/bootstrap-responsive.min.css
\ No newline at end of file
diff --git a/api/src/site/resources/css/bootstrap.min.css b/api/src/site/resources/css/bootstrap.min.css
deleted file mode 120000
index 5e3fc7732..000000000
--- a/api/src/site/resources/css/bootstrap.min.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../src/site/resources/css/bootstrap.min.css
\ No newline at end of file
diff --git a/api/src/site/resources/js/bootstrap.min.js b/api/src/site/resources/js/bootstrap.min.js
deleted file mode 120000
index 59bc73727..000000000
--- a/api/src/site/resources/js/bootstrap.min.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../src/site/resources/js/bootstrap.min.js
\ No newline at end of file
diff --git a/api/src/site/site.xml b/api/src/site/site.xml
deleted file mode 100644
index 8e0f9fd4b..000000000
--- a/api/src/site/site.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/assets/images/hypothesis.jpg b/assets/images/hypothesis.jpg
new file mode 100644
index 000000000..a9ca4c14f
Binary files /dev/null and b/assets/images/hypothesis.jpg differ
diff --git a/main/src/main/webapp/app/images/logo.png b/assets/images/logo.png
similarity index 100%
rename from main/src/main/webapp/app/images/logo.png
rename to assets/images/logo.png
diff --git a/main/pom.xml b/main/pom.xml
index ef628498b..2aaca4c4d 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -7,7 +7,7 @@
de.learnlib.alexalex-parent
- 1.0-SNAPSHOT
+ 1.0../pom.xml
@@ -19,6 +19,12 @@
The actual ALEX.
+
+ 1.3.2.RELEASE
+ 2.4.1
+ de.learnlib.alex.App
+
+
@@ -35,18 +41,33 @@
compile
-
- org.glassfish.jersey.containers
- jersey-container-jetty-servlet
- ${jersey.version}
+ org.springframework.boot
+ spring-boot-starter-jersey
+ ${spring-boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring-boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ ${spring-boot.version}
+ provided
+
+
+ org.springframework
+ spring-context
+ 4.2.4.RELEASEorg.hibernatehibernate-core
- 4.3.10.Final
+ 5.0.3.Finalorg.hibernate
@@ -74,16 +95,24 @@
2.3.3
-
org.glassfish.jersey.media
- jersey-media-json-jackson
+ jersey-media-multipart${jersey.version}
+
+
- org.glassfish.jersey.media
- jersey-media-multipart
- ${jersey.version}
+ org.bitbucket.b_c
+ jose4j
+ ${jose4j.version}
+
+
+
+
+ org.apache.shiro
+ shiro-core
+ ${shiro.version}
@@ -151,12 +180,29 @@
org.apache.logging.log4jlog4j-api
- 2.3
+ ${log4j.version}org.apache.logging.log4jlog4j-core
- 2.3
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-jul
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-jcl
+ ${log4j.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring-boot.version}
@@ -191,143 +237,79 @@
src/main/resourcestrue
+
+ src/main/webapp
+
+ **/node_modules/**
+ **/tests/**
+ **/src/**
+ package.json
+ gruntfile.js
+
+
+ **/node_modules/font-awesome/fonts/**
+
+
-
- org.apache.maven.plugins
- maven-compiler-plugin
- ${compiler-plugin.version}
-
-
-
-
-
-
-
-
org.apache.maven.pluginsmaven-war-plugin${war-plugin.version}
+ false
+
+
+ src/main/webapp
+
+ **/node_modules/**
+ **/tests/**
+ **/src/**
+ package.json
+ gruntfile.js
+
+
+ **/node_modules/font-awesome/fonts/**
+
+
+
- **/node_modules/**,
+ **/node_modules/**
+ **/tests/**
+ **/src/**
+ package.json
+ gruntfile.js
-
- app/**,
- index.html,
- img/**,
- restdocs/**,
- WEB-INF/**,
-
+
+ **/node_modules/font-awesome/fonts/**
+
- org.codehaus.mojo
- exec-maven-plugin
- 1.4.0
-
-
- npm-install
- generate-sources
-
- exec
-
-
- npm
- src/main/webapp
-
- install
-
-
-
-
- grunt
- generate-sources
-
- exec
-
-
- grunt
- src/main/webapp
-
-
-
- grunt-css
- generate-sources
-
- exec
-
-
- grunt
-
- build-css
-
- src/main/webapp
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- ${javadoc-plugin.version}
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+ de.learnlib.alex.App
+ false
+
- generate-service-docs
- generate-resources
- javadoc-no-fork
+ repackage
-
- com.carma.swagger.doclet.ServiceDoclet
-
- com.carma
- swagger-doclet
- 1.1.0
-
- ${basedir}/src/main/webapp
- false
- -apiVersion 1 -docBasePath /restdocs/docs -apiBasePath /rest -disableCopySwaggerUi
- restdocs/docs
-
-
-
-
-
- org.eclipse.jetty
- jetty-maven-plugin
- ${jetty.version}
-
-
- org.eclipse.jetty
- jetty-servlets
- ${jetty.version}
-
-
-
- 60
- 8082
- stop
-
-
- start-jetty
+ server-startpre-integration-teststart
-
- true
- 0
-
- stop-jetty
+ server-stoppost-integration-teststop
@@ -344,7 +326,11 @@
alex.dbpath
- mem:integration-test-db
+ mem:test-db
+
+
+ java.util.logging.manager
+ org.apache.logging.log4j.jul.LogManager
@@ -360,6 +346,10 @@
alex.dbpathmem:integration-test-db
+
+ java.util.logging.manager
+ org.apache.logging.log4j.jul.LogManager
+
@@ -397,77 +387,48 @@
-
-
-
-
-
- org.apache.maven.plugins
- maven-project-info-reports-plugin
- ${reports-plugin.version}
-
-
-
- index
-
-
-
-
-
-
-
- default
+ createRestDoctrue
-
-
+
-
org.apache.maven.plugins
- maven-surefire-report-plugin
- ${surefire-report.version}
-
-
-
-
- org.codehaus.mojo
- cobertura-maven-plugin
- ${cobertura.version}
-
-
-
- cobertura
-
-
-
-
-
- html
-
-
- 60
- 60
-
-
+ maven-javadoc-plugin
+ ${javadoc-plugin.version}
+
+
+ generate-service-docs
+ generate-resources
+
+ javadoc-no-fork
+
+
+ com.carma.swagger.doclet.ServiceDoclet
+
+ com.carma
+ swagger-doclet
+ 1.1.1
+
+ ${basedir}/src/main/webapp
+ false
+ -apiVersion 1 -docBasePath /restdocs/docs -apiBasePath /rest -disableCopySwaggerUi
+ restdocs/docs
+
+
+
-
-
-
-
- release
+
- bootstrap-npm
+ createFrontend
-
- src/main/webapp/node_modules
-
+ true
@@ -477,15 +438,17 @@
1.4.0
- npm
- initialize
+ grunt
+ generate-sourcesexec
- npm
+ grunt
- install
+ build-html
+ build-css
+ build-jssrc/main/webapp
@@ -495,11 +458,12 @@
+
- bootstrap-bower
+ bootstrap
- src/main/webapp/bower_components
+ src/main/webapp/node_modules
@@ -510,23 +474,35 @@
1.4.0
- grunt-bower
+ npminitializeexec
- grunt
+ npm
- bower:install
+ installsrc/main/webapp
+
+ grunt
+ generate-sources
+
+ exec
+
+
+ grunt
+ src/main/webapp
+
+
+
diff --git a/main/src/docker/Dockerfile b/main/src/docker/Dockerfile
index badb1754a..8b9eb608f 100644
--- a/main/src/docker/Dockerfile
+++ b/main/src/docker/Dockerfile
@@ -1,5 +1,9 @@
-FROM jetty:9.3
+FROM java:8
-ADD ALEX-*.war /var/lib/jetty/webapps/ROOT.war
+ADD ALEX-*.war /usr/src/alex/ALEX.war
+WORKDIR /usr/src/alex
+
+EXPOSE 8080
+
+ENTRYPOINT ["java", "-jar", "ALEX.war"]
-CMD ["jetty.sh", "run"]
diff --git a/main/src/main/java/de/learnlib/alex/ALEXApplication.java b/main/src/main/java/de/learnlib/alex/ALEXApplication.java
index a07f87936..a181acb57 100644
--- a/main/src/main/java/de/learnlib/alex/ALEXApplication.java
+++ b/main/src/main/java/de/learnlib/alex/ALEXApplication.java
@@ -1,53 +1,94 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex;
-import de.learnlib.alex.core.dao.CounterDAO;
-import de.learnlib.alex.core.dao.CounterDAOImpl;
-import de.learnlib.alex.core.dao.FileDAO;
-import de.learnlib.alex.core.dao.FileDAOImpl;
-import de.learnlib.alex.core.dao.LearnerResultDAO;
-import de.learnlib.alex.core.dao.LearnerResultDAOImpl;
-import de.learnlib.alex.core.dao.ProjectDAO;
-import de.learnlib.alex.core.dao.ProjectDAOImpl;
-import de.learnlib.alex.core.dao.SymbolDAO;
-import de.learnlib.alex.core.dao.SymbolDAOImpl;
-import de.learnlib.alex.core.dao.SymbolGroupDAO;
-import de.learnlib.alex.core.dao.SymbolGroupDAOImpl;
-import de.learnlib.alex.core.learner.Learner;
-import de.learnlib.alex.core.learner.LearnerThreadFactory;
-import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import de.learnlib.alex.core.dao.UserDAO;
+import de.learnlib.alex.core.entities.User;
+import de.learnlib.alex.core.entities.UserRole;
+import de.learnlib.alex.rest.CounterResource;
+import de.learnlib.alex.rest.FileResource;
+import de.learnlib.alex.rest.IFrameProxyResource;
+import de.learnlib.alex.rest.LearnerResource;
+import de.learnlib.alex.rest.LearnerResultResource;
+import de.learnlib.alex.rest.ProjectResource;
+import de.learnlib.alex.rest.SymbolGroupResource;
+import de.learnlib.alex.rest.SymbolResource;
+import de.learnlib.alex.rest.UserResource;
+import de.learnlib.alex.security.AuthenticationFilter;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.ws.rs.ApplicationPath;
/**
* Main class of the REST API. Implements the Jersey {@link ResourceConfig} and does some configuration and stuff.
*/
+@Component
+@ApplicationPath("rest")
public class ALEXApplication extends ResourceConfig {
+ /** The E-Mail for the default admin, i.e. the admin that will be auto created if no other admin exists. */
+ public static final String DEFAULT_ADMIN_EMAIL = "admin@alex.example";
+
+ /** The Password for the default admin, i.e. the admin that will be auto created if no other admin exists. */
+ public static final String DEFAULT_ADMIN_PASSWORD = "admin";
+
+ /** The UserDOA to create an admin if needed. */
+ @Inject
+ private UserDAO userDAO;
+
/**
* Constructor where the magic happens.
*/
public ALEXApplication() {
- // packages with REST resources classes
- packages(true, "de.learnlib.alex");
+ // register REST resources classes
+ register(CounterResource.class);
+ register(FileResource.class);
+ register(IFrameProxyResource.class);
+ register(LearnerResource.class);
+ register(LearnerResultResource.class);
+ register(ProjectResource.class);
+ register(SymbolGroupResource.class);
+ register(SymbolResource.class);
+ register(UserResource.class);
register(MultiPartFeature.class);
+ register(AuthenticationFilter.class);
+ register(RolesAllowedDynamicFeature.class); // allow protecting routes with user roles
+ }
+
+ /**
+ * Create an admin at the start of th ALEX if no admin is currently in the DB.
+ */
+ @PostConstruct
+ public void createAdminIfNeeded() {
+ // create an admin if none exists
+ if (userDAO.getAllByRole(UserRole.ADMIN).size() == 0) {
+ User admin = new User();
+ admin.setEmail(DEFAULT_ADMIN_EMAIL);
+ admin.setRole(UserRole.ADMIN);
+ admin.setEncryptedPassword(DEFAULT_ADMIN_PASSWORD);
- // register some classes/ objects for IoC.
- register(new AbstractBinder() {
- @Override
- protected void configure() {
- LearnerResultDAOImpl learnerResultDAO = new LearnerResultDAOImpl();
- LearnerThreadFactory threadFactory = new LearnerThreadFactory(learnerResultDAO);
-
- bind(ProjectDAOImpl.class).to(ProjectDAO.class);
- bind(CounterDAOImpl.class).to(CounterDAO.class);
- bind(SymbolGroupDAOImpl.class).to(SymbolGroupDAO.class);
- bind(SymbolDAOImpl.class).to(SymbolDAO.class);
- bind(LearnerResultDAOImpl.class).to(LearnerResultDAO.class);
- bind(new Learner(threadFactory)).to(Learner.class);
- bind(FileDAOImpl.class).to(FileDAO.class);
- }
- });
+ userDAO.create(admin);
+ }
}
}
diff --git a/main/src/main/java/de/learnlib/alex/App.java b/main/src/main/java/de/learnlib/alex/App.java
new file mode 100644
index 000000000..1a96baa41
--- /dev/null
+++ b/main/src/main/java/de/learnlib/alex/App.java
@@ -0,0 +1,29 @@
+package de.learnlib.alex;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.web.SpringBootServletInitializer;
+
+/**
+ * The entry point to ALEX.
+ */
+@SpringBootApplication
+public class App extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(App.class);
+ }
+
+ /**
+ * Starts the standalone modus of ALEX.
+ *
+ * @param args
+ * Additional commandline parameters.
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(App.class, args);
+ }
+}
+
diff --git a/main/src/main/java/de/learnlib/alex/actions/ExecuteSymbolAction.java b/main/src/main/java/de/learnlib/alex/actions/ExecuteSymbolAction.java
index a8b27cc33..b0914c05e 100644
--- a/main/src/main/java/de/learnlib/alex/actions/ExecuteSymbolAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/ExecuteSymbolAction.java
@@ -1,13 +1,32 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
+import de.learnlib.alex.core.dao.SymbolDAO;
+import de.learnlib.alex.core.dao.SymbolDAOImpl;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.entities.IdRevisionPair;
import de.learnlib.alex.core.entities.Symbol;
import de.learnlib.alex.core.entities.SymbolAction;
import de.learnlib.alex.core.learner.connectors.ConnectorManager;
+import de.learnlib.alex.exceptions.NotFoundException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -25,14 +44,19 @@
@JsonTypeName("executeSymbol")
public class ExecuteSymbolAction extends SymbolAction {
- /** to be serializable. */
+ /**
+ * to be serializable.
+ */
private static final long serialVersionUID = 3143716533295082498L;
- /** Use the logger for the server part. */
- private static final Logger LOGGER = LogManager.getLogger("server");
+ /**
+ * Use the learner logger.
+ */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
/**
* Reference to the Symbol that will be executed.
+ *
* @requiredField
*/
@Transient
@@ -47,6 +71,11 @@ public class ExecuteSymbolAction extends SymbolAction {
@JsonIgnore
private Symbol symbolToExecute;
+ /**
+ * Indicates if the latest revision of the symbol should be used.
+ */
+ private boolean useLatestRevision;
+
/**
* Get the reference to the Symbol which will be executed.
*
@@ -63,8 +92,7 @@ public IdRevisionPair getSymbolToExecuteAsIdRevisionPair() {
* Set a new reference to the Symbol to execute.
* This does not update the actual Symbol!
*
- * @param symbolToExecuteAsIdRevisionPair
- * The new IdRevisionPair of the Symbol to execute.
+ * @param symbolToExecuteAsIdRevisionPair The new IdRevisionPair of the Symbol to execute.
*/
public void setSymbolToExecuteAsIdRevisionPair(IdRevisionPair symbolToExecuteAsIdRevisionPair) {
this.symbolToExecuteAsIdRevisionPair = symbolToExecuteAsIdRevisionPair;
@@ -104,14 +132,36 @@ public String getSymbolToExecuteName() {
return symbolToExecute.getName();
}
+ /**
+ * Checks if the latest revision of the symbols should be used.
+ *
+ * @return if the latest revision should be used.
+ */
+ public boolean isUseLatestRevision() {
+ return useLatestRevision;
+ }
+
+ /**
+ * Sets the flag that indicates if the latest revision of the symbol should be used.
+ *
+ * @param useLatestRevision the flag
+ */
+ public void setUseLatestRevision(boolean useLatestRevision) {
+ this.useLatestRevision = useLatestRevision;
+ }
+
@Override
public ExecuteResult execute(ConnectorManager connector) {
if (symbolToExecute == null) {
- LOGGER.info("ExecuteSymbolAction.execute: Symbol not found!");
+ LOGGER.info("No other Symbol to execute was set "
+ + "(ignoreFailure : " + ignoreFailure + ", negated: " + negated + ").");
return getFailedOutput();
}
ExecuteResult symbolResult = symbolToExecute.execute(connector);
+ LOGGER.info("Executed other Symbol <" + symbolToExecute.getId() + ":" + symbolToExecute.getRevision() + "> "
+ + " with the result of '" + symbolResult + "' "
+ + "(ignoreFailure : " + ignoreFailure + ", negated: " + negated + ").");
if (symbolResult == ExecuteResult.OK) {
return getSuccessOutput();
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CallAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CallAction.java
index 18141dc90..87eb6d152 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CallAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CallAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -7,6 +23,7 @@
import org.apache.logging.log4j.Logger;
import org.hibernate.validator.constraints.NotBlank;
+import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Lob;
@@ -28,8 +45,8 @@ public class CallAction extends RESTSymbolAction {
/** to be serializable. */
private static final long serialVersionUID = 7971257988991996022L;
- /** Use the logger for the server part. */
- private static final Logger LOGGER = LogManager.getLogger("server");
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
/**
* Enumeration to specify the HTTP method.
@@ -71,8 +88,12 @@ public enum Method {
private HashMap cookies; // OM NOM NOM NOM!!!
/** Optional data to sent with a POST or PUT request. */
+ @Column(columnDefinition = "CLOB")
private String data;
+ /**
+ * Default constructor that just initializes the internal data structures.
+ */
public CallAction() {
this.headers = new HashMap<>();
this.cookies = new HashMap<>();
@@ -221,6 +242,9 @@ public void setData(String data) {
@Override
public ExecuteResult execute(WebServiceConnector target) {
try {
+ LOGGER.info("Do REST request '" + method + " " + url + "' "
+ + "(ignoreFailure : " + ignoreFailure + ", negated: " + negated + ").");
+
doRequest(target);
return getSuccessOutput();
} catch (Exception e) {
@@ -248,7 +272,7 @@ private void doRequest(WebServiceConnector target) {
getCookiesWithVariableValues());
break;
default:
- LOGGER.info("tried to make a call to a REST API with an unknown method '" + method.name() + "'.");
+ LOGGER.warn("tried to make a call to a REST API with an unknown method '" + method.name() + "'.");
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeExistsAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeExistsAction.java
index c5763d649..47fcc4b27 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeExistsAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeExistsAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeTypeAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeTypeAction.java
index 7a712a14e..c5514d4d3 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeTypeAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeTypeAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeValueAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeValueAction.java
index 482b30375..af5803161 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeValueAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckAttributeValueAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckHeaderFieldAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckHeaderFieldAction.java
index 7429d8b6c..40277f4a5 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckHeaderFieldAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckHeaderFieldAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckStatusAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckStatusAction.java
index 2e2957327..7bad87813 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckStatusAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckStatusAction.java
@@ -1,8 +1,26 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.learner.connectors.WebServiceConnector;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@@ -18,6 +36,9 @@ public class CheckStatusAction extends RESTSymbolAction {
/** to be serializable. */
private static final long serialVersionUID = -4444604521120530087L;
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
/** The status code to check. */
private int status;
@@ -42,7 +63,11 @@ public void setStatus(int status) {
@Override
public ExecuteResult execute(WebServiceConnector target) {
- if (status == target.getStatus()) {
+ int returnedStatus = target.getStatus();
+ LOGGER.info("check if the returned status code '" + returnedStatus + " is equal to '" + status + "' "
+ + "(ignoreFailure : " + ignoreFailure + ", negated: " + negated + ").");
+
+ if (this.status == returnedStatus) {
return getSuccessOutput();
} else {
return getFailedOutput();
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckTextRestAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckTextRestAction.java
index ee1f585ff..9646ffa6c 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckTextRestAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/CheckTextRestAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/RESTSymbolAction.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/RESTSymbolAction.java
index 71a10c421..bce97aa06 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/RESTSymbolAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/RESTSymbolAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.RESTSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
diff --git a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/package-info.java b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/package-info.java
index e416f47b8..a80cddf14 100644
--- a/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/package-info.java
+++ b/main/src/main/java/de/learnlib/alex/actions/RESTSymbolActions/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * 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.
+ */
+
/**
* This package contains all concrete implementations around REST Symbols.
*/
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertCounterAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertCounterAction.java
index 69111dd46..662c16c36 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertCounterAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertCounterAction.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.entities.SymbolAction;
@@ -12,18 +29,56 @@
import javax.validation.constraints.NotNull;
/**
- * Action to assert the value of a counter
+ * Action to assert the value of a counter.
*/
@Entity
@DiscriminatorValue("assertCounter")
@JsonTypeName("assertCounter")
public class AssertCounterAction extends SymbolAction {
- // assert types to mimic <, <=, ==, >=, > in this order
- private enum Operator {
- LESS_THAN, LESS_OR_EQUAL, EQUAL, GREATER_OR_EQUAL, GREATER_THAN
+ /**
+ * Assert types to mimic the different operators.
+ */
+ public enum Operator {
+ /** '<'. */
+ LESS_THAN,
+
+ /** '<='. */
+ LESS_OR_EQUAL,
+
+ /** '=='. */
+ EQUAL,
+
+ /** '>='. */
+ GREATER_OR_EQUAL,
+
+ /** '>'. */
+ GREATER_THAN;
+
+ /**
+ * Parser function to handle the enum names case insensitive.
+ *
+ * @param name
+ * The enum name.
+ * @return The corresponding CookieType.
+ * @throws IllegalArgumentException
+ * If the name could not be parsed.
+ */
+ @JsonCreator
+ public static Operator fromString(String name) throws IllegalArgumentException {
+ return Operator.valueOf(name.toUpperCase());
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+
}
+ /** to be serializable. */
+ private static final long serialVersionUID = -8210218030257177422L;
+
/**
* The name of the variable to assert.
*/
@@ -37,15 +92,57 @@ private enum Operator {
private Integer value;
/**
- * The method to compare the counterVariable value with the one given
+ * The method to compare the counterVariable value with the one given.
*/
@NotNull
private Operator operator;
+ /**
+ * @return The name of the counter that will be compared.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name The new name of the counter to compare.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return The value that the counter will be compared with.
+ */
+ public Integer getValue() {
+ return value;
+ }
+
+ /**
+ * @param value The new value to compare the counter with.
+ */
+ public void setValue(Integer value) {
+ this.value = value;
+ }
+
+ /**
+ * @return The current operator to compare the counter with the given value.
+ */
+ public Operator getOperator() {
+ return operator;
+ }
+
+ /**
+ * @param assertMethod Set the new operator to use to compare the counter with the given value.
+ */
+ public void setOperator(Operator assertMethod) {
+ this.operator = assertMethod;
+ }
+
@Override
protected ExecuteResult execute(ConnectorManager connector) {
CounterStoreConnector storeConnector = connector.getConnector(CounterStoreConnector.class);
- Integer counterValue = storeConnector.get(project.getId(), name);
+ Integer counterValue = storeConnector.get(getUser().getId(), project.getId(), name);
boolean result;
switch (operator) {
@@ -69,32 +166,11 @@ protected ExecuteResult execute(ConnectorManager connector) {
break;
}
- return result ? getSuccessOutput() : getFailedOutput();
- }
-
- // auto generated getter & setter
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getValue() {
- return value;
- }
-
- public void setValue(Integer value) {
- this.value = value;
- }
-
- public Operator getOperator() {
- return operator;
+ if (result) {
+ return getSuccessOutput();
+ } else {
+ return getFailedOutput();
+ }
}
- public void setOperator(Operator assertMethod) {
- this.operator = assertMethod;
- }
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertVariableAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertVariableAction.java
index a8b42b994..36c150581 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertVariableAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/AssertVariableAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -12,13 +28,16 @@
import javax.validation.constraints.NotNull;
/**
- * Action to assert the equality of the content of a variable with a given string
+ * Action to assert the equality of the content of a variable with a given string.
*/
@Entity
@DiscriminatorValue("assertVariable")
@JsonTypeName("assertVariable")
public class AssertVariableAction extends SymbolAction {
+ /** to be serializable. */
+ private static final long serialVersionUID = 6363724455992504221L;
+
/**
* The name of the variable to assert.
*/
@@ -32,45 +51,70 @@ public class AssertVariableAction extends SymbolAction {
private String value;
/**
- * Whether the value of the variable is matched against a regular expression
+ * Whether the value of the variable is matched against a regular expression.
*/
private boolean regexp;
- @Override
- protected ExecuteResult execute(ConnectorManager connector) {
- VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
- String variableValue = storeConnector.get(name);
-
- if (regexp) {
- return variableValue.matches(value) ? getSuccessOutput() : getFailedOutput();
- } else {
- return variableValue.equals(value) ? getSuccessOutput() : getFailedOutput();
- }
- }
-
- // auto generated getter & setter
-
+ /**
+ * @return The name of the variable to assert.
+ */
public String getName() {
return name;
}
+ /**
+ * @param name The new name of the variable to assert.
+ */
public void setName(String name) {
this.name = name;
}
+ /**
+ * @return The value to check the variable against.
+ */
public String getValue() {
return value;
}
+ /**
+ * @param value The new vlue to check the variable against.
+ */
public void setValue(String value) {
this.value = value;
}
+ /**
+ * @return Treat the value as regexp?
+ */
public boolean isRegexp() {
return regexp;
}
+ /**
+ * @param regexp True, if the value is a regular expression; false otherwise.
+ */
public void setRegexp(boolean regexp) {
this.regexp = regexp;
}
+
+ @Override
+ protected ExecuteResult execute(ConnectorManager connector) {
+ VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
+ String variableValue = storeConnector.get(name);
+
+ if (regexp) {
+ if (variableValue.matches(value)) {
+ return getSuccessOutput();
+ } else {
+ return getFailedOutput();
+ }
+ } else {
+ if (variableValue.equals(value)) {
+ return getSuccessOutput();
+ } else {
+ return getFailedOutput();
+ }
+ }
+ }
+
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/IncrementCounterAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/IncrementCounterAction.java
index 4a0bab43b..07ad11327 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/IncrementCounterAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/IncrementCounterAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -44,12 +60,7 @@ public void setName(String name) {
@Override
public ExecuteResult execute(ConnectorManager connector) {
CounterStoreConnector storeConnector = connector.getConnector(CounterStoreConnector.class);
- try {
- storeConnector.increment(project.getId(), name);
- return getSuccessOutput();
- } catch (IllegalStateException e) {
- return getFailedOutput();
- }
-
+ storeConnector.increment(user.getId(), project.getId(), name);
+ return getSuccessOutput();
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetCounterAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetCounterAction.java
index 9430aeed9..758e850a7 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetCounterAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetCounterAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -19,6 +35,9 @@
@JsonTypeName("setCounter")
public class SetCounterAction extends SymbolAction {
+ /** to be serializable. */
+ private static final long serialVersionUID = -6023597222318880440L;
+
/** The name of the counter to set a new value to. */
@NotBlank
private String name;
@@ -27,18 +46,30 @@ public class SetCounterAction extends SymbolAction {
@NotNull
private Integer counterValue;
+ /**
+ * @return The name of the counter to set.
+ */
public String getName() {
return name;
}
+ /**
+ * @param name The new name of the counter to set.
+ */
public void setName(String name) {
this.name = name;
}
+ /**
+ * @return The value to set the counter to.
+ */
public Integer getValue() {
return counterValue;
}
+ /**
+ * @param value The new value to set the counter to.
+ */
public void setValue(Integer value) {
this.counterValue = value;
}
@@ -46,11 +77,7 @@ public void setValue(Integer value) {
@Override
public ExecuteResult execute(ConnectorManager connector) {
CounterStoreConnector storeConnector = connector.getConnector(CounterStoreConnector.class);
- try {
- storeConnector.set(project.getId(), name, counterValue);
- return getSuccessOutput();
- } catch (IllegalStateException e) {
- return getFailedOutput();
- }
+ storeConnector.set(getUser().getId(), project.getId(), name, counterValue);
+ return getSuccessOutput();
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableAction.java
index ab5eca598..952d6ffb3 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -19,6 +35,9 @@
@JsonTypeName("setVariable")
public class SetVariableAction extends SymbolAction {
+ /** to be serializable. */
+ private static final long serialVersionUID = 1935478771410953466L;
+
/** The name of the variable to set a new value to. */
@NotBlank
protected String name;
@@ -27,18 +46,30 @@ public class SetVariableAction extends SymbolAction {
@NotNull
protected String value;
+ /**
+ * @return The name of the variable to set.
+ */
public String getName() {
return name;
}
+ /**
+ * @param name The new name of the variable to set.
+ */
public void setName(String name) {
this.name = name;
}
+ /**
+ * @return The value to set the variable to.
+ */
public String getValue() {
return value;
}
+ /**
+ * @param value The new value to set the variable to.
+ */
public void setValue(String value) {
this.value = value;
}
@@ -46,11 +77,7 @@ public void setValue(String value) {
@Override
public ExecuteResult execute(ConnectorManager connector) {
VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
- try {
- storeConnector.set(name, value);
- return getSuccessOutput();
- } catch (IllegalStateException e) {
- return getFailedOutput();
- }
+ storeConnector.set(name, value);
+ return getSuccessOutput();
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByCookieAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByCookieAction.java
index 778649bd7..94cd7804a 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByCookieAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByCookieAction.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.learner.connectors.ConnectorManager;
@@ -8,34 +25,75 @@
import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebDriver;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.ws.rs.core.NewCookie;
import java.util.Map;
+/**
+ * Action to set the value of a variable based on a response cookie.
+ */
@Entity
@DiscriminatorValue("setVariableByCookie")
@JsonTypeName("setVariableByCookie")
public class SetVariableByCookieAction extends SetVariableAction {
- private enum CookieType {
- WEB, REST
+ /**
+ * Enum to differentiate web & REST cookies.
+ */
+ public enum CookieType {
+
+ /** Cookies from or to a web interface. */
+ WEB,
+
+ /** Cookies from or to an REST interface. */
+ REST;
+
+ /**
+ * Parser function to handle the enum names case insensitive.
+ *
+ * @param name
+ * The enum name.
+ * @return The corresponding CookieType.
+ * @throws IllegalArgumentException
+ * If the name could not be parsed.
+ */
+ @JsonCreator
+ public static CookieType fromString(String name) throws IllegalArgumentException {
+ return CookieType.valueOf(name.toUpperCase());
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+
}
+ /** to be serializable. */
+ private static final long serialVersionUID = 5093001294341313128L;
+
/**
- * The type of the cookie. Either by selenium cookie or from a http request
+ * The type of the cookie. Either by selenium cookie or from a http request.
*
* @requiredField
*/
private CookieType cookieType;
+ /**
+ * @return The type of the cookie.
+ */
public CookieType getCookieType() {
return cookieType;
}
- public void setCookieType(CookieType t) {
- cookieType = t;
+ /**
+ * @param type The new type of the cookie.
+ */
+ public void setCookieType(CookieType type) {
+ cookieType = type;
}
@Override
@@ -45,25 +103,27 @@ public ExecuteResult execute(ConnectorManager connector) {
WebSiteConnector webSiteConnector = connector.getConnector(WebSiteConnector.class);
try {
- String value = null;
+ String cookieValue = null;
if (cookieType == CookieType.WEB) {
- Cookie cookie = webSiteConnector.getDriver().manage().getCookieNamed(value);
+ WebDriver driver = webSiteConnector.getDriver();
+ WebDriver.Options manage = driver.manage();
+ Cookie cookie = manage.getCookieNamed(value);
if (cookie != null) {
- value = cookie.getValue();
+ cookieValue = cookie.getValue();
}
} else if (cookieType == CookieType.REST) {
Map cookies = webServiceConnector.getCookies();
javax.ws.rs.core.Cookie cookie = cookies.get(value);
if (cookie != null) {
- value = cookies.get(value).getValue();
+ cookieValue = cookie.getValue();
}
} else {
return getFailedOutput();
}
- if (value != null) {
- storeConnector.set(name, value);
+ if (cookieValue != null) {
+ storeConnector.set(name, cookieValue);
return getSuccessOutput();
} else {
return getFailedOutput();
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByHTMLElementAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByHTMLElementAction.java
index c2760b692..b17fedc9d 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByHTMLElementAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByHTMLElementAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
@@ -5,6 +21,8 @@
import de.learnlib.alex.core.learner.connectors.ConnectorManager;
import de.learnlib.alex.core.learner.connectors.VariableStoreConnector;
import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.openqa.selenium.NoSuchElementException;
import javax.persistence.DiscriminatorValue;
@@ -18,6 +36,12 @@
@JsonTypeName("setVariableByHTML")
public class SetVariableByHTMLElementAction extends SetVariableAction {
+ /** to be serializable. */
+ private static final long serialVersionUID = -7654754471208209824L;
+
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
@Override
public ExecuteResult execute(ConnectorManager connector) {
VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
@@ -27,7 +51,8 @@ public ExecuteResult execute(ConnectorManager connector) {
String valueInTheNode = webSiteConnector.getElement(value).getText();
storeConnector.set(name, valueInTheNode);
return getSuccessOutput();
- } catch (IllegalStateException | NoSuchElementException e) {
+ } catch (NoSuchElementException e) {
+ LOGGER.info("Could not set the variable '" + name + "' to the value of the HTML node '" + value + "'.");
return getFailedOutput();
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByJSONAttributeAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByJSONAttributeAction.java
index 5adcdae41..382fe17b3 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByJSONAttributeAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByJSONAttributeAction.java
@@ -1,14 +1,34 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.StoreSymbolActions;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeName;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.learner.connectors.ConnectorManager;
import de.learnlib.alex.core.learner.connectors.VariableStoreConnector;
import de.learnlib.alex.core.learner.connectors.WebServiceConnector;
import de.learnlib.alex.utils.JSONHelpers;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
+import javax.persistence.Transient;
/**
* Action to set a variable to a value received from an element of the current (JSON) body.
@@ -18,6 +38,11 @@
@JsonTypeName("setVariableByJSON")
public class SetVariableByJSONAttributeAction extends SetVariableAction {
+ /** Use the learner logger. */
+ @Transient
+ @JsonIgnore
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
@Override
public ExecuteResult execute(ConnectorManager connector) {
VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
@@ -25,7 +50,11 @@ public ExecuteResult execute(ConnectorManager connector) {
String body = webServiceConnector.getBody();
String valueInTheBody = JSONHelpers.getAttributeValue(body, value);
+
if (valueInTheBody == null) {
+ LOGGER.info("Could not set the variable '" + name + "' to the value of the "
+ + "JSON attribute '" + value + "' in the body '" + body + "' "
+ + "(ignoreFailure : " + ignoreFailure + ", negated: " + negated + ").");
return getFailedOutput();
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByNodeAttributeAction.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByNodeAttributeAction.java
new file mode 100644
index 000000000..861a6e46c
--- /dev/null
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/SetVariableByNodeAttributeAction.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.learnlib.alex.actions.StoreSymbolActions;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import de.learnlib.alex.core.entities.ExecuteResult;
+import de.learnlib.alex.core.entities.SymbolAction;
+import de.learnlib.alex.core.learner.connectors.ConnectorManager;
+import de.learnlib.alex.core.learner.connectors.VariableStoreConnector;
+import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.hibernate.validator.constraints.NotBlank;
+import org.openqa.selenium.NoSuchElementException;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Action to set a variable to the value of an attribute of an HTML node.
+ */
+@Entity
+@DiscriminatorValue("setVariableByNodeAttribute")
+@JsonTypeName("setVariableByNodeAttribute")
+public class SetVariableByNodeAttributeAction extends SymbolAction {
+
+ /** to be serializable. */
+ private static final long serialVersionUID = 8998187003156355834L;
+
+ /** Use the learner logger. */
+ @Transient
+ @JsonIgnore
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
+ /** The name of the variable. */
+ @NotBlank
+ protected String name;
+
+ /** The node to look for. */
+ @NotNull
+ @Column(columnDefinition = "CLOB")
+ protected String node;
+
+ /** The attribute name of the node to look for. */
+ @NotNull
+ protected String attribute;
+
+ /**
+ * @return The name of the variable to set.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name The name of the new variable to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return The node to get the attribute from.
+ */
+ public String getNode() {
+ return node;
+ }
+
+ /**
+ * @param node The new identifier for the node to get the attribute from.
+ */
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ /**
+ * @return The identifier of the attribute to get the value from.
+ */
+ public String getAttribute() {
+ return attribute;
+ }
+
+ /**
+ * @param attribute The identifier of the new attribute to get the value from.
+ */
+ public void setAttribute(String attribute) {
+ this.attribute = attribute;
+ }
+
+ @Override
+ protected ExecuteResult execute(ConnectorManager connector) {
+ VariableStoreConnector storeConnector = connector.getConnector(VariableStoreConnector.class);
+ WebSiteConnector webSiteConnector = connector.getConnector(WebSiteConnector.class);
+
+ try {
+ String value = webSiteConnector.getElement(node).getAttribute(attribute);
+ storeConnector.set(name, value);
+
+ return getSuccessOutput();
+ } catch (NoSuchElementException e) {
+ LOGGER.info("Could not set the variable '" + name + "' to the value of the attribute "
+ + "of the HTML node '" + node + "'.");
+ return getFailedOutput();
+ }
+ }
+
+}
diff --git a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/package-info.java b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/package-info.java
index 8bc6056b0..a191573f8 100644
--- a/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/package-info.java
+++ b/main/src/main/java/de/learnlib/alex/actions/StoreSymbolActions/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * 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.
+ */
+
/**
* This package contains all implementations of actions that store data (counters & variables).
*/
diff --git a/main/src/main/java/de/learnlib/alex/actions/WaitAction.java b/main/src/main/java/de/learnlib/alex/actions/WaitAction.java
index af053b8bd..dce72ea9d 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WaitAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WaitAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions;
import com.fasterxml.jackson.annotation.JsonTypeName;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckNodeAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckNodeAction.java
index 4a9a19ffc..502b104ca 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckNodeAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckNodeAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckPageTitleAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckPageTitleAction.java
index 472e10a3f..dad7144b9 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckPageTitleAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckPageTitleAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -12,16 +28,14 @@
import javax.persistence.Entity;
/**
- * Action to check the page title
+ * Action to check the page title.
*/
@Entity
@DiscriminatorValue("web_checkPageTitle")
@JsonTypeName("web_checkPageTitle")
public class CheckPageTitleAction extends WebSymbolAction {
- /**
- * The title of the web page
- */
+ /** The title of the web page. */
@NotBlank
private String title;
@@ -31,14 +45,11 @@ public class CheckPageTitleAction extends WebSymbolAction {
*/
private boolean regexp;
- @Override
- public ExecuteResult execute(WebSiteConnector connector) {
- WebDriver driver = connector.getDriver();
- if (SearchHelper.search(getTitleWithVariableValues(), driver.getTitle(), regexp)) {
- return getSuccessOutput();
- } else {
- return getFailedOutput();
- }
+ /**
+ * @return The title to search for (without replaced counters nor variables).
+ */
+ public String getTitle() {
+ return title;
}
/**
@@ -52,19 +63,35 @@ public String getTitleWithVariableValues() {
return insertVariableValues(title);
}
- public String getTitle() {
- return title;
- }
-
+ /**
+ * @param title The new title to search for.
+ */
public void setTitle(String title) {
this.title = title;
}
+ /**
+ * @return Is the title to search for a regexp?
+ */
public boolean isRegexp() {
return regexp;
}
+ /**
+ * @param regexp True if the title is a regexp; False otherwise.
+ */
public void setRegexp(boolean regexp) {
this.regexp = regexp;
}
+
+ @Override
+ public ExecuteResult execute(WebSiteConnector connector) {
+ WebDriver driver = connector.getDriver();
+ if (SearchHelper.search(getTitleWithVariableValues(), driver.getTitle(), regexp)) {
+ return getSuccessOutput();
+ } else {
+ return getFailedOutput();
+ }
+ }
+
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckTextWebAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckTextWebAction.java
index 08f123246..b07db2f62 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckTextWebAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/CheckTextWebAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClearAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClearAction.java
index 962c05898..660bef564 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClearAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClearAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickAction.java
index 161f70dd7..5d0255166 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickLinkAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickLinkAction.java
index 9c068f126..e8cecc676 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickLinkAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/ClickLinkAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/FillAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/FillAction.java
index 4f837c580..8615a64b6 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/FillAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/FillAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/GotoAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/GotoAction.java
index 904d4e62b..35c24d963 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/GotoAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/GotoAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -21,8 +37,8 @@ public class GotoAction extends WebSymbolAction {
/** to be serializable. */
private static final long serialVersionUID = -9158530821188611940L;
- /** Use the logger for the server part. */
- private static final Logger LOGGER = LogManager.getLogger("server");
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
/** The URL of the site. */
private String url;
@@ -61,9 +77,10 @@ public void setUrl(String url) {
public ExecuteResult execute(WebSiteConnector connector) {
try {
connector.get(getURLWithVariableValues());
+ LOGGER.info("Could goto '" + url + "'.");
return getSuccessOutput();
} catch (Exception e) {
- LOGGER.info("Could not goto " + url, e);
+ LOGGER.info("Could not goto '" + url + "'.", e);
return getFailedOutput();
}
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SelectAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SelectAction.java
index 08f358624..77621f153 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SelectAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SelectAction.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName;
import de.learnlib.alex.core.entities.ExecuteResult;
import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
@@ -20,8 +37,38 @@
@JsonTypeName("web_select")
public class SelectAction extends FillAction {
- private enum SelectByType {
- VALUE, TEXT, INDEX;
+ /**
+ * Enum to choose how to interact with the selection input.
+ */
+ public enum SelectByType {
+ /** Select by the value attribute. */
+ VALUE,
+
+ /** Select by the option text. */
+ TEXT,
+
+ /** Select simply by using the index starting at 0. */
+ INDEX;
+
+ /**
+ * Parser function to handle the enum names case insensitive.
+ *
+ * @param name
+ * The enum name.
+ * @return The corresponding SelectByType.
+ * @throws IllegalArgumentException
+ * If the name could not be parsed.
+ */
+ @JsonCreator
+ public static SelectByType fromString(String name) throws IllegalArgumentException {
+ return SelectByType.valueOf(name.toUpperCase());
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+
}
/**
@@ -31,6 +78,20 @@ private enum SelectByType {
*/
private SelectByType selectBy;
+ /**
+ * @return How to do the selection of the node.
+ */
+ public SelectByType getSelectBy() {
+ return selectBy;
+ }
+
+ /**
+ * @param selectBy The new method to select the value in the node.
+ */
+ public void setSelectBy(SelectByType selectBy) {
+ this.selectBy = selectBy;
+ }
+
@Override
public ExecuteResult execute(WebSiteConnector connector) {
try {
@@ -51,16 +112,9 @@ public ExecuteResult execute(WebSiteConnector connector) {
break;
}
return getSuccessOutput();
- } catch (NoSuchElementException | UnexpectedTagNameException e) {
+ } catch (NoSuchElementException | NumberFormatException | UnexpectedTagNameException e) {
return getFailedOutput();
}
}
- public SelectByType getSelectBy() {
- return selectBy;
- }
-
- public void setSelectBy(SelectByType selectBy) {
- this.selectBy = selectBy;
- }
}
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SubmitAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SubmitAction.java
index 6365c0a3a..4e84908ac 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SubmitAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/SubmitAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForNodeAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForNodeAction.java
new file mode 100644
index 000000000..97c3a5279
--- /dev/null
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForNodeAction.java
@@ -0,0 +1,190 @@
+package de.learnlib.alex.actions.WebSymbolActions;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import de.learnlib.alex.core.entities.ExecuteResult;
+import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
+import de.learnlib.alex.utils.CSSUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.hibernate.validator.constraints.NotBlank;
+import org.openqa.selenium.By;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Action to wait for the state of an element to change.
+ */
+@Entity
+@DiscriminatorValue("web_waitForNode")
+@JsonTypeName("web_waitForNode")
+public class WaitForNodeAction extends WebSymbolAction {
+
+ /**
+ * to be serializable.
+ */
+ private static final long serialVersionUID = 4029222122474954117L;
+
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
+ /**
+ * Enumeration to specify the wait criterion.
+ */
+ public enum WaitCriterion {
+
+ /**
+ * If an element is attached to the DOM and visible.
+ */
+ VISIBLE,
+
+ /**
+ * If an element is attached to the DOM but not visible.
+ */
+ INVISIBLE,
+
+ /**
+ * If an element is added to the DOM tree.
+ */
+ ADDED,
+
+ /**
+ * If an element is removed from the DOM tree.
+ */
+ REMOVED;
+
+ /**
+ * Parser function to handle the enum names case insensitive.
+ *
+ * @param name
+ * The enum name.
+ * @return The corresponding WaitCriterion.
+ * @throws IllegalArgumentException
+ * If the name could not be parsed.
+ */
+ @JsonCreator
+ public static WaitCriterion fromString(String name) throws IllegalArgumentException {
+ return WaitCriterion.valueOf(name.toUpperCase());
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+ }
+
+ /**
+ * The css selector of the element.
+ */
+ @NotBlank
+ @Column(columnDefinition = "CLOB")
+ private String node;
+
+ /**
+ * Which criterion is used to wait for the title.
+ */
+ @NotNull
+ private WaitCriterion waitCriterion;
+
+ /**
+ * How many seconds should be waited before the action fails.
+ */
+ @NotNull
+ private long maxWaitTime;
+
+ /**
+ * Get the selector of the element.
+ *
+ * @return The selector of the element
+ */
+ public String getNode() {
+ return node;
+ }
+
+ /**
+ * Set the selector of the element.
+ *
+ * @param node The selector of the element
+ */
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ /**
+ * Get the wait criterion.
+ *
+ * @return The wait criterion
+ */
+ public WaitCriterion getWaitCriterion() {
+ return waitCriterion;
+ }
+
+ /**
+ * Set the wait criterion.
+ *
+ * @param waitCriterion The wait criterion
+ */
+ public void setWaitCriterion(WaitCriterion waitCriterion) {
+ this.waitCriterion = waitCriterion;
+ }
+
+ /**
+ * Get the max amount of time in seconds to wait before the action fails.
+ *
+ * @return The max amount of time
+ */
+ public long getMaxWaitTime() {
+ return maxWaitTime;
+ }
+
+ /**
+ * Set the max amount of time in seconds to wait before the action fails.
+ *
+ * @param maxWaitTime The max amount of time in seconds
+ */
+ public void setMaxWaitTime(long maxWaitTime) {
+ this.maxWaitTime = maxWaitTime;
+ }
+
+ @Override
+ protected ExecuteResult execute(WebSiteConnector connector) {
+ if (maxWaitTime < 0) {
+ return getFailedOutput();
+ }
+
+ WebDriverWait wait = new WebDriverWait(connector.getDriver(), maxWaitTime);
+ String selector = CSSUtils.escapeSelector(insertVariableValues(node));
+
+ try {
+ switch (waitCriterion) {
+ case VISIBLE:
+ wait.until(ExpectedConditions.visibilityOf(connector.getElement(selector)));
+ break;
+ case INVISIBLE:
+ wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(selector)));
+ break;
+ case ADDED:
+ wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(selector)));
+ break;
+ case REMOVED:
+ wait.until(ExpectedConditions.stalenessOf(connector.getElement(selector)));
+ break;
+ default:
+ return getFailedOutput();
+ }
+ return getSuccessOutput();
+ } catch (TimeoutException e) {
+ LOGGER.info("Waiting on the node '" + selector + "' (criterion: '" + waitCriterion + "') timed out.");
+ return getFailedOutput();
+ }
+
+ }
+
+
+}
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForTitleAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForTitleAction.java
new file mode 100644
index 000000000..e7384708b
--- /dev/null
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WaitForTitleAction.java
@@ -0,0 +1,169 @@
+package de.learnlib.alex.actions.WebSymbolActions;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import de.learnlib.alex.core.entities.ExecuteResult;
+import de.learnlib.alex.core.learner.connectors.WebSiteConnector;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.hibernate.validator.constraints.NotBlank;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Action to wait for the title of a page to change.
+ */
+@Entity
+@DiscriminatorValue("web_waitForTitle")
+@JsonTypeName("web_waitForTitle")
+public class WaitForTitleAction extends WebSymbolAction {
+
+ /**
+ * to be serializable.
+ */
+ private static final long serialVersionUID = -7416267361597106520L;
+
+ /** Use the learner logger. */
+ private static final Logger LOGGER = LogManager.getLogger("learner");
+
+ /**
+ * Enumeration to specify the wait criterion.
+ */
+ public enum WaitCriterion {
+ /**
+ * If the title should be the value.
+ */
+ IS,
+
+ /**
+ * If the title should contain the value.
+ */
+ CONTAINS;
+
+
+ /**
+ * Parser function to handle the enum names case insensitive.
+ *
+ * @param name
+ * The enum name.
+ * @return The corresponding WaitCriterion.
+ * @throws IllegalArgumentException
+ * If the name could not be parsed.
+ */
+ @JsonCreator
+ public static WaitCriterion fromString(String name) throws IllegalArgumentException {
+ return WaitCriterion.valueOf(name.toUpperCase());
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+ }
+
+ /**
+ * The value the title should match / contain.
+ */
+ @NotBlank
+ private String value;
+
+ /**
+ * Which criterion is used to wait for the title.
+ */
+ @NotNull
+ private WaitCriterion waitCriterion;
+
+ /**
+ * How many seconds should be waited before the action fails.
+ */
+ @NotNull
+ private long maxWaitTime;
+
+ /**
+ * Get the value for the title.
+ *
+ * @return The value for the title
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Set the expected value of the title.
+ *
+ * @param value The expected value of the title
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the wait criterion.
+ *
+ * @return The wait criterion
+ */
+ public WaitCriterion getWaitCriterion() {
+ return waitCriterion;
+ }
+
+ /**
+ * Set the wait criterion.
+ *
+ * @param waitCriterion The wait criterion
+ */
+ public void setWaitCriterion(WaitCriterion waitCriterion) {
+ this.waitCriterion = waitCriterion;
+ }
+
+ /**
+ * Get the max amount of time in seconds to wait before the action fails.
+ *
+ * @return The max amount of time
+ */
+ public long getMaxWaitTime() {
+ return maxWaitTime;
+ }
+
+ /**
+ * Set the max amount of time in seconds to wait before the action fails.
+ *
+ * @param maxWaitTime The max amount of time in seconds
+ */
+ public void setMaxWaitTime(long maxWaitTime) {
+ this.maxWaitTime = maxWaitTime;
+ }
+
+ @Override
+ protected ExecuteResult execute(WebSiteConnector connector) {
+ if (maxWaitTime < 0) {
+ return getFailedOutput();
+ }
+
+ WebDriverWait wait = new WebDriverWait(connector.getDriver(), maxWaitTime);
+
+ try {
+ switch (waitCriterion) {
+ case IS:
+ wait.until(ExpectedConditions.titleIs(value));
+ break;
+ case CONTAINS:
+ wait.until(ExpectedConditions.titleContains(value));
+ break;
+ default:
+ return getFailedOutput();
+ }
+
+ return getSuccessOutput();
+ } catch (TimeoutException e) {
+ LOGGER.info("Waiting on the title '" + value + "' (criterion: '" + waitCriterion + "') timed out. "
+ + "Last known title was '" + connector.getDriver().getTitle() + "'.");
+ return getFailedOutput();
+ }
+ }
+
+}
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WebSymbolAction.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WebSymbolAction.java
index a102a4c15..b5849e89f 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WebSymbolAction.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/WebSymbolAction.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.actions.WebSymbolActions;
import com.fasterxml.jackson.annotation.JsonTypeName;
diff --git a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/package-info.java b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/package-info.java
index 67590e85d..8b7268833 100644
--- a/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/package-info.java
+++ b/main/src/main/java/de/learnlib/alex/actions/WebSymbolActions/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * 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.
+ */
+
/**
* This package contains all concrete implementations around REST Symbols.
*/
diff --git a/main/src/main/java/de/learnlib/alex/actions/package-info.java b/main/src/main/java/de/learnlib/alex/actions/package-info.java
index 611e97030..54edd53f0 100644
--- a/main/src/main/java/de/learnlib/alex/actions/package-info.java
+++ b/main/src/main/java/de/learnlib/alex/actions/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * 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.
+ */
+
/**
* All the actions!!
*/
diff --git a/main/src/main/java/de/learnlib/alex/algorithms/DHC.java b/main/src/main/java/de/learnlib/alex/algorithms/DHC.java
index cd0d530d7..312f4efda 100644
--- a/main/src/main/java/de/learnlib/alex/algorithms/DHC.java
+++ b/main/src/main/java/de/learnlib/alex/algorithms/DHC.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.algorithms;
import de.learnlib.alex.annotations.LearnAlgorithm;
diff --git a/main/src/main/java/de/learnlib/alex/algorithms/DiscriminationTree.java b/main/src/main/java/de/learnlib/alex/algorithms/DiscriminationTree.java
index 24405b227..2fe1a667b 100644
--- a/main/src/main/java/de/learnlib/alex/algorithms/DiscriminationTree.java
+++ b/main/src/main/java/de/learnlib/alex/algorithms/DiscriminationTree.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.algorithms;
import de.learnlib.alex.annotations.LearnAlgorithm;
diff --git a/main/src/main/java/de/learnlib/alex/algorithms/LStar.java b/main/src/main/java/de/learnlib/alex/algorithms/LStar.java
index 3a475d5f6..55de264c5 100644
--- a/main/src/main/java/de/learnlib/alex/algorithms/LStar.java
+++ b/main/src/main/java/de/learnlib/alex/algorithms/LStar.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.algorithms;
import de.learnlib.alex.annotations.LearnAlgorithm;
diff --git a/main/src/main/java/de/learnlib/alex/algorithms/TTT.java b/main/src/main/java/de/learnlib/alex/algorithms/TTT.java
index 20dbdb609..2b8369932 100644
--- a/main/src/main/java/de/learnlib/alex/algorithms/TTT.java
+++ b/main/src/main/java/de/learnlib/alex/algorithms/TTT.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.algorithms;
import de.learnlib.alex.annotations.LearnAlgorithm;
diff --git a/main/src/main/java/de/learnlib/alex/algorithms/package-info.java b/main/src/main/java/de/learnlib/alex/algorithms/package-info.java
index afcc11396..cc80ff6ce 100644
--- a/main/src/main/java/de/learnlib/alex/algorithms/package-info.java
+++ b/main/src/main/java/de/learnlib/alex/algorithms/package-info.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * 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.
+ */
+
/**
* This package contains the algorithms that ALEX will be able to use.
*/
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/CounterDAO.java b/main/src/main/java/de/learnlib/alex/core/dao/CounterDAO.java
index 4a7771bd3..832deafe6 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/CounterDAO.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/CounterDAO.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.Counter;
@@ -27,17 +43,21 @@ public interface CounterDAO {
/**
* Get all counter of a project.
*
+ * @param userId
+ * The user that owns the counters
* @param projectId
* The project of the counters.
* @return A list of counters within the given project.
* @throws NotFoundException
* If no project with the given ID exists.
*/
- List getAll(Long projectId) throws NotFoundException;
+ List getAll(Long userId, Long projectId) throws NotFoundException;
/**
* Get a specific counter.
*
+ * @param userId
+ * The user that owns the counter.
* @param projectId
* The project of the counter.
* @param name
@@ -46,7 +66,7 @@ public interface CounterDAO {
* @throws NotFoundException
* If the counter was not found.
*/
- Counter get(Long projectId, String name) throws NotFoundException;
+ Counter get(Long userId, Long projectId, String name) throws NotFoundException;
/**
* Update a counter.
@@ -63,6 +83,8 @@ public interface CounterDAO {
/**
* Deletes counters.
*
+ * @param userId
+ * The user that owns the counters
* @param projectId
* The project of the counter.
* @param names
@@ -70,6 +92,6 @@ public interface CounterDAO {
* @throws NotFoundException
* If the project or counter was not found.
*/
- void delete(Long projectId, String... names) throws NotFoundException;
+ void delete(Long userId, Long projectId, String... names) throws NotFoundException;
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/CounterDAOImpl.java b/main/src/main/java/de/learnlib/alex/core/dao/CounterDAOImpl.java
index 1122d9aec..187593114 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/CounterDAOImpl.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/CounterDAOImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.Counter;
@@ -7,14 +23,15 @@
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
+import org.springframework.stereotype.Repository;
import javax.validation.ValidationException;
-import java.util.LinkedList;
import java.util.List;
/**
* Implementation of a CounterDAO using Hibernate.
*/
+@Repository
public class CounterDAOImpl implements CounterDAO {
@Override
@@ -22,8 +39,7 @@ public void create(Counter counter) throws ValidationException {
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getSession();
try {
- Project project = (Project) session.load(Project.class, counter.getProjectId());
- project.getId();
+ Project project = session.load(Project.class, counter.getProjectId());
counter.setProject(project);
session.save(counter);
@@ -37,29 +53,30 @@ public void create(Counter counter) throws ValidationException {
}
@Override
- public List getAll(Long projectId) throws NotFoundException {
+ public List getAll(Long userId, Long projectId) throws NotFoundException {
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getSession();
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
+ if (session.get(Project.class, projectId) == null) {
throw new NotFoundException("The project with the id " + projectId + " was not found.");
}
@SuppressWarnings("Should always return a list of Counters.")
List result = session.createCriteria(Counter.class)
- .add(Restrictions.eq("project.id", projectId))
- .list();
+ .add(Restrictions.eq("project.id", projectId))
+ .add(Restrictions.eq("user.id", userId))
+ .list();
HibernateUtil.commitTransaction();
return result;
}
@Override
- public Counter get(Long projectId, String name) throws NotFoundException {
+ public Counter get(Long userId, Long projectId, String name) throws NotFoundException {
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getSession();
try {
- Counter result = get(session, projectId, name);
+ Counter result = get(session, userId, projectId, name);
HibernateUtil.commitTransaction();
return result;
@@ -69,20 +86,21 @@ public Counter get(Long projectId, String name) throws NotFoundException {
}
}
- private Counter get(Session session, Long projectId, String name) throws NotFoundException {
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
+ private Counter get(Session session, Long userId, Long projectId, String name) throws NotFoundException {
+ if (session.get(Project.class, projectId) == null) {
throw new NotFoundException("The project with the id " + projectId + " was not found.");
}
@SuppressWarnings("Should always return a list of Counters.")
Counter result = (Counter) session.createCriteria(Counter.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.eq("name", name))
- .uniqueResult();
+ .add(Restrictions.eq("project.id", projectId))
+ .add(Restrictions.eq("user.id", userId))
+ .add(Restrictions.eq("name", name))
+ .uniqueResult();
if (result == null) {
throw new NotFoundException("Could not find the counter with the name '" + name
- + "' in the project " + projectId + "!");
+ + "' in the project " + projectId + "!");
}
return result;
@@ -94,7 +112,7 @@ public void update(Counter counter) throws NotFoundException, ValidationExceptio
Session session = HibernateUtil.getSession();
try {
- get(session, counter.getProjectId(), counter.getName()); // check if the counter exists
+ get(session, counter.getUserId(), counter.getProjectId(), counter.getName()); // check if the counter exists
session.merge(counter);
HibernateUtil.commitTransaction();
@@ -108,21 +126,23 @@ public void update(Counter counter) throws NotFoundException, ValidationExceptio
}
@Override
- public void delete(Long projectId, String... names) throws NotFoundException {
+ public void delete(Long userId, Long projectId, String... names) throws NotFoundException {
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getSession();
- try {
- List counters = new LinkedList<>();
- for (String name : names) {
- counters.add(get(session, projectId, name));
- }
+ @SuppressWarnings("Should always return a list of Counters.")
+ List counters = session.createCriteria(Counter.class)
+ .add(Restrictions.in("name", names))
+ .add(Restrictions.eq("project.id", projectId))
+ .add(Restrictions.eq("user.id", userId))
+ .list();
+ if (names.length == counters.size()) { // all counters found -> delete them & success
counters.forEach(session::delete);
HibernateUtil.commitTransaction();
- } catch (NotFoundException e) {
+ } else {
HibernateUtil.rollbackTransaction();
- throw e;
+ throw new NotFoundException("Could not delete the counter(s), becauser at least one does not exists!");
}
}
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/FileDAO.java b/main/src/main/java/de/learnlib/alex/core/dao/FileDAO.java
index 925287d44..1a2e0b76a 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/FileDAO.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/FileDAO.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.UploadableFile;
@@ -8,15 +24,70 @@
import java.io.InputStream;
import java.util.List;
+/**
+ * Interface to describe how Files are handled.
+ */
public interface FileDAO {
- void create(Long projectId, InputStream uploadedInputStream, FormDataContentDisposition fileDetail)
- throws IllegalArgumentException, IOException, IllegalStateException;
+ /**
+ * Put a new file into the file system.
+ *
+ * @param userId
+ * The user the file belongs to.
+ * @param projectId
+ * The id of the project that the file belongs to.
+ * @param uploadedInputStream
+ * The file as input stream.
+ * @param fileDetail
+ * Other file (meta) data.
+ * @throws IOException
+ * If something during the actual writing went wrong.
+ * @throws IllegalStateException
+ * If the file already exists or the destination directory is not a directory or otherwise blocked.
+ */
+ void create(Long userId, Long projectId, InputStream uploadedInputStream, FormDataContentDisposition fileDetail)
+ throws IOException, IllegalStateException;
- List getAll(Long projectId) throws NotFoundException;
+ /**
+ * Get a list of all fiels of a user within a project.
+ *
+ * @param userId
+ * The user to show the files of.
+ * @param projectId
+ * The project the files belong to.
+ * @return A List of Files. Can be empty.
+ * @throws NotFoundException
+ * If no files can be found.
+ */
+ List getAll(Long userId, Long projectId) throws NotFoundException;
- String getAbsoulteFilePath(Long projectId, String fileName) throws NotFoundException;
+ /**
+ * Get the absolute path to a file on the machine.
+ *
+ * @param userId
+ * The user the file belongs to.
+ * @param projectId
+ * The id of the project that the file belongs to.
+ * @param fileName
+ * The name of the file.
+ * @return The absolute path to the file on the actual machine.
+ * @throws NotFoundException
+ * If the file could not be found.
+ */
+ String getAbsoluteFilePath(Long userId, Long projectId, String fileName) throws NotFoundException;
- void delete(Long projectId, String fileName) throws NotFoundException;
+ /**
+ * Deletes a file.
+ *
+ * @param userId
+ * The user the file belongs to.
+ * @param projectId
+ * The id of the project that the file belongs to.
+ * @param fileName
+ * The name of the file to delete.
+ * @throws NotFoundException
+ * If the file could not be found.
+ */
+ void delete(Long userId, Long projectId, String fileName) throws NotFoundException;
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/FileDAOImpl.java b/main/src/main/java/de/learnlib/alex/core/dao/FileDAOImpl.java
index 63748e758..9e2615c3a 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/FileDAOImpl.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/FileDAOImpl.java
@@ -1,8 +1,25 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.UploadableFile;
import de.learnlib.alex.exceptions.NotFoundException;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.springframework.stereotype.Repository;
import java.io.File;
import java.io.FileOutputStream;
@@ -13,10 +30,21 @@
import java.util.LinkedList;
import java.util.List;
+/**
+ * Simple implementation of a FileDAO.
+ */
+@Repository
public class FileDAOImpl implements FileDAO {
+ /** The size of the output write buffer in bytes. */
+ public static final int WRITE_BUFFER_SIZE = 1024;
+
+ /** Path to the root of the upload directory. */
private java.nio.file.Path uploadedDirectoryBaseLocation;
+ /**
+ * Default consturtor that jsut initialises the internal data structures.
+ */
public FileDAOImpl() {
this.uploadedDirectoryBaseLocation = Paths.get(System.getProperty("user.dir"), "uploads");
@@ -27,9 +55,11 @@ public FileDAOImpl() {
}
@Override
- public void create(Long projectId, InputStream uploadedInputStream, FormDataContentDisposition fileDetail)
- throws IllegalArgumentException, IOException, IllegalStateException {
+ public void create(Long userId, Long projectId, InputStream uploadedInputStream,
+ FormDataContentDisposition fileDetail)
+ throws IOException, IllegalStateException {
java.nio.file.Path uploadedDirectoryLocation = Paths.get(uploadedDirectoryBaseLocation.toString(),
+ String.valueOf(userId),
String.valueOf(projectId));
File uploadDirectory = uploadedDirectoryLocation.toFile();
@@ -38,7 +68,7 @@ public void create(Long projectId, InputStream uploadedInputStream, FormDataCont
}
if (!uploadDirectory.isDirectory()) {
- throw new IllegalArgumentException("Could not find the right directory to upload the file.");
+ throw new IllegalStateException("Could not find the right directory to upload the file.");
}
java.nio.file.Path uploadedFileLocation = Paths.get(uploadedDirectoryLocation.toString(),
@@ -53,8 +83,8 @@ public void create(Long projectId, InputStream uploadedInputStream, FormDataCont
}
@Override
- public List getAll(Long projectId) throws NotFoundException {
- File uploadDirectory = getUploadDirectory(projectId);
+ public List getAll(Long userId, Long projectId) throws NotFoundException {
+ File uploadDirectory = getUploadDirectory(userId, projectId);
List files = new LinkedList<>();
for (File f : uploadDirectory.listFiles()) {
@@ -65,12 +95,17 @@ public List getAll(Long projectId) throws NotFoundException {
files.add(uploadableFile);
}
+ if (files.isEmpty()) {
+ throw new NotFoundException("No files found for the User <" + userId + "> and "
+ + "the project <" + projectId + ">.");
+ }
+
return files;
}
@Override
- public String getAbsoulteFilePath(Long projectId, String fileName) throws NotFoundException {
- File uploadDirectory = getUploadDirectory(projectId);
+ public String getAbsoluteFilePath(Long userId, Long projectId, String fileName) throws NotFoundException {
+ File uploadDirectory = getUploadDirectory(userId, projectId);
java.nio.file.Path uploadedFileLocation = Paths.get(uploadDirectory.getPath(), fileName);
File file = uploadedFileLocation.toFile();
@@ -83,8 +118,8 @@ public String getAbsoulteFilePath(Long projectId, String fileName) throws NotFou
}
@Override
- public void delete(Long projectId, String fileName) throws NotFoundException {
- File uploadDirectory = getUploadDirectory(projectId);
+ public void delete(Long userId, Long projectId, String fileName) throws NotFoundException {
+ File uploadDirectory = getUploadDirectory(userId, projectId);
java.nio.file.Path uploadedFileLocation = Paths.get(uploadDirectory.getPath(), fileName);
File file = uploadedFileLocation.toFile();
@@ -96,14 +131,15 @@ public void delete(Long projectId, String fileName) throws NotFoundException {
file.delete();
}
- private File getUploadDirectory(Long projectId) throws NotFoundException {
+ private File getUploadDirectory(Long userId, Long projectId) throws NotFoundException {
java.nio.file.Path uploadedDirectoryLocation = Paths.get(uploadedDirectoryBaseLocation.toString(),
+ String.valueOf(userId),
String.valueOf(projectId));
File uploadDirectory = uploadedDirectoryLocation.toFile();
if (!uploadDirectory.exists() || !uploadDirectory.isDirectory()) {
try {
- uploadDirectory.mkdir();
+ uploadDirectory.mkdirs();
} catch (SecurityException e) {
throw new NotFoundException("Could not find the project directory you are looking for.");
}
@@ -115,16 +151,15 @@ private File getUploadDirectory(Long projectId) throws NotFoundException {
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation)
throws IOException {
- OutputStream out;
- int read;
- byte[] bytes = new byte[1024];
+ try (OutputStream out = new FileOutputStream(new File(uploadedFileLocation))) {
+ int read;
+ byte[] bytes = new byte[WRITE_BUFFER_SIZE];
- out = new FileOutputStream(new File(uploadedFileLocation));
- while ((read = uploadedInputStream.read(bytes)) != -1) {
- out.write(bytes, 0, read);
+ while ((read = uploadedInputStream.read(bytes)) != -1) {
+ out.write(bytes, 0, read);
+ }
+ out.flush();
}
- out.flush();
- out.close();
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAO.java b/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAO.java
index 25a8a3a10..9f7caaace 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAO.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAO.java
@@ -1,6 +1,25 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.LearnerResult;
+import de.learnlib.alex.core.entities.LearnerResultStep;
+import de.learnlib.alex.core.entities.LearnerResumeConfiguration;
+import de.learnlib.alex.core.entities.User;
import de.learnlib.alex.exceptions.NotFoundException;
import javax.validation.ValidationException;
@@ -22,101 +41,98 @@ public interface LearnerResultDAO {
void create(LearnerResult learnerResult) throws ValidationException;
/**
- * Get a list of JSON data containing all the LearnerResults, that are the latest of any test run for a given
- * Project. This LearnerResult are most likely the final results of each test run.
+ * Get a list of all the LearnerResults for a given
+ * Project.
*
+ * @param userId
+ * The user of the LearnerResult
* @param projectId
* The project id of the test run.
- * @return A list of LearnerResults as JSON data.
+ * @param includeSteps
+ * Should all steps be included?
+ * @return A list of LearnerResults.
* @throws NotFoundException
* If the project id was invalid.
*/
- List getAllAsJSON(Long projectId) throws NotFoundException;
-
- /**
- * Get a list of JSON data containing all the steps of a given TestRun for a given Project.
- *
- * @param projectId
- * The project id if the test run.
- * @param testNo
- * The test no. of the test run.
- * @return A list of LearnerResults as JSON data.
- * @throws NotFoundException
- * If the project id or test no. was invalid.
- */
- List getAllAsJSON(Long projectId, Long testNo) throws NotFoundException;
+ List getAll(Long userId, Long projectId, boolean includeSteps) throws NotFoundException;
/**
- * Get a list of lists of JSON data containing all the steps of a given TestRun for a given Project.
+ * Get a list of LearnResults with given testNos for a given Project.
*
+ * @param userId
+ * The user of the LearnerResult
* @param projectId
* The project id if the test run.
* @param testNos
- * The list of test nos. of the test runs.
- * @return A list of list containing LearnerResults as JSON data.
+ * The list of test nos. of the LearnResults.
+ * @param includeSteps
+ * Should all steps be included?
+ * @return A list of LearnerResults.
* @throws NotFoundException
* If the project id or test no. was invalid.
*/
- List> getAllAsJson(Long projectId, List testNos) throws NotFoundException;
+ List getAll(Long userId, Long projectId, Long[] testNos, boolean includeSteps)
+ throws NotFoundException;
/**
- * Get a the last / final LearnerResult of one test run.
+ * Get a single LearnResult.
*
+ * @param userId
+ * The user of the LearnerResult
* @param projectId
* The project id if the test run.
- * @param testRunNo
- * The test no. of the test run.
- * @return The LearnerResult you are looking for, if it exists.
+ * @param testNos
+ * The list of test nos. of the LearnResults.
+ * @param includeSteps
+ * Should all steps be included?
+ * @return The LearnResult you are looking for.
* @throws NotFoundException
- * If the project id or test no. was invalid.
+ * If the given LearnerResult was invalid.
*/
- LearnerResult get(Long projectId, Long testRunNo) throws NotFoundException;
+ LearnerResult get(Long userId, Long projectId, Long testNos, boolean includeSteps) throws NotFoundException;
/**
- * Get the latest LearnerResult of a given test run as JSON data, e.g. the final result.
+ * Create a new step for a LearnResult based on the latest step within the result.
*
- * @param projectId
- * The project id of the test run.
- * @param testNo
- * The test no. of the test run.
- * @return The latest LearnerResult, i.e. the one with the highest step no., for the given test run.
- * @throws NotFoundException
- * If the project id or test no. was invalid.
+ * @param result
+ * The result that the new step will be added to.
+ * @return A new step.
+ * @throws ValidationException
+ * If the requested result could not be found.
*/
- String getAsJSON(Long projectId, Long testNo) throws NotFoundException;
+ LearnerResultStep createStep(LearnerResult result) throws ValidationException;
/**
- * Get a specific LearnerResult as JSON data.
+ * Create a new step for a LearnResult based on the given configuration.
*
- * @param projectId
- * The project id of the test run / LearnerResult.
- * @param testNo
- * The test non. of the test run / LearnerResult.
- * @param stepNo
- * The step no. of the test run / LearnerResult.
- * @return The LearnerResult as JSON data.
- * @throws NotFoundException
- * If the project id, test no. or step no. was invalid.
+ * @param result
+ * The result that the new step will be added to.
+ * @param configuration
+ * The configuration to set the step up.
+ * @return A new step.
+ * @throws ValidationException
+ * If the given LearnerResult was invalid.
*/
- String getAsJSON(Long projectId, Long testNo, Long stepNo) throws NotFoundException;
+ LearnerResultStep createStep(LearnerResult result, LearnerResumeConfiguration configuration)
+ throws ValidationException;
/**
- * Update a given LearnResult. Update means here, to save a new LearnerResult with an increased step no.
- * The previous steps of one test run should not change.
- * This method must also verify that the given result is valid.
+ * Save / Update a step.
*
- * @param learnerResult
- * The LearnerResult to update.
+ * @param result
+ * The result that the step is part of.
+ * @param step
+ * The step the should be saved / updated.
* @throws ValidationException
* If the given LearnerResult was invalid.
- * @throws NotFoundException
- * If the project id or test no. was invalid.
*/
- void update(LearnerResult learnerResult) throws NotFoundException, ValidationException;
+ void saveStep(LearnerResult result, LearnerResultStep step) throws ValidationException;
/**
* Remove a complete test run of a project.
*
+ * @param user
+ * The user of the LearnerResult
* @param projectId
* The project id.
* @param testNo
@@ -124,5 +140,5 @@ public interface LearnerResultDAO {
* @throws NotFoundException
* If the project id or test no. was invalid.
*/
- void delete(Long projectId, Long... testNo) throws NotFoundException;
+ void delete(User user, Long projectId, Long... testNo) throws NotFoundException;
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAOImpl.java b/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAOImpl.java
index 5d90ddb63..abb0bc8b3 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAOImpl.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/LearnerResultDAOImpl.java
@@ -1,28 +1,50 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.LearnerResult;
+import de.learnlib.alex.core.entities.LearnerResultStep;
+import de.learnlib.alex.core.entities.LearnerResumeConfiguration;
import de.learnlib.alex.core.entities.LearnerStatus;
+import de.learnlib.alex.core.entities.Statistics;
+import de.learnlib.alex.core.entities.User;
+import de.learnlib.alex.core.learner.Learner;
import de.learnlib.alex.exceptions.NotFoundException;
import de.learnlib.alex.utils.HibernateUtil;
-import de.learnlib.alex.core.learner.Learner;
+import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
+import org.springframework.stereotype.Repository;
+import javax.inject.Inject;
import javax.validation.ValidationException;
import java.util.Arrays;
import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;
-import javax.inject.Inject;
/**
* Implementation of a LearnerResultDAO using Hibernate.
*/
+@Repository
public class LearnerResultDAOImpl implements LearnerResultDAO {
/** The {@link Learner learner} to use. */
@@ -31,7 +53,7 @@ public class LearnerResultDAOImpl implements LearnerResultDAO {
/**
* Set the learner instance to use.
- * Only package visible, because normlly this instance will be injected, but for testing a manual setter is needed.
+ * Only package visible, because normally this instance will be injected, but for testing a manual setter is needed.
*
* @param learner The learner to use.
*/
@@ -42,11 +64,11 @@ void setLearner(Learner learner) {
@Override
public void create(LearnerResult learnerResult) throws ValidationException {
// new LearnerResults should have a project, not a test number not a step number
- if (learnerResult.getProject() == null
- || learnerResult.getTestNo() != null
- || learnerResult.getStepNo() != null) {
+ if (learnerResult.getUser() == null
+ || learnerResult.getProject() == null
+ || learnerResult.getTestNo() != null) {
throw new ValidationException(
- "To create a LearnResult it must have a Project but must not have a test no. nor step no.");
+ "To create a LearnResult it must have a User and Project but must not have a test no.");
}
// start session
@@ -55,6 +77,7 @@ public void create(LearnerResult learnerResult) throws ValidationException {
// get the current highest test no in the project and add 1 for the next id
Long maxTestNo = (Long) session.createCriteria(LearnerResult.class)
+ .add(Restrictions.eq("user", learnerResult.getUser()))
.add(Restrictions.eq("project", learnerResult.getProject()))
.setProjection(Projections.max("testNo"))
.uniqueResult();
@@ -65,44 +88,45 @@ public void create(LearnerResult learnerResult) throws ValidationException {
learnerResult.setId(0L);
learnerResult.setTestNo(nextTestNo);
- learnerResult.setStepNo(0L);
session.save(learnerResult);
HibernateUtil.commitTransaction();
}
@Override
- public List getAllAsJSON(Long projectId) throws NotFoundException {
+ public List getAll(Long userId, Long projectId, boolean includeSteps) throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
- throw new NotFoundException("The project with the id " + projectId + " was not found.");
- }
-
// fetch the LearnerResults of the project with the the highest step no.
@SuppressWarnings("unchecked") // should return a list of LearnerResults
- List resultsAsJSON = session.createCriteria(LearnerResult.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.eq("stepNo", 0L))
- .setProjection(Projections.property("JSON"))
- .addOrder(Order.asc("testNo"))
- .list();
+ List results = session.createCriteria(LearnerResult.class)
+ .add(Restrictions.eq("user.id", userId))
+ .add(Restrictions.eq("project.id", projectId))
+ .addOrder(Order.asc("testNo"))
+ .list();
+
+ if (results.isEmpty()) {
+ HibernateUtil.rollbackTransaction();
+ throw new NotFoundException("The project with the id " + projectId + " was not found.");
+ }
+ initializeLazyRelations(session, results, includeSteps);
// done
HibernateUtil.commitTransaction();
- return resultsAsJSON;
+ return results;
}
@Override
- public List getAllAsJSON(Long projectId, Long testNo) throws NotFoundException {
+ public List getAll(Long userId, Long projectId, Long[] testNos, boolean includeSteps)
+ throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
try {
- List result = getAllAsJSON(session, projectId, testNo);
+ List result = getAll(session, userId, projectId, testNos, includeSteps);
// done
HibernateUtil.commitTransaction();
@@ -114,167 +138,149 @@ public List getAllAsJSON(Long projectId, Long testNo) throws NotFoundExc
}
@Override
- public List> getAllAsJson(Long projectId, List testNos) throws NotFoundException {
+ public LearnerResult get(Long userId, Long projectId, Long testNo, boolean includeSteps) throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- List> result = new LinkedList<>();
-
try {
- for (Long testNo : testNos) {
- List stepsOfOneTestRun = getAllAsJSON(session, projectId, testNo);
- result.add(stepsOfOneTestRun);
- }
+ List result = getAll(session, userId, projectId, new Long[] {testNo}, includeSteps);
+
// done
HibernateUtil.commitTransaction();
- return result;
- } catch (NotFoundException e) {
+ return result.get(0);
+ } catch (NoSuchElementException e) {
HibernateUtil.rollbackTransaction();
throw e;
}
}
- private List getAllAsJSON(Session session, Long projectId, Long testNo) throws NotFoundException {
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
- throw new NotFoundException("The project with the id " + projectId + " was not found.");
- }
-
- // fetch the LearnerResults of the project with the the highest step no.
+ private List getAll(Session session, Long userId, Long projectId,
+ Long[] testNos, boolean includeSteps)
+ throws NotFoundException {
@SuppressWarnings("unchecked") // should return a list of LearnerResults
- List result = session.createCriteria(LearnerResult.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.eq("testNo", testNo))
- .setProjection(Projections.property("JSON"))
- .addOrder(Order.asc("stepNo"))
- .list();
-
- if (result.isEmpty()) {
- throw new NotFoundException("No result with the test no. " + testNo + " was found.");
- }
-
- // done
- return result;
- }
-
- @Override
- public LearnerResult get(Long projectId, Long testNo) throws NotFoundException {
- // start session
- Session session = HibernateUtil.getSession();
- HibernateUtil.beginTransaction();
+ List results = session.createCriteria(LearnerResult.class)
+ .add(Restrictions.eq("user.id", userId))
+ .add(Restrictions.eq("project.id", projectId))
+ .add(Restrictions.in("testNo", testNos))
+ .list();
- LearnerResult result = get(session, projectId, testNo);
+ if (results.size() != testNos.length) {
+ throw new NotFoundException("Not all results with the test nos. " + Arrays.toString(testNos)
+ + " for the user " + userId + "were found.");
+ }
+ initializeLazyRelations(session, results, includeSteps);
// done
- HibernateUtil.commitTransaction();
- return result;
+ return results;
}
- private LearnerResult get(Session session, Long projectId, Long testNo) throws NotFoundException {
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
- throw new NotFoundException("The project with the id " + projectId + " was not found.");
- }
-
- LearnerResult result = (LearnerResult) session.createCriteria(LearnerResult.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.eq("testNo", testNo))
- .add(Restrictions.eq("stepNo", 0L))
- .uniqueResult();
-
- if (result == null) {
- HibernateUtil.rollbackTransaction();
- throw new NotFoundException("The results with the test no. " + testNo + " in the project " + projectId
- + " was not found.");
+ private void initializeLazyRelations(Session session, List results, boolean includeSteps) {
+ results.forEach(r -> Hibernate.initialize(r.getResetSymbol()));
+ results.forEach(r -> Hibernate.initialize(r.getSymbols()));
+ if (includeSteps) {
+ results.forEach(r -> Hibernate.initialize(r.getSteps()));
+ } else {
+ results.forEach(r -> {
+ session.evict(r);
+ r.setSteps(null);
+ });
}
- return result;
}
@Override
- public String getAsJSON(Long projectId, Long testNo) throws NotFoundException {
+ public LearnerResultStep createStep(LearnerResult result)
+ throws ValidationException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
- throw new NotFoundException("The project with the id " + projectId + " was not found.");
- }
-
- String result = getAsJSON(session, projectId, testNo, 0L);
-
- if (result == null) {
+ LearnerResultStep latestStep = result.getSteps().get(result.getSteps().size() - 1);
+
+ LearnerResultStep newStep = new LearnerResultStep();
+ newStep.setUser(result.getUser());
+ newStep.setProject(result.getProject());
+ newStep.setResult(result);
+ newStep.setStepNo(latestStep.getStepNo() + 1);
+ newStep.setEqOracle(latestStep.getEqOracle());
+ if (latestStep.getStepsToLearn() > 0) {
+ newStep.setStepsToLearn(latestStep.getStepsToLearn() - 1);
+ } else if (latestStep.getStepsToLearn() == -1) {
+ newStep.setStepsToLearn(-1);
+ } else {
HibernateUtil.rollbackTransaction();
- throw new NotFoundException("The results with the test no. " + testNo + " in the project " + projectId
- + " was not found.");
+ throw new IllegalStateException("The previous step has a step to learn of 0 "
+ + "-> no new step can be crated!");
}
- // done
+ result.getSteps().add(newStep);
+ session.save(newStep);
+ session.update(result);
+
HibernateUtil.commitTransaction();
- return result;
+ return newStep;
}
@Override
- public String getAsJSON(Long projectId, Long testNo, Long stepNo) throws NotFoundException {
+ public LearnerResultStep createStep(LearnerResult result, LearnerResumeConfiguration configuration)
+ throws ValidationException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- if (ProjectDAOImpl.isProjectIdInvalid(projectId)) {
- throw new NotFoundException("The project with the id " + projectId + " was not found.");
- }
-
- String result = getAsJSON(session, projectId, testNo, stepNo);
+ // create the new step
+ LearnerResultStep newStep = new LearnerResultStep();
+ newStep.setUser(result.getUser());
+ newStep.setProject(result.getProject());
+ newStep.setResult(result);
+ newStep.setStepNo((long) result.getSteps().size());
+ newStep.setEqOracle(configuration.getEqOracle());
+ newStep.setStepsToLearn(configuration.getMaxAmountOfStepsToLearn());
- if (result == null) {
- throw new NotFoundException("The result with the test no. " + testNo
- + " and the step no. " + stepNo + " was not found.");
- }
+ result.getSteps().add(newStep);
+ session.save(newStep);
+ session.update(result);
- // done
HibernateUtil.commitTransaction();
- return result;
+ return newStep;
}
@Override
- public void update(LearnerResult learnerResult) throws NotFoundException, ValidationException {
+ public void saveStep(LearnerResult result, LearnerResultStep step) throws ValidationException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- learnerResult.setId(0L);
- learnerResult.setStepNo(learnerResult.getStepNo() + 1);
- session.save(learnerResult);
+ session.update(step);
- updateSummary(session, learnerResult);
+ updateSummary(result, step);
+ session.update(result);
- // done
HibernateUtil.commitTransaction();
}
- private void updateSummary(Session session, LearnerResult result) throws NotFoundException {
- LearnerResult summaryResult = get(session, result.getProjectId(), result.getTestNo());
- summaryResult.setErrorText(result.getErrorText());
- summaryResult.setHypothesis(result.getHypothesis());
+ private void updateSummary(LearnerResult result, LearnerResultStep step) {
+ result.setHypothesis(step.getHypothesis());
+ result.setErrorText(step.getErrorText());
- LearnerResult.Statistics summaryStatistics = summaryResult.getStatistics();
- LearnerResult.Statistics newStatistics = result.getStatistics();
+ Statistics summaryStatistics = result.getStatistics();
+ Statistics newStatistics = step.getStatistics();
summaryStatistics.setDuration(summaryStatistics.getDuration() + newStatistics.getDuration());
summaryStatistics.setMqsUsed(summaryStatistics.getMqsUsed() + newStatistics.getMqsUsed());
summaryStatistics.setSymbolsUsed(summaryStatistics.getSymbolsUsed() + newStatistics.getSymbolsUsed());
summaryStatistics.setEqsUsed(summaryStatistics.getEqsUsed() + newStatistics.getEqsUsed());
-
- session.update(summaryResult);
}
@Override
- public void delete(Long projectId, Long... testNo) throws NotFoundException, ValidationException {
- checkIfResultsCanBeDeleted(projectId, testNo); // check before the session is opened
+ public void delete(User user, Long projectId, Long... testNo) throws NotFoundException, ValidationException {
+ checkIfResultsCanBeDeleted(user, projectId, testNo); // check before the session is opened
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- List validTestNumbers = getTestNumbersInDB(session, projectId, testNo);
+ List validTestNumbers = getTestNumbersInDB(session, user.getId(), projectId, testNo);
Set diffSet = setDifference(Arrays.asList(testNo), validTestNumbers);
if (diffSet.size() > 0) {
throw new NotFoundException("The result with the number " + diffSet + " was not found, thus nothing could"
@@ -283,18 +289,26 @@ public void delete(Long projectId, Long... testNo) throws NotFoundException, Val
@SuppressWarnings("unchecked") // should always return a list of LernerResults
List results = session.createCriteria(LearnerResult.class)
+ .add(Restrictions.eq("user", user))
.add(Restrictions.eq("project.id", projectId))
.add(Restrictions.in("testNo", testNo))
.list();
+
results.forEach(session::delete);
// done
HibernateUtil.commitTransaction();
}
- private void checkIfResultsCanBeDeleted(Long projectId, Long... testNo) throws ValidationException {
+ private void checkIfResultsCanBeDeleted(User user, Long projectId, Long... testNo) throws ValidationException {
// don't delete the learnResult of the active learning process
- LearnerStatus status = new LearnerStatus(learner);
+ LearnerStatus status = learner.getStatus(user);
+
+ // user has no active thread -> no conflict possible
+ if (!status.isActive()) {
+ return;
+ }
+
Long activeTestNo = status.getTestNo();
Long activeProjectId = status.getProjectId();
@@ -313,21 +327,13 @@ private void checkIfResultsCanBeDeleted(Long projectId, Long... testNo) throws V
}
}
- private String getAsJSON(Session session, long projectId, long testNo, long stepNo) {
- return (String) session.createCriteria(LearnerResult.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.eq("testNo", testNo))
- .add(Restrictions.eq("stepNo", stepNo))
- .setProjection(Projections.property("JSON"))
- .uniqueResult();
- }
-
- private List getTestNumbersInDB(Session session, Long projectId, Long... testNo) {
+ private List getTestNumbersInDB(Session session, Long userId, Long projectId, Long... testNo) {
return session.createCriteria(LearnerResult.class)
- .add(Restrictions.eq("project.id", projectId))
- .add(Restrictions.in("testNo", testNo))
- .setProjection(Projections.distinct(Projections.property("testNo")))
- .list();
+ .add(Restrictions.eq("user.id", userId))
+ .add(Restrictions.eq("project.id", projectId))
+ .add(Restrictions.in("testNo", testNo))
+ .setProjection(Projections.distinct(Projections.property("testNo")))
+ .list();
}
private Set setDifference(Collection collectionA, Collection collectionB) {
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAO.java b/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAO.java
index 23b4498e2..727128393 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAO.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAO.java
@@ -1,6 +1,23 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.Project;
+import de.learnlib.alex.core.entities.User;
import de.learnlib.alex.exceptions.NotFoundException;
import javax.validation.ValidationException;
@@ -28,6 +45,9 @@ enum EmbeddableFields {
/** Flag to embed test results. */
TEST_RESULTS,
+ /** FLag to embed counters. */
+ COUNTERS,
+
/** Flag to embed everything. */
ALL;
@@ -53,7 +73,7 @@ public String toString() {
/**
* Save the given project.
- *
+ *
* @param project
* The project to be saved.
* @throws ValidationException
@@ -63,17 +83,20 @@ public String toString() {
/**
* Get a list of all the projects.
- *
+ * @param user
+ * The user of the project.
* @param embedFields
* The fields to include in returned project. By default no additional data will be fetched from the DB.
* @return All projects in a list.
*/
- List getAll(EmbeddableFields... embedFields);
+ List getAll(User user, EmbeddableFields... embedFields);
/**
* Get a specific project by its ID.
*
- * @param id
+ * @param userId
+ * The ID of the user.
+ * @param projectId
* The ID of the project to find.
* @param embedFields
* The fields to include in returned project. By default no additional data will be fetched from the DB.
@@ -81,11 +104,21 @@ public String toString() {
* @throws NotFoundException
* If the project could not be found.
*/
- Project getByID(long id, EmbeddableFields... embedFields) throws NotFoundException;
+ Project getByID(Long userId, Long projectId, EmbeddableFields... embedFields) throws NotFoundException;
+
+ /**
+ * Get a specific project by its ID.
+ * @param userId
+ * The ID of the user.
+ * @param projectName
+ * The name of the project.
+ * @return The project with the name.
+ */
+ Project getByName(Long userId, String projectName);
/**
* Update a project.
- *
+ *
* @param project
* The project to update.
* @throws NotFoundException
@@ -97,12 +130,14 @@ public String toString() {
/**
* Delete a project.
- *
- * @param id
- * The id of the project to delete.
+ *
+ * @param userId
+ * The id of the user.
+ * @param projectId
+ * The id of the project to delete.
* @throws NotFoundException
- * When the Project id was not found.
+ * When the Project id was not found.
*/
- void delete(long id) throws NotFoundException;
+ void delete(Long userId, Long projectId) throws NotFoundException;
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAOImpl.java b/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAOImpl.java
index ccfe0cce6..f35c4b290 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAOImpl.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/ProjectDAOImpl.java
@@ -1,17 +1,37 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.Project;
import de.learnlib.alex.core.entities.Symbol;
import de.learnlib.alex.core.entities.SymbolGroup;
+import de.learnlib.alex.core.entities.User;
import de.learnlib.alex.exceptions.NotFoundException;
import de.learnlib.alex.utils.HibernateUtil;
+import de.learnlib.alex.utils.ValidationExceptionHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.hibernate.Hibernate;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Session;
-import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
+import org.springframework.stereotype.Repository;
+import javax.inject.Inject;
import javax.validation.ValidationException;
import java.util.Arrays;
import java.util.Collections;
@@ -22,11 +42,26 @@
/**
* Implementation of a ProjectDAO using Hibernate.
*/
+@Repository
public class ProjectDAOImpl implements ProjectDAO {
/** Use the logger for the server part. */
private static final Logger LOGGER = LogManager.getLogger("server");
+ /** The SymbolDAO to use. */
+ private SymbolDAOImpl symbolDAO;
+
+ /**
+ * The constructor.
+ *
+ * @param symbolDAO
+ * The SymbolDAOImpl to use.
+ */
+ @Inject
+ public ProjectDAOImpl(SymbolDAOImpl symbolDAO) {
+ this.symbolDAO = symbolDAO;
+ }
+
@Override
public void create(Project project) throws ValidationException {
// start session
@@ -35,6 +70,7 @@ public void create(Project project) throws ValidationException {
try {
+ // TODO: fix this branch with multi user
if (project.getGroups().size() > 0) { // create new project from json with existing groups
Integer i = 0;
for (SymbolGroup group: project.getGroups()) {
@@ -64,6 +100,7 @@ public void create(Project project) throws ValidationException {
SymbolGroup defaultGroup = new SymbolGroup();
defaultGroup.setName("Default Group");
defaultGroup.setProject(project);
+ defaultGroup.setUser(project.getUser());
project.addGroup(defaultGroup);
project.setDefaultGroup(defaultGroup);
@@ -72,6 +109,7 @@ public void create(Project project) throws ValidationException {
symbol.setId(nextSymbolId);
symbol.setRevision(0L);
symbol.setProject(project);
+ symbol.setUser(project.getUser());
if (symbol.getGroup() == null) {
symbol.setGroup(defaultGroup);
}
@@ -83,27 +121,33 @@ public void create(Project project) throws ValidationException {
HibernateUtil.commitTransaction();
// error handling
- } catch (javax.validation.ConstraintViolationException
- | org.hibernate.exception.ConstraintViolationException e) {
+ } catch (javax.validation.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ LOGGER.info("Project creation failed:", e);
+ throw ValidationExceptionHelper.createValidationException("Project was not created:", e);
+ } catch (org.hibernate.exception.ConstraintViolationException e) {
HibernateUtil.rollbackTransaction();
+ LOGGER.info("Project creation failed:", e);
throw new javax.validation.ValidationException(
- "The Project was not created because it did not pass the validation!", e);
+ "The Project was not created: " + e.getMessage(), e);
}
}
@Override
- public List getAll(EmbeddableFields... embedFields) {
+ public List getAll(User user, EmbeddableFields... embedFields) {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
// get the Projects
@SuppressWarnings("unchecked") // it should be a list of Projects
- List result = session.createCriteria(Project.class).list();
+ List result = session.createCriteria(Project.class)
+ .add(Restrictions.eq("user", user))
+ .list();
// load lazy relations
for (Project p : result) {
- initLazyRelations(p, embedFields);
+ initLazyRelations(p, session, embedFields);
}
// done
@@ -112,28 +156,44 @@ public List getAll(EmbeddableFields... embedFields) {
}
@Override
- public Project getByID(long id, EmbeddableFields... embedFields) throws NotFoundException {
+ public Project getByID(Long userId, Long projectId, EmbeddableFields... embedFields) throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
// get the Project
- Project result = (Project) session.get(Project.class, id);
+ Project result = session.get(Project.class, projectId);
// load lazy relations
if (result != null) {
- initLazyRelations(result, embedFields);
+ initLazyRelations(result, session, embedFields);
}
// done
HibernateUtil.commitTransaction();
if (result == null) {
- throw new NotFoundException("Could not find the project with the id " + id + ".");
+ throw new NotFoundException("Could not find the project with the id " + projectId + ".");
}
return result;
}
+ @Override
+ public Project getByName(Long userId, String projectName) {
+ // start session
+ Session session = HibernateUtil.getSession();
+ HibernateUtil.beginTransaction();
+
+ Project result = (Project) session.createCriteria(Project.class)
+ .add(Restrictions.eq("user.id", userId))
+ .add(Restrictions.eq("name", projectName))
+ .uniqueResult();
+
+ HibernateUtil.commitTransaction();
+
+ return result;
+ }
+
@Override
public void update(Project project) throws NotFoundException, ValidationException {
// start session
@@ -141,7 +201,7 @@ public void update(Project project) throws NotFoundException, ValidationExceptio
HibernateUtil.beginTransaction();
try {
- Project projectInDB = (Project) session.load(Project.class, project.getId());
+ Project projectInDB = session.load(Project.class, project.getId());
// apply changes
projectInDB.setName(project.getName());
@@ -153,21 +213,24 @@ public void update(Project project) throws NotFoundException, ValidationExceptio
// error handling
} catch (ObjectNotFoundException e) {
- LOGGER.info("Project Update Failed:", e);
+ LOGGER.info("Project update failed:", e);
HibernateUtil.rollbackTransaction();
throw new NotFoundException("Could not find the project with the id " + project.getId() + ".", e);
- } catch (javax.validation.ConstraintViolationException
- | org.hibernate.exception.ConstraintViolationException e) {
- LOGGER.info("Project Update Failed:", e);
+ } catch (javax.validation.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ LOGGER.info("Project update failed:", e);
+ throw ValidationExceptionHelper.createValidationException("Project was not updated:", e);
+ } catch (org.hibernate.exception.ConstraintViolationException e) {
HibernateUtil.rollbackTransaction();
+ LOGGER.info("Project update failed:", e);
throw new javax.validation.ValidationException(
- "The Project was not updated because it did not pass the validation!", e);
+ "The Project was not updated: " + e.getMessage(), e);
}
}
@Override
- public void delete(long id) throws NotFoundException {
- Project project = getByID(id, EmbeddableFields.ALL);
+ public void delete(Long userId, Long projectId) throws NotFoundException {
+ Project project = getByID(userId, projectId, EmbeddableFields.ALL);
// start session
Session session = HibernateUtil.getSession();
@@ -183,46 +246,55 @@ public void delete(long id) throws NotFoundException {
/**
* Load objects that are connected with a project over a 'lazy' relation ship.
- *
* @param project
* The project which needs the 'lazy' objects.
+ * @param session
+ *
*/
- private void initLazyRelations(Project project, EmbeddableFields... embedFields) {
+ private void initLazyRelations(Project project, Session session, EmbeddableFields... embedFields) {
if (embedFields != null && embedFields.length > 0) {
Set fieldsToLoad = fieldsArrayToHashSet(embedFields);
if (fieldsToLoad.contains(EmbeddableFields.GROUPS)) {
- project.getGroups().forEach(group -> group.getSymbols().forEach(SymbolDAOImpl::loadLazyRelations));
+ project.getGroups().forEach(group -> group.getSymbols()
+ .forEach(s -> symbolDAO.loadLazyRelations(session, s)));
} else {
project.setGroups(null);
}
if (fieldsToLoad.contains(EmbeddableFields.DEFAULT_GROUP)) {
- project.getDefaultGroup();
- if (project.getDefaultGroup() != null) {
- project.getDefaultGroup().getSymbols().forEach(SymbolDAOImpl::loadLazyRelations);
- }
+ project.getDefaultGroup().getSymbols().forEach(s -> symbolDAO.loadLazyRelations(session, s));
} else {
project.setDefaultGroup(null);
}
if (fieldsToLoad.contains(EmbeddableFields.SYMBOLS)) {
- project.getSymbols().forEach(SymbolDAOImpl::loadLazyRelations);
+ project.getSymbols().forEach(s -> symbolDAO.loadLazyRelations(session, s));
} else {
project.setSymbols(null);
}
if (fieldsToLoad.contains(EmbeddableFields.TEST_RESULTS)) {
- project.getTestResults();
+ Hibernate.initialize(project.getTestResults());
} else {
project.setTestResults(null);
}
+
+ if (fieldsToLoad.contains(EmbeddableFields.COUNTERS)) {
+ Hibernate.initialize(project.getCounters());
+ } else {
+ project.setCounters(null);
+ }
} else {
project.setGroups(null);
project.setDefaultGroup(null);
project.setSymbols(null);
project.setTestResults(null);
+ project.setCounters(null);
}
+
+ // make sure that the "changes" of the project are never actually send to the db.
+ session.evict(project);
}
private Set fieldsArrayToHashSet(EmbeddableFields[] embedFields) {
@@ -232,28 +304,11 @@ private Set fieldsArrayToHashSet(EmbeddableFields[] embedField
fieldsToLoad.add(EmbeddableFields.DEFAULT_GROUP);
fieldsToLoad.add(EmbeddableFields.SYMBOLS);
fieldsToLoad.add(EmbeddableFields.TEST_RESULTS);
+ fieldsToLoad.add(EmbeddableFields.COUNTERS);
} else {
Collections.addAll(fieldsToLoad, embedFields);
}
return fieldsToLoad;
}
- /**
- * Checks if a project with the given project id exists.
- *
- * @param projectId
- * The project id to test.
- * @return true if the a project exits, false otherwise.
- */
- public static boolean isProjectIdInvalid(long projectId) {
- Session session = HibernateUtil.getSession();
-
- Long projectCount = (Long) session.createCriteria(Project.class)
- .add(Restrictions.eq("id", projectId))
- .setProjection(Projections.rowCount())
- .uniqueResult();
-
- return projectCount == 0;
- }
-
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAO.java b/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAO.java
index 71b43f4d7..bb5c9ee0b 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAO.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAO.java
@@ -1,8 +1,25 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.core.entities.IdRevisionPair;
import de.learnlib.alex.core.entities.Symbol;
import de.learnlib.alex.core.entities.SymbolVisibilityLevel;
+import de.learnlib.alex.core.entities.User;
import de.learnlib.alex.exceptions.NotFoundException;
import javax.validation.ValidationException;
@@ -15,11 +32,11 @@ public interface SymbolDAO {
/**
* Save the given symbol.
- *
+ *
* @param symbol
- * The symbol to save.
+ * The symbol to save.
* @throws ValidationException
- * When the symbol was not valid.
+ * When the symbol was not valid.
*/
void create(Symbol symbol) throws ValidationException;
@@ -27,16 +44,18 @@ public interface SymbolDAO {
* Save the given symbols.
*
* @param symbols
- * The symbols to save.
+ * The symbols to save.
* @throws ValidationException
- * When one the symbols was not valid.
- * In this case all symbols are reverted and not saved.
+ * When one the symbols was not valid.
+ * In this case all symbols are reverted and not saved.
*/
void create(List symbols) throws ValidationException;
/**
* Get a list of specific symbols of a project.
*
+ * @param user
+ * The owner of the symbols
* @param projectId
* The project the symbols should belong to.
* @param idRevPairs
@@ -45,27 +64,79 @@ public interface SymbolDAO {
* @throws NotFoundException
* If the project or one of the symbols could not be found.
*/
- List getAll(Long projectId, List idRevPairs) throws NotFoundException;
+ List getAll(User user, Long projectId, List idRevPairs) throws NotFoundException;
+
+ /**
+ * Get all symbols of a Project.
+ *
+ * @param user
+ * The user of the Symbols.
+ * @param projectID
+ * The project the Symbols should belong to.
+ * @param visibilityLevel
+ * Include symbols that are currently marked as hidden?
+ * @return A list of symbols belonging to the Project. Can be empty.
+ * @throws NotFoundException
+ * If the User or Project could not be found.
+ */
+ List getAllWithLatestRevision(User user, Long projectID, SymbolVisibilityLevel visibilityLevel)
+ throws NotFoundException;
- List getAllWithLatestRevision(Long projectId, Long groupId) throws NotFoundException;
+ /**
+ * Get a List of Symbols that are within a specific Group within a Project.
+ *
+ * @param user
+ * The user of the Symbols.
+ * @param projectId
+ * The Project of the Symbols.
+ * @param groupId
+ * The Group of the Symbols.
+ * @return A List of Symbols belonging to the Group. Can be empty.
+ * @throws NotFoundException
+ * If the User, Project or Group could not be found.
+ */
+ List getAllWithLatestRevision(User user, Long projectId, Long groupId)
+ throws NotFoundException;
- List getAllWithLatestRevision(Long projectId, Long groupId, SymbolVisibilityLevel visibilityLevel)
+ /**
+ * Get a List of Symbols that are withing a specific Group within a Project and have a specific visibility level.
+ *
+ * @param user
+ * The user of the Symbols.
+ * @param projectId
+ * The Project the Symbols.
+ * @param groupId
+ * The Group of the Symbols.
+ * @param visibilityLevel
+ * Only look for Symbols with the given visibility level.
+ * @return A List of Symbols belonging to the Group with the given VisibilityLevel. Can be empty.
+ * @throws NotFoundException
+ * If the User, Project or Group could not be found.
+ */
+ List getAllWithLatestRevision(User user, Long projectId,
+ Long groupId, SymbolVisibilityLevel visibilityLevel)
throws NotFoundException;
/**
* Get a list of symbols by their ids. Fetch only the latest revision of each.
*
+ * @param user
+ * The owner of the symbol
* @param projectId
* The project the symbols should belong to.
* @param ids
* The ids of the symbols you want to get.
* @return A list of symbols. Can be empty.
+ * @throws NotFoundException
+ * If no Symbol was found.
*/
- List getByIdsWithLatestRevision(Long projectId, Long... ids) throws NotFoundException;
+ List getByIdsWithLatestRevision(User user, Long projectId, Long... ids) throws NotFoundException;
/**
* Get a list of symbols by their ids. Fetch only the latest revision of each.
*
+ * @param user
+ * The owner of the symbol
* @param projectId
* The project the symbols should belong to.
* @param visibilityLevel
@@ -73,50 +144,75 @@ List getAllWithLatestRevision(Long projectId, Long groupId, SymbolVisibi
* @param ids
* The ids of the symbols you want to get.
* @return A list of symbols. Can be empty.
+ * @throws NotFoundException
+ * If no Symbol was found.
*/
- List getByIdsWithLatestRevision(Long projectId, SymbolVisibilityLevel visibilityLevel, Long... ids)
+ List getByIdsWithLatestRevision(User user, Long projectId,
+ SymbolVisibilityLevel visibilityLevel, Long... ids)
throws NotFoundException;
/**
- * Get all symbols of a project.
+ * Get a Symbol by the user, project and a Pair of an ID and a revision.
*
- * @param projectID
- * The project the symbols should belong to.
- * @param visibilityLevel
- * Include symbols that are currently marked as hidden?
- * @return A list of symbols belonging to the project.
+ * @param user
+ * The owner of the Symbol.
+ * @param projectId
+ * The ID of the project the symbol belongs to.
+ * @param idRevisionPair
+ * The ID and the Revision of the Symbol in the project.
+ * @return The Symbol.
+ * @throws NotFoundException
+ * If the Symbol could not be found.
*/
- List getAllWithLatestRevision(Long projectID, SymbolVisibilityLevel visibilityLevel)
- throws NotFoundException;
-
- Symbol get(Long projectId, IdRevisionPair idRevisionPair) throws NotFoundException;
+ Symbol get(User user, Long projectId, IdRevisionPair idRevisionPair) throws NotFoundException;
/**
* Get a specific symbol by its identifying parameters.
- *
+ *
+ * @param user
+ * The owner of the Symbol.
* @param projectId
- * The ID of the project the symbol belongs to.
+ * The ID of the project the symbol belongs to.
* @param id
- * The ID of the symbol itself in the project.
+ * The ID of the symbol itself in the project.
* @param revision
- * The wanted revision of the symbol.
+ * The wanted revision of the symbol.
* @return The Symbol or null.
+ * @throws NotFoundException
+ * If the Symbol was not found.
*/
- Symbol get(Long projectId, Long id, Long revision) throws NotFoundException;
+ Symbol get(User user, Long projectId, Long id, Long revision) throws NotFoundException;
/**
* Get a specific symbol by its identifying parameters and the last
* revision.
*
+ * @param user
+ * The owner of the Symbol.
* @param projectId
- * The ID of the project the symbol belongs to.
+ * The ID of the project the symbol belongs to.
* @param id
- * The ID of the symbol itself in the project.
+ * The ID of the symbol itself in the project.
* @return The Symbol or null.
+ * @throws NotFoundException
+ * If teh Symbols was not found.
*/
- Symbol getWithLatestRevision(Long projectId, Long id) throws NotFoundException;
+ Symbol getWithLatestRevision(User user, Long projectId, Long id) throws NotFoundException;
- List getWithAllRevisions(Long projectId, Long id) throws NotFoundException;
+ /**
+ * Get all Revisions of one Symbol.
+ *
+ * @param user
+ * The owner of the Symbol.
+ * @param projectId
+ * The Project the Symbol belongs to.
+ * @param id
+ * The ID of the Symbol within the Project.
+ * @return A List of all Revision. Sorted with the earliest in the beginning.
+ * @throws NotFoundException
+ * If the Symbol could not be found.
+ */
+ List getWithAllRevisions(User user, Long projectId, Long id) throws NotFoundException;
/**
* Update a symbol.
@@ -146,32 +242,59 @@ List getAllWithLatestRevision(Long projectID, SymbolVisibilityLevel visi
*/
void update(List symbols) throws IllegalArgumentException, NotFoundException, ValidationException;
+ /**
+ * Move a Symbol to a new Group.
+ * This does not increase the revision of the Symbol.
+ *
+ * @param symbol
+ * The Symbol to move.
+ * @param newGroupId
+ * The new Group.
+ * @throws NotFoundException
+ * If the Symbol or the Group could not be found.
+ */
void move(Symbol symbol, Long newGroupId) throws NotFoundException;
+ /**
+ * Moves a List of Symbols ot a new Group.
+ * This does not increase the revision of any Symbol.
+ * If one Symbol failed to be move, no Symbol will be moved.
+ *
+ * @param symbols
+ * The Symbol to move.
+ * @param newGroupId
+ * The new Group.
+ * @throws NotFoundException
+ * If at least one of the Symbols or if the Group could not be found.
+ */
void move(List symbols, Long newGroupId) throws NotFoundException;
/**
* Mark a symbol as hidden.
- *
+ *
+ * @param userId
+ * The ID of the user the symbols belongs to.
* @param projectId
- * The ID of the project the symbol belongs to.
+ * The ID of the project the symbol belongs to.
* @param ids
- * The IDs of the symbols to hide.
+ * The IDs of the symbols to hide.
* @throws NotFoundException
- * When the Symbol was not found.
+ * When the Symbol was not found.
*/
- void hide(Long projectId, Long... ids) throws NotFoundException;
+ void hide(Long userId, Long projectId, Long... ids) throws NotFoundException;
/**
* Revive a symbol from the hidden state.
*
+ * @param userId
+ * The ID of the user the symbols belongs to.
* @param projectId
- * The ID of the project the symbol belongs to.
+ * The ID of the project the symbol belongs to.
* @param ids
- * The ID of the symbols to show.
+ * The ID of the symbols to show.
* @throws NotFoundException
- * When the Symbol was not found.
+ * When the Symbol was not found.
*/
- void show(Long projectId, Long... ids) throws NotFoundException;
+ void show(Long userId, Long projectId, Long... ids) throws NotFoundException;
}
diff --git a/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAOImpl.java b/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAOImpl.java
index 3701e0b88..70d70217e 100644
--- a/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAOImpl.java
+++ b/main/src/main/java/de/learnlib/alex/core/dao/SymbolDAOImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2016 TU Dortmund
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package de.learnlib.alex.core.dao;
import de.learnlib.alex.actions.ExecuteSymbolAction;
@@ -7,17 +23,21 @@
import de.learnlib.alex.core.entities.SymbolAction;
import de.learnlib.alex.core.entities.SymbolGroup;
import de.learnlib.alex.core.entities.SymbolVisibilityLevel;
+import de.learnlib.alex.core.entities.User;
import de.learnlib.alex.exceptions.NotFoundException;
import de.learnlib.alex.utils.HibernateUtil;
+import de.learnlib.alex.utils.ValidationExceptionHelper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
-import org.hibernate.criterion.Junction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
+import org.springframework.stereotype.Repository;
import javax.validation.ValidationException;
import java.util.Arrays;
@@ -30,8 +50,12 @@
/**
* Implementation of a SymbolDAO using Hibernate.
*/
+@Repository
public class SymbolDAOImpl implements SymbolDAO {
+ /** Use the logger for the server part. */
+ private static final Logger LOGGER = LogManager.getLogger("server");
+
@Override
public void create(Symbol symbol) throws ValidationException {
// start session
@@ -44,9 +68,17 @@ public void create(Symbol symbol) throws ValidationException {
HibernateUtil.commitTransaction();
// error handling
- } catch (javax.validation.ConstraintViolationException
- | org.hibernate.exception.ConstraintViolationException
- | IllegalStateException e) {
+ } catch (javax.validation.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ symbol.setId(null);
+ symbol.setRevision(null);
+ throw ValidationExceptionHelper.createValidationException("Symbol was not created:", e);
+ } catch (org.hibernate.exception.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ symbol.setId(null);
+ symbol.setRevision(null);
+ throw new ValidationException("Symbol was not created: " + e.getMessage(), e);
+ } catch (IllegalStateException e) {
HibernateUtil.rollbackTransaction();
symbol.setId(null);
symbol.setRevision(null);
@@ -86,9 +118,21 @@ public void create(List symbols) throws ValidationException {
});
throw new ValidationException("Could not create a symbol because it has a reference to another"
+ " unknown symbol.", e);
- } catch (javax.validation.ConstraintViolationException
- | org.hibernate.exception.ConstraintViolationException
- | IllegalStateException e) {
+ } catch (javax.validation.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ symbols.forEach(s -> {
+ s.setId(null);
+ s.setRevision(null);
+ });
+ throw ValidationExceptionHelper.createValidationException("Symbols were not created:", e);
+ } catch (org.hibernate.exception.ConstraintViolationException e) {
+ HibernateUtil.rollbackTransaction();
+ symbols.forEach(s -> {
+ s.setId(null);
+ s.setRevision(null);
+ });
+ throw new ValidationException("Symbols were not created: " + e.getMessage(), e);
+ } catch (IllegalStateException e) {
HibernateUtil.rollbackTransaction();
symbols.forEach(s -> {
s.setId(null);
@@ -105,10 +149,7 @@ private void create(Session session, Symbol symbol) {
"To create a symbols it must have a Project but not haven an ID or and revision");
}
- Project project = (Project) session.load(Project.class, symbol.getProjectId());
-
- // test for unique constrains
- checkUniqueConstrains(session, symbol); // will throw exception if the symbol is invalid
+ Project project = session.load(Project.class, symbol.getProjectId());
// get the current highest symbol id in the project and add 1 for the next id
long id = project.getNextSymbolId();
@@ -120,10 +161,11 @@ private void create(Session session, Symbol symbol) {
symbol.setRevision(1L);
project.addSymbol(symbol);
- SymbolGroup group = (SymbolGroup) session.byNaturalId(SymbolGroup.class)
- .using("project", project)
- .using("id", symbol.getGroupId())
- .load();
+ SymbolGroup group = session.byNaturalId(SymbolGroup.class)
+ .using("user", symbol.getUser())
+ .using("project", project)
+ .using("id", symbol.getGroupId())
+ .load();
if (group == null) {
throw new ValidationException("The specified group was not found and thus the Symbol was not created.");
}
@@ -135,19 +177,29 @@ private void create(Session session, Symbol symbol) {
}
@Override
- public List getAll(Long projectId, List idRevPairs) throws NotFoundException {
+ public List getAll(User user, Long projectId, List idRevPairs) throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- List result = getAll(session, projectId, idRevPairs);
+ List result = getAll(session, user, projectId, idRevPairs);
// done
HibernateUtil.commitTransaction();
return result;
}
- List getAll(Session session, Long projectId, List idRevPairs) throws NotFoundException {
+ /**
+ * Like {@link #getAll(User, Long, List)}, but use a given Hibernate session.
+ * @param session The session to use.
+ * @param user The owner of the Symbols.
+ * @param projectId The project the symbols should belong to.
+ * @param idRevPairs A list of pairs of an ID and revisions to specify the expected symbols.
+ * @return A list of symbols matching the project and list of IDs and revisions.
+ * @throws NotFoundException If the project or one of the symbols could not be found.
+ */
+ List getAll(Session session, User user, Long projectId, List idRevPairs)
+ throws NotFoundException {
// no DB interaction if no symbols are requested
if (idRevPairs.isEmpty()) {
return new LinkedList<>();
@@ -159,6 +211,7 @@ List getAll(Session session, Long projectId, List idRevP
symbolIdRestrictions.add(Restrictions.eq("idRevisionPair", pair));
}
DetachedCriteria symbolIds = DetachedCriteria.forClass(Symbol.class)
+ .add(Restrictions.eq("user.id", user.getId()))
.add(Restrictions.eq("project.id", projectId))
.add(symbolIdRestrictions)
.setProjection(Projections.property("symbolId"));
@@ -176,48 +229,69 @@ List getAll(Session session, Long projectId, List idRevP
}
// load the lazy relations
- result.forEach(SymbolDAOImpl::loadLazyRelations);
+ result.forEach(s -> loadLazyRelations(session, s));
return result;
}
@Override
- public List getAllWithLatestRevision(Long projectId, Long groupId) throws NotFoundException {
- return getAllWithLatestRevision(projectId, groupId, SymbolVisibilityLevel.VISIBLE);
+ public List getAllWithLatestRevision(User user, Long projectId, Long groupId) throws NotFoundException {
+ return getAllWithLatestRevision(user, projectId, groupId, SymbolVisibilityLevel.VISIBLE);
}
@Override
- public List getAllWithLatestRevision(Long projectId, Long groupId, SymbolVisibilityLevel visibilityLevel)
+ public List getAllWithLatestRevision(User user, Long projectId,
+ Long groupId, SymbolVisibilityLevel visibilityLevel)
throws NotFoundException {
// start session
Session session = HibernateUtil.getSession();
HibernateUtil.beginTransaction();
- List idRevPairs = getIdRevisionPairs(session, projectId, groupId, visibilityLevel);
+ List idRevPairs = getIdRevisionPairs(session, user.getId(), projectId,
+ groupId, visibilityLevel);
HibernateUtil.commitTransaction();
if (idRevPairs.isEmpty()) {
return new LinkedList<>();
}
- return getAll(projectId, idRevPairs);
+ return getAll(user, projectId, idRevPairs);
}
- List getIdRevisionPairs(Session session,
- Long projectId,
- Long groupId,
- SymbolVisibilityLevel visibilityLevel) throws NotFoundException {
+ /**
+ * Get a List of IdRevisionPairs that describes all Symbols within a specific group,
+ * using the given Hibernate session.
+ *
+ * @param session
+ * The Session to use.
+ * @param userId
+ * The owner of the Symbols.
+ * @param projectId
+ * The Project that the Symbols are part of.
+ * @param groupId
+ * The Group in which the Symbols are in.
+ * @param visibilityLevel
+ * The visibility level of the Symbols.
+ * @return A List of IdRevisionPairs to represent the Symbols within a group.
+ * @throws NotFoundException
+ * If the group could not be found.
+ */
+ List getIdRevisionPairs(Session session, Long userId, Long projectId,
+ Long groupId, SymbolVisibilityLevel visibilityLevel)
+ throws NotFoundException {
SymbolGroup group = (SymbolGroup) session.createCriteria(SymbolGroup.class)
+ .add(Restrictions.eq("user.id", userId))
.add(Restrictions.eq("project.id", projectId))
.add(Restrictions.eq("id", groupId))
.uniqueResult();
if (group == null) {
- throw new NotFoundException("Could not find the group the id " + groupId
+ throw new NotFoundException("Could not find the group with the id " + groupId
+ " in the project " + projectId + ". ");
}
// get latest revision
List