├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── rusticisoftware │ └── tincan │ ├── About.java │ ├── Activity.java │ ├── ActivityDefinition.java │ ├── Agent.java │ ├── AgentAccount.java │ ├── Attachment.java │ ├── Context.java │ ├── ContextActivities.java │ ├── Extensions.java │ ├── Group.java │ ├── InteractionComponent.java │ ├── InteractionType.java │ ├── LRS.java │ ├── LanguageMap.java │ ├── Person.java │ ├── QueryResultFormat.java │ ├── QueryableStatementTarget.java │ ├── RemoteLRS.java │ ├── Result.java │ ├── Score.java │ ├── State.java │ ├── Statement.java │ ├── StatementRef.java │ ├── StatementTarget.java │ ├── StatementsQueryInterface.java │ ├── StatementsResult.java │ ├── SubStatement.java │ ├── TCAPIVersion.java │ ├── Verb.java │ ├── documents │ ├── ActivityProfileDocument.java │ ├── AgentProfileDocument.java │ ├── Document.java │ └── StateDocument.java │ ├── exceptions │ ├── IncompatibleTCAPIVersion.java │ ├── UnexpectedHTTPResponse.java │ └── UnrecognizedInteractionType.java │ ├── http │ ├── HTTPPart.java │ ├── HTTPRequest.java │ └── HTTPResponse.java │ ├── internal │ ├── MultipartParser.java │ └── StatementBase.java │ ├── json │ ├── JSON.java │ ├── JSONBase.java │ ├── Mapper.java │ └── StringOfJSON.java │ ├── lrsresponses │ ├── AboutLRSResponse.java │ ├── ActivityLRSResponse.java │ ├── ActivityProfileLRSResponse.java │ ├── AgentProfileLRSResponse.java │ ├── LRSResponse.java │ ├── PersonLRSResponse.java │ ├── ProfileKeysLRSResponse.java │ ├── StateLRSResponse.java │ ├── StatementLRSResponse.java │ └── StatementsResultLRSResponse.java │ ├── v095 │ └── StatementsQuery.java │ └── v10x │ └── StatementsQuery.java └── test ├── java └── com │ └── rusticisoftware │ └── tincan │ ├── ActivityDefinitionTest.java │ ├── ActivityTest.java │ ├── AgentAccountTest.java │ ├── AgentTest.java │ ├── AttachmentTest.java │ ├── ContextActivitiesTest.java │ ├── ContextTest.java │ ├── ExtensionsTest.java │ ├── GroupTest.java │ ├── InteractionComponentTest.java │ ├── InteractionTypeTest.java │ ├── LanguageMapTest.java │ ├── RemoteLRSTest.java │ ├── ResultTest.java │ ├── ScoreTest.java │ ├── StateTest.java │ ├── StatementRefTest.java │ ├── StatementTest.java │ ├── StatementsQueryTest.java │ ├── StatementsResultTest.java │ ├── SubStatementTest.java │ ├── TestUtils.java │ └── VerbTest.java └── resources ├── files └── image.jpg ├── lrs.properties.template └── travis-ci.properties /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .idea 3 | 4 | *.class 5 | 6 | # Properties 7 | src/test/resources/lrs.properties 8 | 9 | # Package Files # 10 | *.jar 11 | *.war 12 | *.ear 13 | 14 | # mvn goal products 15 | target/cobertura 16 | target/generated-classes 17 | target/generated-sources 18 | target/surefire 19 | target/surefire-reports 20 | target/site 21 | target/javadoc-bundle-options 22 | target/maven-archiver/ 23 | target/maven-status/maven-compiler-plugin 24 | target/test-classes/ 25 | 26 | .classpath 27 | .project 28 | .settings/ 29 | /target/ 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | TinCanJava 2 | Copyright 2013 Rustici Software 3 | 4 | This product includes software developed at 5 | Rustici Software (http://www.scorm.com/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A Java library for implementing the xAPI. 2 | 3 | For hosted API documentation, basic usage instructions, supported version listing, etc. visit the main project website at: 4 | 5 | http://rusticisoftware.github.io/TinCanJava/ 6 | 7 | For more information about the Experience API (xAPI) visit: 8 | 9 | http://xapi.com/ 10 | 11 | This library uses Maven 3 for project management, building, etc. It outputs Maven artifacts. 12 | 13 | Building 14 | -------- 15 | 16 | Check out the source: 17 | 18 | git clone https://github.com/RusticiSoftware/TinCanJava.git 19 | cd TinCanJava 20 | 21 | With the repo cloned copy the `src/test/resources/lrs.properties.template` file 22 | to `src/test/resources/lrs.properties` and adjust the values to point to a valid LRS. Then 23 | build the project using: 24 | 25 | mvn install 26 | 27 | This will download dependencies (that are not already locally available) and build and test the 28 | artifact. The result will be in `target/tincan-0.2.5-SNAPSHOT.jar`. To build a specific version 29 | of the library you will need to checkout to the tag for that version first, such as: 30 | 31 | git checkout tincan-0.2.4 32 | 33 | And then do `mvn install`, which will provide `target/tincan-0.2.4.jar`. 34 | 35 | Releasing 36 | --------- 37 | 38 | See http://maven.apache.org/maven-release/maven-release-plugin/index.html. 39 | 40 | mvn release:prepare -DdryRun=true 41 | mvn release:clean 42 | mvn release:prepare 43 | mvn release:perform 44 | 45 | At some point in the future we plan to make the maven artifacts available via some publicly 46 | available repository. 47 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.rusticisoftware 6 | tincan 7 | 1.1.3-SNAPSHOT 8 | Tin Can Java Library 9 | http://rusticisoftware.github.io/TinCanJava/ 10 | Library used to interact with Learning Record Stores (LRS) speaking the Tin Can API protocol. 11 | 12 | 13 | The Apache Software License, Version 2.0 14 | http://www.apache.org/licenses/LICENSE-2.0.txt 15 | manual 16 | A business-friendly OSS license 17 | 18 | 19 | 20 | Rustici Software 21 | http://tincanapi.com/ 22 | 23 | 24 | 25 | brianjmiller 26 | Brian J. Miller 27 | brian.miller@tincanapi.com 28 | Rustici Software 29 | http://tincanapi.com/ 30 | 31 | maintainer 32 | 33 | -5 34 | 35 | 36 | 37 | scm:git:https://github.com/RusticiSoftware/TinCanJava.git 38 | scm:git:git@github.com:RusticiSoftware/TinCanJava.git 39 | https://github.com/RusticiSoftware/TinCanJava 40 | HEAD 41 | 42 | 43 | 44 | 45 | org.owasp 46 | dependency-check-maven 47 | 6.4.1 48 | 49 | 50 | false 51 | false 52 | false 53 | 54 | 55 | 56 | 57 | check 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 66 | 1.8 67 | 1.8 68 | 1.8 69 | 70 | 3.3 71 | 72 | 89 | 90 | org.apache.maven.plugins 91 | maven-surefire-plugin 92 | 2.13 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-javadoc-plugin 97 | 2.9 98 | 99 | ${project.version} 100 | target/generated-sources/delombok 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-project-info-reports-plugin 106 | 2.6 107 | 108 | 109 | org.codehaus.mojo 110 | cobertura-maven-plugin 111 | 2.5.2 112 | 113 | 114 | maven-assembly-plugin 115 | 116 | 117 | jar-with-dependencies 118 | 119 | 120 | 121 | 122 | assemble-all 123 | package 124 | 125 | single 126 | 127 | 128 | 129 | 130 | 131 | org.apache.maven.plugins 132 | maven-release-plugin 133 | 2.4 134 | 135 | 136 | 137 | 138 | 139 | 140 | org.projectlombok 141 | lombok 142 | 1.18.22 143 | 144 | 145 | junit 146 | junit 147 | 4.13.2 148 | test 149 | 150 | 151 | com.fasterxml.jackson.core 152 | jackson-databind 153 | 2.12.5 154 | 155 | 156 | com.fasterxml.jackson.core 157 | jackson-annotations 158 | 2.12.5 159 | 160 | 161 | com.fasterxml.jackson.core 162 | jackson-core 163 | 2.12.5 164 | 165 | 166 | com.fasterxml.jackson.datatype 167 | jackson-datatype-joda 168 | 2.7.4 169 | 170 | 171 | commons-codec 172 | commons-codec 173 | 1.7 174 | 175 | 176 | joda-time 177 | joda-time 178 | 2.1 179 | 180 | 181 | org.eclipse.jetty 182 | jetty-client 183 | 9.4.44.v20210927 184 | 185 | 186 | org.eclipse.jetty 187 | jetty-servlet 188 | 9.4.44.v20210927 189 | 190 | 191 | 192 | 193 | UTF-8 194 | 195 | 196 | 197 | 198 | 199 | org.apache.maven.plugins 200 | maven-project-info-reports-plugin 201 | 2.6 202 | 203 | 204 | org.codehaus.mojo 205 | cobertura-maven-plugin 206 | 2.5.2 207 | 208 | 209 | 210 | html 211 | xml 212 | 213 | 214 | 215 | 216 | org.apache.maven.plugins 217 | maven-surefire-report-plugin 218 | 2.13 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/About.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ArrayNode; 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.rusticisoftware.tincan.json.JSONBase; 22 | import com.rusticisoftware.tincan.json.Mapper; 23 | import com.rusticisoftware.tincan.json.StringOfJSON; 24 | import lombok.Data; 25 | import lombok.EqualsAndHashCode; 26 | 27 | import java.io.IOException; 28 | import java.net.URISyntaxException; 29 | import java.util.ArrayList; 30 | import java.util.Iterator; 31 | import java.util.List; 32 | 33 | @Data 34 | @EqualsAndHashCode(callSuper = false) 35 | public class About extends JSONBase{ 36 | private List version; 37 | private Extensions extensions; 38 | 39 | public About(String str) throws IOException, URISyntaxException { 40 | StringOfJSON jsonStr = new StringOfJSON(str); 41 | init(jsonStr.toJSONNode()); 42 | } 43 | 44 | public About(StringOfJSON jsonStr) throws IOException, URISyntaxException{ 45 | init(jsonStr.toJSONNode()); 46 | } 47 | 48 | public About(JsonNode jsonNode) throws URISyntaxException{ 49 | init(jsonNode); 50 | } 51 | 52 | private void init(JsonNode jsonNode) throws URISyntaxException{ 53 | 54 | if(jsonNode.hasNonNull("version")) { 55 | 56 | Iterator it = jsonNode.get("version").elements(); 57 | 58 | while(it.hasNext()){ 59 | if(version == null) { version = new ArrayList(); } 60 | version.add(TCAPIVersion.fromString(((JsonNode)it.next()).textValue())); 61 | } 62 | } 63 | 64 | if(jsonNode.hasNonNull("extensions")) { 65 | extensions = new Extensions(jsonNode.get("extensions")); 66 | } 67 | } 68 | 69 | @Override 70 | public ObjectNode toJSONNode(TCAPIVersion v) { 71 | ObjectNode result = new ObjectNode(Mapper.getInstance().getNodeFactory()); 72 | if(!version.isEmpty()){ 73 | ArrayNode versions = Mapper.getInstance().createArrayNode(); 74 | for(TCAPIVersion tcapiVersion: this.getVersion()){ 75 | versions.add(tcapiVersion.toString()); 76 | } 77 | result.put("version", versions); 78 | } 79 | 80 | if(extensions != null){ 81 | result.put("extensions", extensions.toJSONNode()); 82 | } 83 | 84 | return result; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Activity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.io.IOException; 19 | import java.net.URI; 20 | import java.net.URISyntaxException; 21 | 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.NoArgsConstructor; 25 | 26 | import com.fasterxml.jackson.databind.JsonNode; 27 | import com.fasterxml.jackson.databind.node.ObjectNode; 28 | import com.rusticisoftware.tincan.json.JSONBase; 29 | import com.rusticisoftware.tincan.json.Mapper; 30 | import com.rusticisoftware.tincan.json.StringOfJSON; 31 | 32 | /** 33 | * Activity model class 34 | */ 35 | @Data 36 | @EqualsAndHashCode(callSuper = false) 37 | @NoArgsConstructor 38 | public class Activity extends JSONBase implements QueryableStatementTarget { 39 | private final String objectType = "Activity"; 40 | 41 | private URI id; 42 | private ActivityDefinition definition; 43 | 44 | public Activity(URI id) { 45 | this.id = id; 46 | } 47 | 48 | public Activity(String id) throws URISyntaxException { 49 | this(new URI(id)); 50 | } 51 | 52 | public Activity(JsonNode jsonNode) throws URISyntaxException { 53 | this(); 54 | 55 | JsonNode idNode = jsonNode.path("id"); 56 | if (! idNode.isMissingNode()) { 57 | this.setId(new URI(idNode.textValue())); 58 | } 59 | 60 | JsonNode definitionNode = jsonNode.path("definition"); 61 | if (! definitionNode.isMissingNode()) { 62 | this.setDefinition(new ActivityDefinition(definitionNode)); 63 | } 64 | } 65 | 66 | public Activity(String id, String name, String description) throws URISyntaxException { 67 | this(id); 68 | 69 | this.setDefinition(new ActivityDefinition(name, description)); 70 | } 71 | 72 | public Activity(StringOfJSON jsonStr) throws URISyntaxException, IOException { 73 | this(jsonStr.toJSONNode()); 74 | } 75 | 76 | @Override 77 | public ObjectNode toJSONNode(TCAPIVersion version) { 78 | ObjectNode node = Mapper.getInstance().createObjectNode(); 79 | node.put("objectType", this.getObjectType()); 80 | 81 | if (this.id != null) { 82 | node.put("id", this.getId().toString()); 83 | } 84 | if (this.definition != null) { 85 | node.put("definition", this.getDefinition().toJSONNode()); 86 | } 87 | 88 | return node; 89 | } 90 | 91 | public void setId(URI id) { 92 | this.id = id; 93 | } 94 | 95 | public void setId(String id) throws URISyntaxException { 96 | this.setId(new URI(id)); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/ActivityDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.InteractionType.getByString; 19 | 20 | import java.net.URI; 21 | import java.net.URISyntaxException; 22 | import java.util.ArrayList; 23 | import java.util.Iterator; 24 | 25 | import lombok.Data; 26 | import lombok.EqualsAndHashCode; 27 | import lombok.NoArgsConstructor; 28 | 29 | import com.fasterxml.jackson.databind.JsonNode; 30 | import com.fasterxml.jackson.databind.ObjectMapper; 31 | import com.fasterxml.jackson.databind.node.ArrayNode; 32 | import com.fasterxml.jackson.databind.node.ObjectNode; 33 | import com.rusticisoftware.tincan.json.JSONBase; 34 | import com.rusticisoftware.tincan.json.Mapper; 35 | 36 | /** 37 | * Activity Definition model class 38 | */ 39 | @Data 40 | @EqualsAndHashCode(callSuper = false) 41 | @NoArgsConstructor 42 | public class ActivityDefinition extends JSONBase { 43 | private LanguageMap name; 44 | private LanguageMap description; 45 | private URI type; 46 | private URI moreInfo; 47 | private Extensions extensions; 48 | private InteractionType interactionType; 49 | private ArrayList correctResponsesPattern; 50 | private ArrayList choices; 51 | private ArrayList scale; 52 | private ArrayList source; 53 | private ArrayList target; 54 | private ArrayList steps; 55 | 56 | public ActivityDefinition(JsonNode jsonNode) throws URISyntaxException { 57 | this(); 58 | 59 | JsonNode typeNode = jsonNode.path("type"); 60 | if (! typeNode.isMissingNode()) { 61 | this.setType(new URI(typeNode.textValue())); 62 | } 63 | 64 | JsonNode moreInfoNode = jsonNode.path("moreInfo"); 65 | if (! moreInfoNode.isMissingNode()) { 66 | this.setMoreInfo(new URI(moreInfoNode.textValue())); 67 | } 68 | 69 | JsonNode nameNode = jsonNode.path("name"); 70 | if (! nameNode.isMissingNode()) { 71 | this.setName(new LanguageMap(nameNode)); 72 | } 73 | 74 | JsonNode descNode = jsonNode.path("description"); 75 | if (! descNode.isMissingNode()) { 76 | this.setDescription(new LanguageMap(descNode)); 77 | } 78 | 79 | JsonNode extensionsNode = jsonNode.path("extensions"); 80 | if (! extensionsNode.isMissingNode()) { 81 | this.setExtensions(new Extensions(extensionsNode)); 82 | } 83 | 84 | JsonNode interactionTypeNode = jsonNode.path("interactionType"); 85 | InteractionType intType = null; 86 | if (! interactionTypeNode.isMissingNode()) { 87 | intType = getByString(interactionTypeNode.textValue()); 88 | this.setInteractionType(intType); 89 | } 90 | 91 | JsonNode correctResponsesPatternNode = jsonNode.path("correctResponsesPattern"); 92 | if (! correctResponsesPatternNode.isMissingNode()) { 93 | this.correctResponsesPattern = new ArrayList(); 94 | for (JsonNode element : correctResponsesPatternNode) { 95 | this.correctResponsesPattern.add(element.textValue()); 96 | } 97 | } 98 | 99 | JsonNode choicesNode = jsonNode.path("choices"); 100 | if (! choicesNode.isMissingNode()) { 101 | this.choices = new ArrayList(); 102 | for (JsonNode element : choicesNode) { 103 | this.choices.add(new InteractionComponent(element)); 104 | } 105 | } 106 | 107 | JsonNode scaleNode = jsonNode.path("scale"); 108 | if (! scaleNode.isMissingNode()) { 109 | this.scale = new ArrayList(); 110 | for (JsonNode element : scaleNode) { 111 | this.scale.add(new InteractionComponent(element)); 112 | } 113 | } 114 | 115 | JsonNode sourceNode = jsonNode.path("source"); 116 | if (! sourceNode.isMissingNode()) { 117 | this.source = new ArrayList(); 118 | for (JsonNode element : sourceNode) { 119 | this.source.add(new InteractionComponent(element)); 120 | } 121 | } 122 | 123 | JsonNode targetNode = jsonNode.path("target"); 124 | if (! targetNode.isMissingNode()) { 125 | this.target = new ArrayList(); 126 | for (JsonNode element : targetNode) { 127 | this.target.add(new InteractionComponent(element)); 128 | } 129 | } 130 | 131 | JsonNode stepsNode = jsonNode.path("steps"); 132 | if (! stepsNode.isMissingNode()) { 133 | this.steps = new ArrayList(); 134 | for (JsonNode element : stepsNode) { 135 | this.steps.add(new InteractionComponent(element)); 136 | } 137 | } 138 | } 139 | 140 | public ActivityDefinition(String name, String description) { 141 | this(); 142 | 143 | LanguageMap nameMap = new LanguageMap(); 144 | nameMap.put("und", name); 145 | this.setName(nameMap); 146 | 147 | LanguageMap descriptionMap = new LanguageMap(); 148 | descriptionMap.put("und", description); 149 | this.setDescription(descriptionMap); 150 | } 151 | 152 | @Override 153 | public ObjectNode toJSONNode(TCAPIVersion version) { 154 | ObjectMapper mapper = Mapper.getInstance(); 155 | ObjectNode node = mapper.createObjectNode(); 156 | if (this.name != null) { 157 | node.put("name", this.getName().toJSONNode(version)); 158 | } 159 | if (this.description != null) { 160 | node.put("description", this.getDescription().toJSONNode(version)); 161 | } 162 | if (this.type != null) { 163 | node.put("type", this.getType().toString()); 164 | } 165 | if (this.moreInfo != null) { 166 | node.put("moreInfo", this.getMoreInfo().toString()); 167 | } 168 | if (this.extensions != null) { 169 | node.put("extensions", this.getExtensions().toJSONNode(version)); 170 | } 171 | if (this.interactionType != null) { 172 | node.put("interactionType", this.getInteractionType().toString()); 173 | 174 | switch (this.interactionType) { 175 | case CHOICE: 176 | case SEQUENCING: 177 | if (this.choices != null && this.choices.size() > 0) { 178 | ArrayNode choices = mapper.createArrayNode(); 179 | node.put("choices", choices); 180 | 181 | for(InteractionComponent ic : this.getChoices()) { 182 | choices.add(ic.toJSONNode(version)); 183 | } 184 | } 185 | break; 186 | 187 | case LIKERT: 188 | if (this.scale != null && this.scale.size() > 0) { 189 | ArrayNode scale = mapper.createArrayNode(); 190 | node.put("scale", scale); 191 | 192 | for(InteractionComponent ic : this.getScale()) { 193 | scale.add(ic.toJSONNode(version)); 194 | } 195 | } 196 | break; 197 | 198 | case MATCHING: 199 | if (this.source != null && this.source.size() > 0) { 200 | ArrayNode source = mapper.createArrayNode(); 201 | node.put("source", source); 202 | 203 | for(InteractionComponent ic : this.getSource()) { 204 | source.add(ic.toJSONNode(version)); 205 | } 206 | } 207 | if (this.target != null && this.target.size() > 0) { 208 | ArrayNode target = mapper.createArrayNode(); 209 | node.put("target", target); 210 | 211 | for(InteractionComponent ic : this.getTarget()) { 212 | target.add(ic.toJSONNode(version)); 213 | } 214 | } 215 | break; 216 | 217 | case PERFORMANCE: 218 | if (this.steps != null && this.steps.size() > 0) { 219 | ArrayNode steps = mapper.createArrayNode(); 220 | node.put("steps", steps); 221 | 222 | for(InteractionComponent ic : this.getSteps()) { 223 | steps.add(ic.toJSONNode(version)); 224 | } 225 | } 226 | break; 227 | 228 | case TRUE_FALSE: 229 | case FILL_IN: 230 | case LONG_FILL_IN: 231 | case NUMERIC: 232 | case OTHER: 233 | break; 234 | } 235 | } 236 | if (this.correctResponsesPattern != null && this.correctResponsesPattern.size() > 0) { 237 | ArrayNode responses = mapper.createArrayNode(); 238 | node.put("correctResponsesPattern", responses); 239 | 240 | for(String resp : this.getCorrectResponsesPattern()) { 241 | responses.add(resp); 242 | } 243 | } 244 | return node; 245 | } 246 | 247 | public void setType(URI type) { 248 | this.type = type; 249 | } 250 | 251 | public void setType(String type) throws URISyntaxException { 252 | this.setType(new URI(type)); 253 | } 254 | 255 | public void setMoreInfo(URI moreInfo) { 256 | this.moreInfo = moreInfo; 257 | } 258 | 259 | public void setMoreInfo(String moreInfo) throws URISyntaxException { 260 | this.setMoreInfo(new URI(moreInfo)); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Agent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | import com.rusticisoftware.tincan.json.JSONBase; 24 | import com.rusticisoftware.tincan.json.Mapper; 25 | 26 | /** 27 | * Agent model class 28 | */ 29 | @Data 30 | @EqualsAndHashCode(callSuper = false) 31 | @NoArgsConstructor 32 | public class Agent extends JSONBase implements QueryableStatementTarget { 33 | protected final String objectType = "Agent"; 34 | private String name; 35 | private String mbox; 36 | private String mboxSHA1Sum; 37 | private String openID; 38 | private AgentAccount account; 39 | 40 | public static Agent fromJson(JsonNode jsonNode) { 41 | 42 | String objectType = "Agent"; 43 | JsonNode objectTypeNode = jsonNode.path("objectType"); 44 | if (! objectTypeNode.isMissingNode()) { 45 | objectType = objectTypeNode.textValue(); 46 | } 47 | 48 | return "Group".equals(objectType) ? new Group(jsonNode) : new Agent(jsonNode); 49 | } 50 | 51 | protected Agent(JsonNode jsonNode) { 52 | this(); 53 | 54 | JsonNode nameNode = jsonNode.path("name"); 55 | if (! nameNode.isMissingNode()) { 56 | this.setName(nameNode.textValue()); 57 | } 58 | 59 | JsonNode mboxNode = jsonNode.path("mbox"); 60 | if (! mboxNode.isMissingNode()) { 61 | this.setMbox(mboxNode.textValue()); 62 | } 63 | 64 | JsonNode mboxSHA1SumNode = jsonNode.path("mbox_sha1sum"); 65 | if (! mboxSHA1SumNode.isMissingNode()) { 66 | this.setMboxSHA1Sum(mboxSHA1SumNode.textValue()); 67 | } 68 | 69 | JsonNode openIDNode = jsonNode.path("openid"); 70 | if (! openIDNode.isMissingNode()) { 71 | this.setOpenID(openIDNode.textValue()); 72 | } 73 | 74 | JsonNode acctNode = jsonNode.path("account"); 75 | if (! acctNode.isMissingNode()) { 76 | this.setAccount(new AgentAccount(acctNode)); 77 | } 78 | } 79 | 80 | @Override 81 | public ObjectNode toJSONNode(TCAPIVersion version) { 82 | ObjectNode node = Mapper.getInstance().createObjectNode(); 83 | node.put("objectType", this.getObjectType()); 84 | 85 | if (this.name != null) { 86 | node.put("name", this.getName()); 87 | } 88 | if (this.mbox != null) { 89 | node.put("mbox", this.getMbox()); 90 | } 91 | if (this.mboxSHA1Sum != null) { 92 | node.put("mbox_sha1sum", this.getMboxSHA1Sum()); 93 | } 94 | if (this.openID != null) { 95 | node.put("openid", this.getOpenID()); 96 | } 97 | if (this.account != null) { 98 | node.put("account", this.getAccount().toJSONNode(version)); 99 | } 100 | 101 | return node; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/AgentAccount.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | import com.rusticisoftware.tincan.json.JSONBase; 24 | import com.rusticisoftware.tincan.json.Mapper; 25 | 26 | /** 27 | * Agent Account model class 28 | */ 29 | @Data 30 | @EqualsAndHashCode(callSuper = false) 31 | @NoArgsConstructor 32 | public class AgentAccount extends JSONBase { 33 | private String homePage; 34 | private String name; 35 | 36 | public AgentAccount(JsonNode jsonNode) { 37 | this(); 38 | 39 | JsonNode homePageNode = jsonNode.path("homePage"); 40 | if (! homePageNode.isMissingNode()) { 41 | this.setHomePage(homePageNode.textValue()); 42 | } 43 | 44 | JsonNode nameNode = jsonNode.path("name"); 45 | if (! nameNode.isMissingNode()) { 46 | this.setName(nameNode.textValue()); 47 | } 48 | } 49 | 50 | @Override 51 | public ObjectNode toJSONNode(TCAPIVersion version) { 52 | ObjectNode node = Mapper.getInstance().createObjectNode(); 53 | if (this.homePage != null) { 54 | node.put("homePage", this.getHomePage()); 55 | } 56 | if (this.name != null) { 57 | node.put("name", this.getName()); 58 | } 59 | 60 | return node; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Attachment.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.MalformedURLException; 19 | import java.net.URI; 20 | import java.net.URISyntaxException; 21 | import java.net.URL; 22 | import java.security.MessageDigest; 23 | import java.security.NoSuchAlgorithmException; 24 | import java.util.Arrays; 25 | import java.io.IOException; 26 | 27 | import com.fasterxml.jackson.databind.JsonNode; 28 | import com.fasterxml.jackson.databind.node.ObjectNode; 29 | import com.rusticisoftware.tincan.http.HTTPPart; 30 | import com.rusticisoftware.tincan.json.JSONBase; 31 | import com.rusticisoftware.tincan.json.Mapper; 32 | import org.apache.commons.codec.binary.Hex; 33 | 34 | import lombok.Data; 35 | import lombok.EqualsAndHashCode; 36 | import lombok.NoArgsConstructor; 37 | 38 | /** 39 | * Attachment Class 40 | */ 41 | @Data 42 | @EqualsAndHashCode(callSuper = false) 43 | @NoArgsConstructor 44 | public class Attachment extends JSONBase { 45 | private URI usageType; 46 | private LanguageMap display; 47 | private LanguageMap description; 48 | private String contentType; 49 | private Integer length; 50 | private String sha2; 51 | private URL fileUrl; 52 | private byte[] content; 53 | 54 | public Attachment(JsonNode jsonNode) throws URISyntaxException, MalformedURLException, IOException, NoSuchAlgorithmException { 55 | this(jsonNode, null); 56 | } 57 | 58 | public Attachment(JsonNode jsonNode, byte[] content) throws URISyntaxException, MalformedURLException, IOException, NoSuchAlgorithmException { 59 | JsonNode usageTypeNode = jsonNode.path("usageType"); 60 | if (! usageTypeNode.isMissingNode()) { 61 | this.setUsageType(new URI(usageTypeNode.textValue())); 62 | } 63 | 64 | JsonNode displayNode = jsonNode.path("display"); 65 | if (! displayNode.isMissingNode()) { 66 | this.setDisplay(new LanguageMap(displayNode)); 67 | } 68 | 69 | JsonNode descriptionNode = jsonNode.path("description"); 70 | if (! descriptionNode.isMissingNode()) { 71 | this.setDescription(new LanguageMap(descriptionNode)); 72 | } 73 | 74 | JsonNode contentTypeNode = jsonNode.path("contentType"); 75 | if (! contentTypeNode.isMissingNode()) { 76 | this.setContentType(contentTypeNode.textValue()); 77 | } 78 | 79 | JsonNode lengthNode = jsonNode.path("length"); 80 | if (! lengthNode.isMissingNode()) { 81 | this.setLength(lengthNode.intValue()); 82 | } 83 | 84 | JsonNode sha2Node = jsonNode.path("sha2"); 85 | if (! sha2Node.isMissingNode()) { 86 | this.setSha2(sha2Node.textValue()); 87 | } 88 | 89 | JsonNode fileUrlNode = jsonNode.path("fileUrl"); 90 | if (! fileUrlNode.isMissingNode()) { 91 | this.setFileUrl(new URL(fileUrlNode.textValue())); 92 | } 93 | 94 | if (content != null) { 95 | this.setContent(content); 96 | } 97 | } 98 | 99 | public void setContent(byte[] content) throws NoSuchAlgorithmException { 100 | this.content = Arrays.copyOf(content, content.length); 101 | this.setLength(content.length); 102 | MessageDigest digest = MessageDigest.getInstance("SHA-256"); 103 | digest.update(content); 104 | byte[] hash = digest.digest(); 105 | this.setSha2(new String(Hex.encodeHex(hash))); 106 | } 107 | 108 | @Override 109 | public ObjectNode toJSONNode(TCAPIVersion version) { 110 | ObjectNode node = Mapper.getInstance().createObjectNode(); 111 | if (this.getUsageType() != null) { 112 | node.put("usageType", this.getUsageType().toString()); 113 | } 114 | if (this.getDisplay() != null) { 115 | node.put("display", this.getDisplay().toJSONNode(version)); 116 | } 117 | if (this.getDescription() != null) { 118 | node.put("description", this.getDescription().toJSONNode(version)); 119 | } 120 | if (this.getContentType() != null) { 121 | node.put("contentType", this.getContentType()); 122 | } 123 | if (this.getLength() != null) { 124 | node.put("length", this.getLength()); 125 | } 126 | if (this.getSha2() != null) { 127 | node.put("sha2", this.getSha2()); 128 | } 129 | if (this.getFileUrl() != null) { 130 | node.put("fileUrl", this.getFileUrl().toString()); 131 | } 132 | return node; 133 | } 134 | 135 | public HTTPPart getPart() { 136 | HTTPPart part = new HTTPPart(); 137 | part.setContent(content); 138 | part.setContentType(contentType); 139 | part.setSha2(sha2); 140 | return part; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.MalformedURLException; 19 | import java.net.URISyntaxException; 20 | import java.util.UUID; 21 | 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.NoArgsConstructor; 25 | 26 | import com.fasterxml.jackson.databind.JsonNode; 27 | import com.fasterxml.jackson.databind.node.ObjectNode; 28 | import com.rusticisoftware.tincan.json.JSONBase; 29 | import com.rusticisoftware.tincan.json.Mapper; 30 | 31 | /** 32 | * Context Class Description 33 | */ 34 | @Data 35 | @EqualsAndHashCode(callSuper = false) 36 | @NoArgsConstructor 37 | public class Context extends JSONBase { 38 | private UUID registration; 39 | private Agent instructor; 40 | private Agent team; 41 | private ContextActivities contextActivities; 42 | private String revision; 43 | private String platform; 44 | private String language; 45 | private StatementRef statement; 46 | private Extensions extensions; 47 | 48 | public Context(JsonNode jsonNode) throws MalformedURLException, URISyntaxException { 49 | this(); 50 | 51 | JsonNode registrationNode = jsonNode.path("registration"); 52 | if (! registrationNode.isMissingNode()) { 53 | this.setRegistration(UUID.fromString(registrationNode.textValue())); 54 | } 55 | 56 | // TODO: check these for Group 57 | JsonNode instructorNode = jsonNode.path("instructor"); 58 | if (! instructorNode.isMissingNode()) { 59 | this.setInstructor(Agent.fromJson(instructorNode)); 60 | } 61 | 62 | JsonNode teamNode = jsonNode.path("team"); 63 | if (! teamNode.isMissingNode()) { 64 | this.setTeam(Agent.fromJson(teamNode)); 65 | } 66 | 67 | JsonNode contextActivitiesNode = jsonNode.path("contextActivities"); 68 | if (! contextActivitiesNode.isMissingNode()) { 69 | this.setContextActivities(new ContextActivities(contextActivitiesNode)); 70 | } 71 | 72 | JsonNode revisionNode = jsonNode.path("revision"); 73 | if (! revisionNode.isMissingNode()) { 74 | this.setRevision(revisionNode.textValue()); 75 | } 76 | 77 | JsonNode platformNode = jsonNode.path("platform"); 78 | if (! platformNode.isMissingNode()) { 79 | this.setPlatform(platformNode.textValue()); 80 | } 81 | 82 | JsonNode languageNode = jsonNode.path("language"); 83 | if (! languageNode.isMissingNode()) { 84 | this.setLanguage(languageNode.textValue()); 85 | } 86 | 87 | JsonNode statementNode = jsonNode.path("statement"); 88 | if (! statementNode.isMissingNode()) { 89 | this.setStatement(new StatementRef(statementNode)); 90 | } 91 | 92 | JsonNode extensionsNode = jsonNode.path("extensions"); 93 | if (! extensionsNode.isMissingNode()) { 94 | this.setExtensions(new Extensions(extensionsNode)); 95 | } 96 | } 97 | 98 | @Override 99 | public ObjectNode toJSONNode(TCAPIVersion version) { 100 | ObjectNode node = Mapper.getInstance().createObjectNode(); 101 | 102 | if (this.registration != null) { 103 | node.put("registration", this.getRegistration().toString()); 104 | } 105 | if (this.instructor != null) { 106 | node.put("instructor", this.getInstructor().toJSONNode(version)); 107 | } 108 | if (this.team != null) { 109 | node.put("team", this.getTeam().toJSONNode(version)); 110 | } 111 | if (this.contextActivities != null) { 112 | node.put("contextActivities", this.getContextActivities().toJSONNode(version)); 113 | } 114 | if (this.revision != null) { 115 | node.put("revision", this.getRevision()); 116 | } 117 | if (this.platform != null) { 118 | node.put("platform", this.getPlatform()); 119 | } 120 | if (this.language != null) { 121 | node.put("language", this.getLanguage()); 122 | } 123 | if (this.statement != null) { 124 | node.put("statement", this.getStatement().toJSONNode(version)); 125 | } 126 | if (this.extensions != null) { 127 | node.put("extensions", this.getExtensions().toJSONNode(version)); 128 | } 129 | 130 | return node; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/ContextActivities.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.URISyntaxException; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import lombok.Data; 23 | import lombok.EqualsAndHashCode; 24 | import lombok.NoArgsConstructor; 25 | 26 | import com.fasterxml.jackson.databind.JsonNode; 27 | import com.fasterxml.jackson.databind.ObjectMapper; 28 | import com.fasterxml.jackson.databind.node.ArrayNode; 29 | import com.fasterxml.jackson.databind.node.ObjectNode; 30 | import com.rusticisoftware.tincan.exceptions.IncompatibleTCAPIVersion; 31 | import com.rusticisoftware.tincan.json.JSONBase; 32 | import com.rusticisoftware.tincan.json.Mapper; 33 | 34 | /** 35 | * ContextActivities Model class 36 | */ 37 | @Data 38 | @EqualsAndHashCode(callSuper = false) 39 | @NoArgsConstructor 40 | public class ContextActivities extends JSONBase { 41 | private List parent; 42 | private List grouping; 43 | private List other; 44 | private List category; 45 | 46 | public ContextActivities(JsonNode jsonNode) throws URISyntaxException { 47 | this(); 48 | 49 | JsonNode parentNode = jsonNode.path("parent"); 50 | if (! parentNode.isMissingNode()) { 51 | this.parent = new ArrayList(); 52 | 53 | if (parentNode.isArray()) { 54 | for (JsonNode element : parentNode) { 55 | this.parent.add(new Activity(element)); 56 | } 57 | } 58 | else { 59 | this.parent.add(new Activity(parentNode)); 60 | } 61 | } 62 | 63 | JsonNode groupingNode = jsonNode.path("grouping"); 64 | if (! groupingNode.isMissingNode()) { 65 | this.grouping = new ArrayList(); 66 | 67 | if (groupingNode.isArray()) { 68 | for (JsonNode element : groupingNode) { 69 | this.grouping.add(new Activity(element)); 70 | } 71 | } 72 | else { 73 | this.grouping.add(new Activity(groupingNode)); 74 | } 75 | } 76 | 77 | JsonNode otherNode = jsonNode.path("other"); 78 | if (! otherNode.isMissingNode()) { 79 | this.other = new ArrayList(); 80 | 81 | if (otherNode.isArray()) { 82 | for (JsonNode element : otherNode) { 83 | this.other.add(new Activity(element)); 84 | } 85 | } 86 | else { 87 | this.other.add(new Activity(otherNode)); 88 | } 89 | } 90 | 91 | JsonNode categoryNode = jsonNode.path("category"); 92 | if (! categoryNode.isMissingNode()) { 93 | this.category = new ArrayList(); 94 | 95 | if (categoryNode.isArray()) { 96 | for (JsonNode element : categoryNode) { 97 | this.category.add(new Activity(element)); 98 | } 99 | } 100 | else { 101 | this.category.add(new Activity(categoryNode)); 102 | } 103 | } 104 | } 105 | 106 | @Override 107 | public ObjectNode toJSONNode(TCAPIVersion version) { 108 | ObjectMapper mapper = Mapper.getInstance(); 109 | ObjectNode node = mapper.createObjectNode(); 110 | 111 | if (this.parent != null && this.parent.size() > 0) { 112 | if (version.equals(TCAPIVersion.V095) && this.getParent().size() > 1) { 113 | throw new IncompatibleTCAPIVersion("Version " + TCAPIVersion.V095.toString() + " doesn't support lists of activities (parent)"); 114 | } 115 | 116 | if (version.equals(TCAPIVersion.V095)) { 117 | node.put("parent", this.getParent().get(0).toJSONNode(version)); 118 | } 119 | else { 120 | ArrayNode parent = mapper.createArrayNode(); 121 | node.put("parent", parent); 122 | 123 | for (Activity element : this.getParent()) { 124 | parent.add(element.toJSONNode(version)); 125 | } 126 | } 127 | } 128 | if (this.grouping != null && this.grouping.size() > 0) { 129 | if (version.equals(TCAPIVersion.V095) && this.getGrouping().size() > 1) { 130 | throw new IncompatibleTCAPIVersion("Version " + TCAPIVersion.V095.toString() + " doesn't support lists of activities (grouping)"); 131 | } 132 | 133 | if (version.equals(TCAPIVersion.V095)) { 134 | node.put("grouping", this.getGrouping().get(0).toJSONNode(version)); 135 | } 136 | else { 137 | ArrayNode grouping = mapper.createArrayNode(); 138 | node.put("grouping", grouping); 139 | 140 | for (Activity element : this.getGrouping()) { 141 | grouping.add(element.toJSONNode(version)); 142 | } 143 | } 144 | } 145 | if (this.other != null && this.other.size() > 0) { 146 | if (version.equals(TCAPIVersion.V095) && this.getOther().size() > 1) { 147 | throw new IncompatibleTCAPIVersion("Version " + TCAPIVersion.V095.toString() + " doesn't support lists of activities (other)"); 148 | } 149 | 150 | if (version.equals(TCAPIVersion.V095)) { 151 | node.put("other", this.getGrouping().get(0).toJSONNode(version)); 152 | } 153 | else { 154 | ArrayNode other = mapper.createArrayNode(); 155 | node.put("other", other); 156 | 157 | for (Activity element : this.getOther()) { 158 | other.add(element.toJSONNode(version)); 159 | } 160 | } 161 | } 162 | if (this.category != null && this.category.size() > 0) { 163 | if (version.ordinal() <= TCAPIVersion.V100.ordinal()) { 164 | ArrayNode category = mapper.createArrayNode(); 165 | node.put("category", category); 166 | 167 | for (Activity element : this.getCategory()) { 168 | category.add(element.toJSONNode(version)); 169 | } 170 | } else { 171 | throw new IncompatibleTCAPIVersion("Version " + version.toString() + " doesn't support the category context activity"); 172 | } 173 | } 174 | 175 | return node; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Extensions.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.io.IOException; 19 | import java.net.URI; 20 | import java.net.URISyntaxException; 21 | import java.util.HashMap; 22 | import java.util.Iterator; 23 | import java.util.Map; 24 | 25 | import lombok.NoArgsConstructor; 26 | 27 | import com.fasterxml.jackson.databind.JsonNode; 28 | import com.fasterxml.jackson.databind.node.ObjectNode; 29 | import com.rusticisoftware.tincan.json.JSONBase; 30 | import com.rusticisoftware.tincan.json.Mapper; 31 | import com.rusticisoftware.tincan.json.StringOfJSON; 32 | 33 | /** 34 | * Extensions model class 35 | */ 36 | @NoArgsConstructor 37 | public class Extensions extends JSONBase { 38 | private final HashMap _map = new HashMap(); 39 | 40 | public Extensions(JsonNode jsonNode) throws URISyntaxException { 41 | Iterator> items = jsonNode.fields(); 42 | while(items.hasNext()) { 43 | Map.Entry item = items.next(); 44 | 45 | this.put(new URI(item.getKey()), item.getValue()); 46 | } 47 | } 48 | 49 | public Extensions(StringOfJSON jsonStr) throws IOException, URISyntaxException { 50 | this(jsonStr.toJSONNode()); 51 | } 52 | 53 | public ObjectNode toJSONNode(TCAPIVersion version) { 54 | ObjectNode node = Mapper.getInstance().createObjectNode(); 55 | 56 | for (Map.Entry entry : this._map.entrySet()) { 57 | node.put(entry.getKey().toString(), entry.getValue()); 58 | } 59 | 60 | return node; 61 | } 62 | 63 | public Object put(URI key, JsonNode val) { 64 | return this._map.put(key, val); 65 | } 66 | 67 | public Object put(String key, JsonNode val) throws URISyntaxException { 68 | return this.put(new URI(key), val); 69 | } 70 | 71 | public Object put(URI key, Object val) { 72 | JsonNode storeVal = Mapper.getInstance().valueToTree(val); 73 | return this.put(key, storeVal); 74 | } 75 | 76 | public Object put(URI key, StringOfJSON val) { 77 | JsonNode storeVal = Mapper.getInstance().valueToTree(val); 78 | return this.put(key, storeVal); 79 | } 80 | 81 | public Object put(String key, Object val) throws URISyntaxException { 82 | return this.put(new URI(key), val); 83 | } 84 | 85 | public JsonNode get(URI key) { 86 | return this._map.get(key); 87 | } 88 | 89 | public JsonNode get(String key) throws URISyntaxException { 90 | return this.get(new URI(key)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Group.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Iterator; 20 | import java.util.List; 21 | 22 | import com.fasterxml.jackson.databind.JsonNode; 23 | import com.fasterxml.jackson.databind.node.ArrayNode; 24 | import com.fasterxml.jackson.databind.node.ObjectNode; 25 | import com.rusticisoftware.tincan.json.Mapper; 26 | 27 | import lombok.Data; 28 | import lombok.EqualsAndHashCode; 29 | 30 | /** 31 | * Group model class 32 | */ 33 | @Data 34 | @EqualsAndHashCode(callSuper = true) 35 | public class Group extends Agent { 36 | protected final String objectType = "Group"; 37 | private List members; 38 | 39 | public Group() { 40 | super(); 41 | } 42 | 43 | public Group(JsonNode jsonNode) { 44 | super(jsonNode); 45 | 46 | JsonNode memberNode = jsonNode.path("member"); 47 | if (! memberNode.isMissingNode()) { 48 | this.members = new ArrayList(); 49 | Iterator it = memberNode.elements(); 50 | while(it.hasNext()) { 51 | this.members.add(Agent.fromJson((JsonNode) it.next())); 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | public ObjectNode toJSONNode(TCAPIVersion version) { 58 | ObjectNode node = super.toJSONNode(version); 59 | if (this.getMembers() != null && this.getMembers().size() > 0) { 60 | ArrayNode memberNode = Mapper.getInstance().createArrayNode(); 61 | for (Agent member : this.getMembers()) { 62 | memberNode.add(member.toJSONNode(version)); 63 | } 64 | node.put("member", memberNode); 65 | } 66 | return node; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/InteractionComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | import com.rusticisoftware.tincan.json.JSONBase; 24 | import com.rusticisoftware.tincan.json.Mapper; 25 | 26 | /** 27 | * InteractionComponent Class Description 28 | */ 29 | @Data 30 | @EqualsAndHashCode(callSuper = false) 31 | @NoArgsConstructor 32 | public class InteractionComponent extends JSONBase { 33 | private String id; 34 | private LanguageMap description; 35 | 36 | public InteractionComponent(JsonNode jsonNode) { 37 | this(); 38 | 39 | JsonNode idNode = jsonNode.path("id"); 40 | if (! idNode.isMissingNode()) { 41 | this.setId(idNode.textValue()); 42 | } 43 | 44 | JsonNode descriptionNode = jsonNode.path("description"); 45 | if (! descriptionNode.isMissingNode()) { 46 | this.setDescription(new LanguageMap(descriptionNode)); 47 | } 48 | } 49 | 50 | @Override 51 | public ObjectNode toJSONNode(TCAPIVersion version) { 52 | ObjectNode node = Mapper.getInstance().createObjectNode(); 53 | if (this.id != null) { 54 | node.put("id", this.getId()); 55 | } 56 | if (this.description != null) { 57 | node.put("description", this.getDescription().toJSONNode(version)); 58 | } 59 | 60 | return node; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/InteractionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.rusticisoftware.tincan.exceptions.UnrecognizedInteractionType; 19 | 20 | /** 21 | * Possible interaction types 22 | */ 23 | public enum InteractionType { 24 | CHOICE("choice"), 25 | SEQUENCING("sequencing"), 26 | LIKERT("likert"), 27 | MATCHING("matching"), 28 | PERFORMANCE("performance"), 29 | TRUE_FALSE("true-false"), 30 | FILL_IN("fill-in"), 31 | LONG_FILL_IN("long-fill-in"), 32 | NUMERIC("numeric"), 33 | OTHER("other"); 34 | 35 | 36 | /** 37 | * @param text 38 | */ 39 | private InteractionType(final String text) { 40 | this.text = text; 41 | } 42 | 43 | private final String text; 44 | 45 | /* (non-Javadoc) 46 | * @see java.lang.Enum#toString() 47 | */ 48 | @Override 49 | public String toString() { 50 | return text; 51 | } 52 | 53 | public static InteractionType getByString(String type) throws UnrecognizedInteractionType { 54 | // TODO: cache this in a map to only do it once? 55 | for(InteractionType it : InteractionType.values()) { 56 | if (type.equals(it.toString())) { 57 | return it; 58 | } 59 | } 60 | throw new UnrecognizedInteractionType(type); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/LRS.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.rusticisoftware.tincan.documents.*; 19 | import com.rusticisoftware.tincan.lrsresponses.*; 20 | 21 | import java.util.List; 22 | import java.util.UUID; 23 | 24 | /** 25 | * Define the interface that must be satisfied to talk to an LRS 26 | */ 27 | public interface LRS { 28 | AboutLRSResponse about(); 29 | 30 | StatementLRSResponse saveStatement(Statement statement); 31 | StatementsResultLRSResponse saveStatements(List statements); 32 | StatementLRSResponse retrieveStatement(String id); 33 | StatementLRSResponse retrieveVoidedStatement(String id); 34 | StatementLRSResponse retrieveStatement(String id, boolean attachments); 35 | StatementLRSResponse retrieveVoidedStatement(String id, boolean attachments); 36 | StatementsResultLRSResponse queryStatements(StatementsQueryInterface query); 37 | StatementsResultLRSResponse moreStatements(String moreURL); 38 | 39 | ProfileKeysLRSResponse retrieveStateIds(Activity activity, Agent agent, UUID registration); 40 | StateLRSResponse retrieveState(String id, Activity activity, Agent agent, UUID registration); 41 | LRSResponse saveState(StateDocument state); 42 | LRSResponse updateState(StateDocument state); 43 | LRSResponse deleteState(StateDocument state); 44 | LRSResponse clearState(Activity activity, Agent agent, UUID registration); 45 | 46 | ActivityLRSResponse retrieveActivity(Activity activity); 47 | ProfileKeysLRSResponse retrieveActivityProfileIds(Activity activity); 48 | ActivityProfileLRSResponse retrieveActivityProfile(String id, Activity activity); 49 | LRSResponse saveActivityProfile(ActivityProfileDocument profile); 50 | LRSResponse updateActivityProfile(ActivityProfileDocument profile); 51 | LRSResponse deleteActivityProfile(ActivityProfileDocument profile); 52 | 53 | PersonLRSResponse retrievePerson(Agent agent); 54 | ProfileKeysLRSResponse retrieveAgentProfileIds(Agent agent); 55 | AgentProfileLRSResponse retrieveAgentProfile(String id, Agent agent); 56 | LRSResponse saveAgentProfile(AgentProfileDocument profile); 57 | LRSResponse updateAgentProfile(AgentProfileDocument profile); 58 | LRSResponse deleteAgentProfile(AgentProfileDocument profile); 59 | } -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/LanguageMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.NoArgsConstructor; 21 | import java.util.HashMap; 22 | import java.util.Iterator; 23 | import java.util.Map; 24 | import java.util.Map.Entry; 25 | import java.util.List; 26 | import java.util.ArrayList; 27 | 28 | import com.rusticisoftware.tincan.json.JSONBase; 29 | import com.rusticisoftware.tincan.json.Mapper; 30 | 31 | /** 32 | * Language map 33 | */ 34 | @NoArgsConstructor 35 | public class LanguageMap extends JSONBase implements Iterable> { 36 | private final HashMap _map = new HashMap(); 37 | 38 | private class LanguageMapIterator implements Iterator> { 39 | private Iterator> iterator; 40 | 41 | public LanguageMapIterator() { 42 | iterator = _map.entrySet().iterator(); 43 | } 44 | 45 | @Override 46 | public boolean hasNext() { 47 | return iterator.hasNext(); 48 | } 49 | 50 | @Override 51 | public Entry next() { 52 | return iterator.next(); 53 | } 54 | 55 | @Override 56 | public void remove() throws UnsupportedOperationException { 57 | throw new UnsupportedOperationException( 58 | "LanguageMap iterator does not implement the remove method" 59 | ); 60 | } 61 | } 62 | public LanguageMap(JsonNode jsonNode) { 63 | this(); 64 | 65 | Iterator> items = jsonNode.fields(); 66 | while(items.hasNext()) { 67 | Map.Entry item = items.next(); 68 | 69 | this.put(item.getKey(), item.getValue().textValue()); 70 | } 71 | } 72 | 73 | public ObjectNode toJSONNode(TCAPIVersion version) { 74 | ObjectNode node = Mapper.getInstance().createObjectNode(); 75 | 76 | for (Map.Entry entry : this._map.entrySet()) { 77 | node.put(entry.getKey(), entry.getValue()); 78 | } 79 | 80 | return node; 81 | } 82 | 83 | public String put(String key, String val) { 84 | return this._map.put(key, val); 85 | } 86 | 87 | public String put(Map.Entry entry) { 88 | return this.put(entry.getKey(), entry.getValue()); 89 | } 90 | 91 | public String get(String key) { 92 | return this._map.get(key); 93 | } 94 | 95 | public boolean containsKey(String key) { 96 | return this._map.containsKey(key); 97 | } 98 | 99 | public boolean containsValue(String value) { 100 | return this._map.containsValue(value); 101 | } 102 | 103 | public Map.Entry findFirstValue(String value) { 104 | Map.Entry retVal = null; 105 | Iterator> it = this.iterator(); 106 | while (it.hasNext()) { 107 | Map.Entry n = it.next(); 108 | if (n.getValue().equalsIgnoreCase(value)) { 109 | retVal = n; 110 | break; 111 | } 112 | } 113 | return retVal; 114 | } 115 | 116 | public void populateWithAvailableLanguages(List list) { 117 | Iterator> it = this.iterator(); 118 | while (it.hasNext()) { 119 | Map.Entry n = it.next(); 120 | list.add(n.getKey()); 121 | } 122 | } 123 | 124 | @Override 125 | public Iterator> iterator() { 126 | return new LanguageMapIterator(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import com.fasterxml.jackson.databind.node.ArrayNode; 21 | import com.fasterxml.jackson.databind.node.ObjectNode; 22 | import com.rusticisoftware.tincan.json.JSONBase; 23 | import com.rusticisoftware.tincan.json.Mapper; 24 | import com.rusticisoftware.tincan.json.StringOfJSON; 25 | import lombok.Data; 26 | import lombok.EqualsAndHashCode; 27 | import lombok.NoArgsConstructor; 28 | 29 | import java.io.IOException; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | /** 34 | * Person Model class 35 | */ 36 | @Data 37 | @EqualsAndHashCode(callSuper = false) 38 | @NoArgsConstructor 39 | public class Person extends JSONBase { 40 | protected final String objectType = "Person"; 41 | private List name; 42 | private List mbox; 43 | private List mbox_sha1sum; 44 | private List openid; 45 | private List account; 46 | 47 | public Person(StringOfJSON jsonStr) throws IOException { 48 | this(jsonStr.toJSONNode()); 49 | } 50 | 51 | public Person(JsonNode jsonNode) { 52 | this(); 53 | 54 | JsonNode nameNode = jsonNode.path("name"); 55 | if (! nameNode.isMissingNode()) { 56 | this.name = new ArrayList(); 57 | 58 | for (JsonNode element : nameNode) { 59 | this.name.add(element.textValue()); 60 | } 61 | } 62 | 63 | JsonNode mboxNode = jsonNode.path("mbox"); 64 | if (! mboxNode.isMissingNode()) { 65 | this.mbox = new ArrayList(); 66 | 67 | for (JsonNode element : mboxNode) { 68 | this.mbox.add(element.textValue()); 69 | } 70 | } 71 | 72 | JsonNode mbox_sha1sumNode = jsonNode.path("mbox_sha1sum"); 73 | if (! mbox_sha1sumNode.isMissingNode()) { 74 | this.mbox_sha1sum = new ArrayList(); 75 | 76 | for (JsonNode element : mbox_sha1sumNode) { 77 | this.mbox_sha1sum.add(element.textValue()); 78 | } 79 | } 80 | 81 | JsonNode openidNode = jsonNode.path("openid"); 82 | if (! openidNode.isMissingNode()) { 83 | this.openid = new ArrayList(); 84 | 85 | for (JsonNode element : openidNode) { 86 | this.openid.add(element.textValue()); 87 | } 88 | } 89 | 90 | JsonNode accountNode = jsonNode.path("account"); 91 | if (! accountNode.isMissingNode()) { 92 | this.account = new ArrayList(); 93 | 94 | for (JsonNode element : accountNode) { 95 | this.account.add(new AgentAccount(element)); 96 | } 97 | } 98 | } 99 | 100 | @Override 101 | public ObjectNode toJSONNode(TCAPIVersion version) { 102 | ObjectMapper mapper = Mapper.getInstance(); 103 | ObjectNode node = mapper.createObjectNode(); 104 | node.put("objectType", this.getObjectType()); 105 | 106 | if (this.name != null && this.name.size() > 0) { 107 | ArrayNode name = mapper.createArrayNode(); 108 | node.put("name", name); 109 | 110 | for (String element : this.getName()) { 111 | name.add(element); 112 | } 113 | } 114 | 115 | if (this.mbox != null && this.mbox.size() > 0) { 116 | ArrayNode mbox = mapper.createArrayNode(); 117 | node.put("mbox", mbox); 118 | 119 | for (String element : this.getMbox()) { 120 | mbox.add(element); 121 | } 122 | } 123 | 124 | if (this.mbox_sha1sum != null && this.mbox_sha1sum.size() > 0) { 125 | ArrayNode mbox_sha1sum = mapper.createArrayNode(); 126 | node.put("mbox_sha1sum", mbox_sha1sum); 127 | 128 | for (String element : this.getMbox_sha1sum()) { 129 | mbox_sha1sum.add(element); 130 | } 131 | } 132 | 133 | if (this.openid != null && this.openid.size() > 0) { 134 | ArrayNode openid = mapper.createArrayNode(); 135 | node.put("openid", openid); 136 | 137 | for (String element : this.getOpenid()) { 138 | openid.add(element); 139 | } 140 | } 141 | 142 | if (this.account != null && this.account.size() > 0) { 143 | ArrayNode account = mapper.createArrayNode(); 144 | node.put("account", account); 145 | 146 | for (AgentAccount element : this.getAccount()) { 147 | account.add(element.toJSONNode(version)); 148 | } 149 | } 150 | 151 | return node; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/QueryResultFormat.java: -------------------------------------------------------------------------------- 1 | package com.rusticisoftware.tincan; 2 | 3 | public enum QueryResultFormat { 4 | IDS, 5 | EXACT, 6 | CANONICAL 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/QueryableStatementTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Essentially empty interface to force type checking for objects of a statement that are queryable 22 | */ 23 | public interface QueryableStatementTarget extends StatementTarget { 24 | String toJSON(TCAPIVersion version) throws IOException; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Result.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.URISyntaxException; 19 | 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | 24 | import org.joda.time.Period; 25 | import org.joda.time.format.ISOPeriodFormat; 26 | 27 | import com.fasterxml.jackson.databind.JsonNode; 28 | import com.fasterxml.jackson.databind.ObjectMapper; 29 | import com.fasterxml.jackson.databind.node.ObjectNode; 30 | import com.rusticisoftware.tincan.json.JSONBase; 31 | import com.rusticisoftware.tincan.json.Mapper; 32 | 33 | /** 34 | * Result Model class 35 | */ 36 | @Data 37 | @EqualsAndHashCode(callSuper = false) 38 | @NoArgsConstructor 39 | public class Result extends JSONBase { 40 | private Score score; 41 | private Boolean success; 42 | private Boolean completion; 43 | private Period duration; 44 | private String response; 45 | private Extensions extensions; 46 | 47 | public Result(JsonNode jsonNode) throws URISyntaxException { 48 | this(); 49 | 50 | JsonNode scoreNode = jsonNode.path("score"); 51 | if (! scoreNode.isMissingNode()) { 52 | this.setScore(new Score(scoreNode)); 53 | } 54 | 55 | JsonNode successNode = jsonNode.path("success"); 56 | if (! successNode.isMissingNode()) { 57 | this.setSuccess(successNode.booleanValue()); 58 | } 59 | 60 | JsonNode completionNode = jsonNode.path("completion"); 61 | if (! completionNode.isMissingNode()) { 62 | this.setCompletion(completionNode.booleanValue()); 63 | } 64 | 65 | JsonNode durationNode = jsonNode.path("duration"); 66 | if (! durationNode.isMissingNode()) { 67 | this.setDuration(new Period(durationNode.textValue())); 68 | } 69 | 70 | JsonNode responseNode = jsonNode.path("response"); 71 | if (! responseNode.isMissingNode()) { 72 | this.setResponse(responseNode.textValue()); 73 | } 74 | 75 | JsonNode extensionsNode = jsonNode.path("extensions"); 76 | if (! extensionsNode.isMissingNode()) { 77 | this.setExtensions(new Extensions(extensionsNode)); 78 | } 79 | } 80 | 81 | @Override 82 | public ObjectNode toJSONNode(TCAPIVersion version) { 83 | ObjectMapper mapper = Mapper.getInstance(); 84 | ObjectNode node = mapper.createObjectNode(); 85 | 86 | if (this.score != null) { 87 | node.put("score", this.getScore().toJSONNode(version)); 88 | } 89 | if (this.success != null) { 90 | node.put("success", this.getSuccess()); 91 | } 92 | if (this.completion != null) { 93 | node.put("completion", this.getCompletion()); 94 | } 95 | if (this.duration != null) { 96 | // 97 | // ISOPeriodFormat includes milliseconds but the spec only allows 98 | // hundredths of a second here, so get the normal string, then truncate 99 | // the last digit to provide the proper precision 100 | // 101 | String shortenedDuration = ISOPeriodFormat.standard().print(this.getDuration()).replaceAll("(\\.\\d\\d)\\dS", "$1S"); 102 | 103 | node.put("duration", shortenedDuration); 104 | } 105 | if (this.response != null) { 106 | node.put("response", this.getResponse()); 107 | } 108 | if (this.extensions != null) { 109 | node.put("extensions", this.getExtensions().toJSONNode(version)); 110 | } 111 | 112 | return node; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Score.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | import com.rusticisoftware.tincan.json.JSONBase; 24 | import com.rusticisoftware.tincan.json.Mapper; 25 | 26 | /** 27 | * Score model class 28 | */ 29 | @Data 30 | @EqualsAndHashCode(callSuper = false) 31 | @NoArgsConstructor 32 | public class Score extends JSONBase { 33 | private Double scaled; 34 | private Double raw; 35 | private Double min; 36 | private Double max; 37 | 38 | public Score(JsonNode jsonNode) { 39 | this(); 40 | 41 | JsonNode scaledNode = jsonNode.path("scaled"); 42 | if (! scaledNode.isMissingNode()) { 43 | this.setScaled(scaledNode.doubleValue()); 44 | } 45 | 46 | JsonNode rawNode = jsonNode.path("raw"); 47 | if (! rawNode.isMissingNode()) { 48 | this.setRaw(rawNode.doubleValue()); 49 | } 50 | 51 | JsonNode minNode = jsonNode.path("min"); 52 | if (! minNode.isMissingNode()) { 53 | this.setMin(minNode.doubleValue()); 54 | } 55 | 56 | JsonNode maxNode = jsonNode.path("max"); 57 | if (! maxNode.isMissingNode()) { 58 | this.setMax(maxNode.doubleValue()); 59 | } 60 | } 61 | 62 | @Override 63 | public ObjectNode toJSONNode(TCAPIVersion version) { 64 | ObjectNode node = Mapper.getInstance().createObjectNode(); 65 | 66 | if (this.scaled != null) { 67 | node.put("scaled", this.getScaled()); 68 | } 69 | if (this.raw != null) { 70 | node.put("raw", this.getRaw()); 71 | } 72 | if (this.min != null) { 73 | node.put("min", this.getMin()); 74 | } 75 | if (this.max != null) { 76 | node.put("max", this.getMax()); 77 | } 78 | 79 | return node; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/State.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.URI; 19 | import java.net.URISyntaxException; 20 | import java.nio.charset.Charset; 21 | import java.util.UUID; 22 | 23 | import lombok.Data; 24 | import lombok.NoArgsConstructor; 25 | 26 | import org.joda.time.DateTime; 27 | 28 | /** 29 | * State Class 30 | */ 31 | @Data 32 | @NoArgsConstructor 33 | public class State { 34 | // TODO: need SHA1 of the contents? 35 | private String id; 36 | private DateTime updated; 37 | private byte[] contents; 38 | private Agent agent; 39 | private URI activityId; 40 | private UUID registration; 41 | 42 | public State(String id, byte[] contents, URI activityId, Agent agent, UUID registration) { 43 | this.setId(id); 44 | this.setContents(contents); 45 | this.setAgent(agent); 46 | this.setActivityId(activityId); 47 | this.setRegistration(registration); 48 | } 49 | 50 | public State(String id, byte[] contents, String activityId, Agent agent, UUID registration) throws URISyntaxException { 51 | this(id, contents, new URI(activityId), agent, registration); 52 | } 53 | 54 | public State(String id, byte[] contents, URI activityId, Agent agent) { 55 | this(id, contents, activityId, agent, null); 56 | } 57 | 58 | public State(String id, byte[] contents, String activityId, Agent agent) throws URISyntaxException { 59 | this(id, contents, new URI(activityId), agent, null); 60 | } 61 | 62 | public State(String id, String contents, URI activityId, Agent agent, UUID registration) { 63 | this(id, contents.getBytes(Charset.forName("UTF-8")), activityId, agent, registration); 64 | } 65 | 66 | public State(String id, String contents, String activityId, Agent agent, UUID registration) throws URISyntaxException { 67 | this(id, contents.getBytes(Charset.forName("UTF-8")), new URI(activityId), agent, registration); 68 | } 69 | 70 | public State(String id, String contents, URI activityId, Agent agent) { 71 | this(id, contents.getBytes(Charset.forName("UTF-8")), activityId, agent, null); 72 | } 73 | 74 | public State(String id, String contents, String activityId, Agent agent) throws URISyntaxException { 75 | this(id, contents.getBytes(Charset.forName("UTF-8")), new URI(activityId), agent, null); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Statement.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.io.IOException; 19 | import java.net.MalformedURLException; 20 | import java.net.URISyntaxException; 21 | import java.security.NoSuchAlgorithmException; 22 | import java.util.List; 23 | import java.util.UUID; 24 | 25 | import com.rusticisoftware.tincan.http.HTTPPart; 26 | import lombok.Data; 27 | import lombok.EqualsAndHashCode; 28 | import lombok.NoArgsConstructor; 29 | 30 | import org.joda.time.DateTime; 31 | import org.joda.time.format.DateTimeFormatter; 32 | import org.joda.time.format.ISODateTimeFormat; 33 | 34 | import com.fasterxml.jackson.databind.JsonNode; 35 | import com.fasterxml.jackson.databind.node.ObjectNode; 36 | import com.rusticisoftware.tincan.internal.StatementBase; 37 | import com.rusticisoftware.tincan.json.StringOfJSON; 38 | 39 | /** 40 | * Statement Class 41 | */ 42 | @Data 43 | @EqualsAndHashCode(callSuper = false) 44 | @NoArgsConstructor 45 | public class Statement extends StatementBase { 46 | private UUID id; 47 | private DateTime stored; 48 | private Agent authority; 49 | private TCAPIVersion version; 50 | 51 | @Deprecated 52 | private Boolean voided; 53 | 54 | public Statement(JsonNode jsonNode) throws URISyntaxException, MalformedURLException, IOException, NoSuchAlgorithmException { 55 | super(jsonNode); 56 | 57 | JsonNode idNode = jsonNode.path("id"); 58 | if (! idNode.isMissingNode()) { 59 | this.setId(UUID.fromString(idNode.textValue())); 60 | } 61 | 62 | JsonNode storedNode = jsonNode.path("stored"); 63 | if (! storedNode.isMissingNode()) { 64 | this.setStored(new DateTime(storedNode.textValue())); 65 | } 66 | 67 | JsonNode authorityNode = jsonNode.path("authority"); 68 | if (! authorityNode.isMissingNode()) { 69 | this.setAuthority(Agent.fromJson(authorityNode)); 70 | } 71 | 72 | JsonNode voidedNode = jsonNode.path("voided"); 73 | if (! voidedNode.isMissingNode()) { 74 | this.setVoided(voidedNode.asBoolean()); 75 | } 76 | 77 | JsonNode versionNode = jsonNode.path("version"); 78 | if (! versionNode.isMissingNode()) { 79 | this.setVersion(TCAPIVersion.fromString(versionNode.textValue())); 80 | } 81 | } 82 | 83 | public Statement(StringOfJSON jsonStr) throws IOException, URISyntaxException, NoSuchAlgorithmException { 84 | this(jsonStr.toJSONNode()); 85 | } 86 | 87 | public Statement(Agent actor, Verb verb, StatementTarget object, Result result, Context context) { 88 | super(actor, verb, object, result, context); 89 | } 90 | 91 | public Statement(Agent actor, Verb verb, StatementTarget object) { 92 | this(actor, verb, object, null, null); 93 | } 94 | 95 | @Override 96 | public ObjectNode toJSONNode(TCAPIVersion version) { 97 | ObjectNode node = super.toJSONNode(version); 98 | DateTimeFormatter fmt = ISODateTimeFormat.dateTime().withZoneUTC(); 99 | 100 | if (this.id != null) { 101 | node.put("id", this.getId().toString()); 102 | } 103 | if (this.stored != null) { 104 | node.put("stored", fmt.print(this.getStored())); 105 | } 106 | if (this.authority != null) { 107 | node.put("authority", this.getAuthority().toJSONNode(version)); 108 | } 109 | 110 | //Include 0.95 specific fields if asking for 0.95 version 111 | if (TCAPIVersion.V095.equals(version)) { 112 | if (this.getVoided() != null) { 113 | node.put("voided", this.getVoided()); 114 | } 115 | } 116 | 117 | //Include 1.0.x specific fields if asking for 1.0.x version 118 | if (version.ordinal() <= TCAPIVersion.V100.ordinal()) { 119 | if (this.getVersion() != null) { 120 | node.put("version", this.getVersion().toString()); 121 | } 122 | } 123 | 124 | return node; 125 | } 126 | 127 | /** 128 | * Method to set a random ID and the current date/time in the 'timestamp' 129 | */ 130 | public void stamp() { 131 | if (this.getId() == null) { 132 | this.setId(UUID.randomUUID()); 133 | } 134 | if (this.getTimestamp() == null) { 135 | this.setTimestamp(new DateTime()); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/StatementRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.node.ObjectNode; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import com.rusticisoftware.tincan.json.JSONBase; 23 | import com.rusticisoftware.tincan.json.Mapper; 24 | 25 | import java.net.URI; 26 | import java.net.URISyntaxException; 27 | import java.util.UUID; 28 | 29 | /** 30 | * StatementRef Class used when referencing another statement from a statement's 31 | * object property 32 | */ 33 | @Data 34 | @EqualsAndHashCode(callSuper = false) 35 | public class StatementRef extends JSONBase implements StatementTarget { 36 | private final String objectType = "StatementRef"; 37 | private UUID id; 38 | 39 | public StatementRef() { 40 | } 41 | 42 | public StatementRef (UUID id) { 43 | this.id = id; 44 | } 45 | 46 | public StatementRef(JsonNode jsonNode) throws URISyntaxException { 47 | this(); 48 | 49 | JsonNode idNode = jsonNode.path("id"); 50 | if (! idNode.isMissingNode()) { 51 | this.setId(UUID.fromString(idNode.textValue())); 52 | } 53 | } 54 | 55 | @Override 56 | public ObjectNode toJSONNode(TCAPIVersion version) { 57 | ObjectNode node = Mapper.getInstance().createObjectNode(); 58 | node.put("objectType", this.objectType); 59 | node.put("id", this.getId().toString()); 60 | return node; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/StatementTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | 20 | /** 21 | * Statement target interface for instances stored in the "object" property of a Statement 22 | */ 23 | public interface StatementTarget { 24 | String getObjectType(); 25 | 26 | JsonNode toJSONNode(TCAPIVersion version); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/StatementsQueryInterface.java: -------------------------------------------------------------------------------- 1 | package com.rusticisoftware.tincan; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | 6 | public interface StatementsQueryInterface { 7 | TCAPIVersion getVersion(); 8 | HashMap toParameterMap() throws IOException; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/StatementsResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.io.IOException; 19 | import java.net.MalformedURLException; 20 | import java.net.URISyntaxException; 21 | import java.security.NoSuchAlgorithmException; 22 | import java.util.ArrayList; 23 | import java.util.Iterator; 24 | 25 | import lombok.Data; 26 | import lombok.EqualsAndHashCode; 27 | import lombok.NoArgsConstructor; 28 | 29 | import com.fasterxml.jackson.databind.JsonNode; 30 | import com.fasterxml.jackson.databind.node.ArrayNode; 31 | import com.fasterxml.jackson.databind.node.ObjectNode; 32 | import com.rusticisoftware.tincan.json.JSONBase; 33 | import com.rusticisoftware.tincan.json.Mapper; 34 | import com.rusticisoftware.tincan.json.StringOfJSON; 35 | 36 | /** 37 | * Statements result model class, returned by LRS calls to get multiple statements 38 | */ 39 | @Data 40 | @EqualsAndHashCode(callSuper = false) 41 | @NoArgsConstructor 42 | public class StatementsResult extends JSONBase { 43 | private ArrayList statements = new ArrayList(); 44 | private String moreURL; 45 | 46 | public StatementsResult(JsonNode jsonNode) throws URISyntaxException, MalformedURLException, IOException, NoSuchAlgorithmException { 47 | this(); 48 | 49 | JsonNode statementsNode = jsonNode.path("statements"); 50 | if (! statementsNode.isMissingNode()) { 51 | for (JsonNode element : ((ArrayNode)statementsNode)) { 52 | this.statements.add(new Statement(element)); 53 | } 54 | } 55 | 56 | JsonNode moreURLNode = jsonNode.path("more"); 57 | if (! moreURLNode.isMissingNode()) { 58 | this.setMoreURL(moreURLNode.textValue()); 59 | } 60 | } 61 | 62 | public StatementsResult(StringOfJSON json) throws IOException, URISyntaxException, NoSuchAlgorithmException { 63 | this(json.toJSONNode()); 64 | } 65 | 66 | @Override 67 | public ObjectNode toJSONNode(TCAPIVersion version) { 68 | ObjectNode node = Mapper.getInstance().createObjectNode(); 69 | 70 | if (this.getStatements() != null) { 71 | ArrayNode statementsNode = Mapper.getInstance().createArrayNode(); 72 | for (Statement statement : this.getStatements()) { 73 | statementsNode.add(statement.toJSONNode(version)); 74 | } 75 | node.put("statements", statementsNode); 76 | } 77 | 78 | if (this.getMoreURL() != null) { 79 | node.put("more", this.getMoreURL()); 80 | } 81 | return node; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/SubStatement.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.MalformedURLException; 19 | import java.net.URISyntaxException; 20 | import java.io.IOException; 21 | import java.security.NoSuchAlgorithmException; 22 | 23 | import lombok.Data; 24 | import lombok.EqualsAndHashCode; 25 | import lombok.NoArgsConstructor; 26 | 27 | import com.fasterxml.jackson.databind.JsonNode; 28 | import com.fasterxml.jackson.databind.node.ObjectNode; 29 | import com.rusticisoftware.tincan.internal.StatementBase; 30 | import com.rusticisoftware.tincan.json.StringOfJSON; 31 | 32 | /** 33 | * SubStatement Class used when including a statement like object in another statement's 'object' property 34 | */ 35 | @Data 36 | @EqualsAndHashCode(callSuper = false) 37 | @NoArgsConstructor 38 | public class SubStatement extends StatementBase implements StatementTarget { 39 | private final String objectType = "SubStatement"; 40 | 41 | public SubStatement (JsonNode jsonNode) throws MalformedURLException, URISyntaxException, IOException, NoSuchAlgorithmException { 42 | super(jsonNode); 43 | } 44 | 45 | public SubStatement (StringOfJSON jsonStr) throws Exception { 46 | super(jsonStr); 47 | } 48 | 49 | @Override 50 | public ObjectNode toJSONNode(TCAPIVersion version) { 51 | ObjectNode node = super.toJSONNode(version); 52 | node.put("objectType", this.getObjectType()); 53 | return node; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/TCAPIVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | /** 19 | * Description 20 | */ 21 | public enum TCAPIVersion { 22 | V101("1.0.1"), 23 | V100("1.0.0"), 24 | V095("0.95"); 25 | 26 | /** 27 | * @param text 28 | */ 29 | private TCAPIVersion(final String text) { 30 | this.text = text; 31 | } 32 | 33 | private final String text; 34 | 35 | /* (non-Javadoc) 36 | * @see java.lang.Enum#toString() 37 | */ 38 | @Override 39 | public String toString() { 40 | return text; 41 | } 42 | 43 | public static TCAPIVersion latest() { 44 | return TCAPIVersion.values()[0]; 45 | } 46 | 47 | public static TCAPIVersion fromString(String text) { 48 | if (text != null) { 49 | for (TCAPIVersion v : TCAPIVersion.values()) { 50 | if (text.equalsIgnoreCase(v.text)) { 51 | return v; 52 | } 53 | } 54 | } 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/Verb.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import java.net.URI; 19 | import java.net.URISyntaxException; 20 | 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | import com.fasterxml.jackson.databind.JsonNode; 26 | import com.fasterxml.jackson.databind.node.ObjectNode; 27 | import com.rusticisoftware.tincan.json.JSONBase; 28 | import com.rusticisoftware.tincan.json.Mapper; 29 | 30 | /** 31 | * Verb model class 32 | */ 33 | @Data 34 | @EqualsAndHashCode(callSuper = false) 35 | @NoArgsConstructor 36 | public class Verb extends JSONBase { 37 | private URI id; 38 | private LanguageMap display; 39 | 40 | public Verb(URI id) { 41 | this.id = id; 42 | } 43 | 44 | public Verb(URI id, String display) { 45 | this(id); 46 | 47 | LanguageMap displayMap = new LanguageMap(); 48 | displayMap.put("und", display); 49 | this.setDisplay(displayMap); 50 | } 51 | 52 | public Verb(String id) throws URISyntaxException { 53 | this(new URI(id)); 54 | } 55 | 56 | public Verb(String id, String display) throws URISyntaxException { 57 | this(new URI(id), display); 58 | } 59 | 60 | public Verb(JsonNode jsonNode) throws URISyntaxException { 61 | this(); 62 | 63 | JsonNode idNode = jsonNode.path("id"); 64 | if (! idNode.isMissingNode()) { 65 | this.setId(new URI(idNode.textValue())); 66 | } 67 | 68 | JsonNode displayNode = jsonNode.path("display"); 69 | if (! displayNode.isMissingNode()) { 70 | this.setDisplay(new LanguageMap(displayNode)); 71 | } 72 | } 73 | 74 | @Override 75 | public ObjectNode toJSONNode(TCAPIVersion version) { 76 | ObjectNode node = Mapper.getInstance().createObjectNode(); 77 | if (this.id != null) { 78 | node.put("id", this.getId().toString()); 79 | } 80 | if (this.display != null) { 81 | node.put("display", this.getDisplay().toJSONNode(version)); 82 | } 83 | 84 | return node; 85 | } 86 | 87 | public void setId(URI id) { 88 | this.id = id; 89 | } 90 | 91 | public void setId(String id) throws URISyntaxException { 92 | this.setId(new URI(id)); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/documents/ActivityProfileDocument.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.documents; 17 | 18 | import com.rusticisoftware.tincan.Activity; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.NoArgsConstructor; 22 | 23 | @Data 24 | @EqualsAndHashCode(callSuper = false) 25 | @NoArgsConstructor 26 | public class ActivityProfileDocument extends Document { 27 | private Activity activity; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/documents/AgentProfileDocument.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.documents; 17 | 18 | import com.rusticisoftware.tincan.Agent; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.NoArgsConstructor; 22 | 23 | @Data 24 | @EqualsAndHashCode(callSuper = false) 25 | @NoArgsConstructor 26 | public class AgentProfileDocument extends Document{ 27 | private Agent agent; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/documents/Document.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.documents; 17 | 18 | import lombok.Data; 19 | import lombok.EqualsAndHashCode; 20 | import lombok.NoArgsConstructor; 21 | import org.joda.time.DateTime; 22 | 23 | @Data 24 | @EqualsAndHashCode(callSuper = false) 25 | @NoArgsConstructor 26 | public class Document { 27 | private String id; 28 | private String etag; 29 | private DateTime timestamp; 30 | private String contentType; 31 | private byte[] content; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/documents/StateDocument.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.documents; 17 | 18 | import com.rusticisoftware.tincan.Activity; 19 | import com.rusticisoftware.tincan.Agent; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.util.UUID; 25 | 26 | @Data 27 | @EqualsAndHashCode(callSuper = false) 28 | @NoArgsConstructor 29 | public class StateDocument extends Document{ 30 | private Activity activity; 31 | private Agent agent; 32 | private UUID registration; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/exceptions/IncompatibleTCAPIVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.exceptions; 17 | 18 | /** 19 | * IncompatibleTCAPIVersion 20 | */ 21 | public class IncompatibleTCAPIVersion extends RuntimeException { 22 | public IncompatibleTCAPIVersion(String message) { 23 | super(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/exceptions/UnexpectedHTTPResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.exceptions; 17 | 18 | import com.rusticisoftware.tincan.http.HTTPResponse; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | 22 | /** 23 | * UnexpectedHTTPResponse 24 | */ 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | public class UnexpectedHTTPResponse extends RuntimeException { 28 | private HTTPResponse response; 29 | 30 | public UnexpectedHTTPResponse(String message, HTTPResponse response) { 31 | super(message); 32 | this.setResponse(response); 33 | } 34 | 35 | public UnexpectedHTTPResponse(HTTPResponse response) { 36 | this("Unexpected HTTP Response", response); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | HTTPResponse response = this.getResponse(); 42 | 43 | return super.toString() 44 | + ", HTTP status: " 45 | + response.getStatus() 46 | + ", HTTP response: " 47 | + (response.isBinary() ? "binary" : response.getContent().substring(0, (response.getContent().length() > 1000 ? 1000 : response.getContent().length()))) 48 | ; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/exceptions/UnrecognizedInteractionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.exceptions; 17 | 18 | /** 19 | * UnrecognizedInteractionType 20 | */ 21 | public class UnrecognizedInteractionType extends RuntimeException { 22 | public UnrecognizedInteractionType(String message) { 23 | super(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/http/HTTPPart.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.http; 17 | 18 | import lombok.Data; 19 | import lombok.EqualsAndHashCode; 20 | import lombok.NoArgsConstructor; 21 | 22 | @Data 23 | @EqualsAndHashCode(callSuper = false) 24 | @NoArgsConstructor 25 | public class HTTPPart { 26 | private String sha2; 27 | private String contentType; 28 | private byte[] content; 29 | } -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/http/HTTPRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.http; 17 | 18 | import com.rusticisoftware.tincan.Attachment; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import javax.servlet.http.Part; 22 | 23 | import java.util.List; 24 | import java.util.Map; 25 | 26 | /** 27 | * HTTPRequest Class Description 28 | */ 29 | @Data 30 | @EqualsAndHashCode(callSuper = false) 31 | public class HTTPRequest { 32 | private String method; 33 | private String resource; 34 | private Map queryParams; 35 | private Map headers; 36 | private String contentType; 37 | private byte[] content; 38 | private HTTPResponse response; 39 | private List partList; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/http/HTTPResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.http; 17 | 18 | import lombok.Data; 19 | import lombok.NoArgsConstructor; 20 | import org.joda.time.DateTime; 21 | import org.joda.time.format.DateTimeFormat; 22 | import org.joda.time.format.DateTimeFormatter; 23 | 24 | import java.util.HashMap; 25 | import java.util.List; 26 | 27 | /** 28 | * HTTPResponse Class Description 29 | */ 30 | @Data 31 | @NoArgsConstructor 32 | public class HTTPResponse { 33 | private int status; 34 | private String statusMsg; 35 | private final HashMap headers = new HashMap(); 36 | private byte[] contentBytes; 37 | private List partList; 38 | private HashMap attachments = new HashMap(); 39 | 40 | public String getHeader(String key) { 41 | return this.headers.get(key); 42 | } 43 | public void setHeader(String key, String val) { 44 | this.headers.put(key, val); 45 | } 46 | 47 | public byte[] getAttachment(String key) { return this.attachments.get(key); } 48 | public void setAttachment(String key, byte[] val) { this.attachments.put(key, val); } 49 | 50 | public String getContent() { 51 | return new String(this.getContentBytes()); 52 | } 53 | 54 | public String getContentType() { return this.getHeader("Content-Type"); } 55 | public String getEtag() { 56 | String etag = this.getHeader("ETag"); 57 | if (etag == null) { 58 | return etag; 59 | } 60 | 61 | return etag.toLowerCase(); 62 | } 63 | public DateTime getLastModified() { 64 | DateTimeFormatter RFC1123_DATE_TIME_FORMATTER = 65 | DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC(); 66 | try { 67 | return DateTime.parse(this.getHeader("Last-Modified"), RFC1123_DATE_TIME_FORMATTER); 68 | } 69 | catch (Exception parseException) { 70 | return null; 71 | } 72 | } 73 | 74 | public Boolean isBinary() { 75 | String contentType = this.getContentType(); 76 | if (contentType == null) { 77 | return false; 78 | } 79 | contentType = contentType.toLowerCase(); 80 | 81 | if (contentType.contains("json") || contentType.contains("xml") || contentType.contains("text")) { 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/internal/MultipartParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.internal; 17 | 18 | import java.io.*; 19 | import java.util.*; 20 | import lombok.Data; 21 | import org.eclipse.jetty.util.IO; 22 | 23 | 24 | @Data 25 | public class MultipartParser { 26 | private byte[] boundary; 27 | private byte[] finalBoundary; 28 | private byte[] content; 29 | private byte[] responseContent; 30 | private HashMap headers = new HashMap(); 31 | private ArrayList sections = new ArrayList(); 32 | private final byte[] CONTENT_DELIMITER = ("\r\n\r\n").getBytes(); 33 | 34 | public MultipartParser(byte[] responseContent, String boundary) throws IOException { 35 | this.responseContent = responseContent; 36 | this.boundary = ("--" + boundary).getBytes(); 37 | this.finalBoundary = ("--" + boundary + "--").getBytes(); 38 | splitIntoParts(); 39 | } 40 | 41 | /** 42 | * Code to find the index of a particular byte[] inside a larger byte[] 43 | * `indexOf` and `computeFailure` taken from StackOverflow user janko. Original response can be found at this link: 44 | * https://stackoverflow.com/questions/1507780/searching-for-a-sequence-of-bytes-in-a-binary-file-with-java 45 | */ 46 | private int indexOf(byte[] data, byte[] pattern) { 47 | int[] failure = computeFailure(pattern); 48 | 49 | int j = 0; 50 | if (data.length == 0) return -1; 51 | 52 | for (int i = 0; i < data.length; i++) { 53 | while (j > 0 && pattern[j] != data[i]) { 54 | j = failure[j - 1]; 55 | } 56 | if (pattern[j] == data[i]) { j++; } 57 | if (j == pattern.length) { 58 | return i - pattern.length + 1; 59 | } 60 | } 61 | return -1; 62 | } 63 | 64 | /** 65 | * Computes the failure function using a boot-strapping process, 66 | * where the pattern is matched against itself. 67 | */ 68 | private int[] computeFailure(byte[] pattern) { 69 | int[] failure = new int[pattern.length]; 70 | 71 | int j = 0; 72 | for (int i = 1; i < pattern.length; i++) { 73 | while (j > 0 && pattern[j] != pattern[i]) { 74 | j = failure[j - 1]; 75 | } 76 | if (pattern[j] == pattern[i]) { 77 | j++; 78 | } 79 | failure[i] = j; 80 | } 81 | 82 | return failure; 83 | } 84 | 85 | private void splitIntoParts() { 86 | byte[] beforeFinalBoundary = Arrays.copyOfRange(responseContent, 0, indexOf(responseContent, finalBoundary)); 87 | 88 | int index; 89 | while ((index = indexOf(beforeFinalBoundary, boundary)) >= 0) { 90 | sections.add(Arrays.copyOfRange(beforeFinalBoundary, 0, index)); 91 | beforeFinalBoundary = Arrays.copyOfRange(beforeFinalBoundary, index + this.boundary.length, beforeFinalBoundary.length); 92 | } 93 | while (beforeFinalBoundary[beforeFinalBoundary.length - 1] == (byte) '\n' || beforeFinalBoundary[beforeFinalBoundary.length - 1] == (byte) '\r') { 94 | beforeFinalBoundary = Arrays.copyOfRange(beforeFinalBoundary, 0, beforeFinalBoundary.length - 1); 95 | } 96 | sections.add(beforeFinalBoundary); 97 | } 98 | 99 | private ArrayList splitDelimited(byte[] original, byte[] delimiter) { 100 | ArrayList parts = new ArrayList(); 101 | 102 | int index; 103 | while ((index = indexOf(original, delimiter)) >= 0) { 104 | parts.add(Arrays.copyOfRange(original, 0, index)); 105 | original = Arrays.copyOfRange(original, index + delimiter.length, original.length); 106 | } 107 | while (original[original.length - 1] == (byte) '\n' || original[original.length - 1] == (byte) '\r') { 108 | original = Arrays.copyOfRange(original, 0, original.length - 1); 109 | } 110 | parts.add(original); 111 | 112 | return parts; 113 | } 114 | 115 | public void parsePart(int i) throws IOException { 116 | ArrayList sectionParts = splitDelimited(sections.get(i), CONTENT_DELIMITER); 117 | Scanner scanner = new Scanner(new String(sectionParts.get(0))); 118 | 119 | String line = scanner.nextLine(); 120 | 121 | // Check if the first line is "\r\n" or one of the headers 122 | if (line.trim().length() > 0) { 123 | if (line.contains(":")) { 124 | String[] parts = line.split(":"); 125 | headers.put(parts[0].trim(), parts[1].trim()); 126 | } 127 | } 128 | 129 | // Populate the headers 130 | while (scanner.hasNextLine() && (line = scanner.nextLine()).trim().length() > 0) { 131 | if (line.contains(":")) { 132 | String[] parts = line.split(":"); 133 | 134 | if (! parts[1].equals(null)) { 135 | headers.put(parts[0].trim(), parts[1].trim()); 136 | } 137 | else { 138 | if ((line = scanner.nextLine()).charAt(0) == '\t') { 139 | headers.put(parts[0].trim(), line.trim()); 140 | } 141 | } 142 | } 143 | } 144 | 145 | if (headers.get("Content-Type").contains("application/json")) { 146 | scanner = new Scanner(new String(sectionParts.get(1))); 147 | 148 | // Read in the content 149 | String contentString = ""; 150 | while (scanner.hasNextLine() && !(line = scanner.nextLine()).equals(boundary)) { 151 | contentString += line; 152 | } 153 | content = contentString.getBytes(); 154 | } 155 | else { 156 | content = sectionParts.get(1); 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/internal/StatementBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.internal; 17 | 18 | import java.io.IOException; 19 | import java.net.MalformedURLException; 20 | import java.net.URISyntaxException; 21 | import java.security.NoSuchAlgorithmException; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import java.util.UUID; 25 | 26 | import com.rusticisoftware.tincan.http.HTTPPart; 27 | import lombok.Data; 28 | import lombok.EqualsAndHashCode; 29 | import lombok.NoArgsConstructor; 30 | 31 | import org.joda.time.DateTime; 32 | import org.joda.time.format.DateTimeFormatter; 33 | import org.joda.time.format.ISODateTimeFormat; 34 | 35 | import com.fasterxml.jackson.databind.JsonNode; 36 | import com.fasterxml.jackson.databind.node.ArrayNode; 37 | import com.fasterxml.jackson.databind.node.ObjectNode; 38 | 39 | import com.rusticisoftware.tincan.*; 40 | import com.rusticisoftware.tincan.json.JSONBase; 41 | import com.rusticisoftware.tincan.json.Mapper; 42 | import com.rusticisoftware.tincan.json.StringOfJSON; 43 | 44 | /** 45 | * StatementBase Class 46 | */ 47 | @Data 48 | @EqualsAndHashCode(callSuper = false) 49 | @NoArgsConstructor 50 | public abstract class StatementBase extends JSONBase { 51 | private Agent actor; 52 | private Verb verb; 53 | private StatementTarget object; 54 | private Result result; 55 | private Context context; 56 | private DateTime timestamp; 57 | private List attachments; 58 | 59 | @Deprecated 60 | private Boolean voided; 61 | 62 | public StatementBase(JsonNode jsonNode) throws URISyntaxException, MalformedURLException, IOException, NoSuchAlgorithmException { 63 | this(); 64 | 65 | JsonNode actorNode = jsonNode.path("actor"); 66 | if (! actorNode.isMissingNode()) { 67 | this.setActor(Agent.fromJson(actorNode)); 68 | } 69 | 70 | JsonNode verbNode = jsonNode.path("verb"); 71 | if (! verbNode.isMissingNode()) { 72 | this.setVerb(new Verb(verbNode)); 73 | } 74 | 75 | JsonNode objectNode = jsonNode.path("object"); 76 | if (! objectNode.isMissingNode()) { 77 | String objectType = objectNode.path("objectType").textValue(); 78 | if ("Group".equals(objectType) || "Agent".equals(objectType)) { 79 | this.setObject(Agent.fromJson(objectNode)); 80 | } 81 | else if ("StatementRef".equals(objectType)) { 82 | this.setObject(new StatementRef(objectNode)); 83 | } 84 | else if ("SubStatement".equals(objectType)) { 85 | this.setObject(new SubStatement(objectNode)); 86 | } 87 | else { 88 | this.setObject(new Activity(objectNode)); 89 | } 90 | } 91 | 92 | JsonNode resultNode = jsonNode.path("result"); 93 | if (! resultNode.isMissingNode()) { 94 | this.setResult(new Result(resultNode)); 95 | } 96 | 97 | JsonNode contextNode = jsonNode.path("context"); 98 | if (! contextNode.isMissingNode()) { 99 | this.setContext(new Context(contextNode)); 100 | } 101 | 102 | JsonNode timestampNode = jsonNode.path("timestamp"); 103 | if (! timestampNode.isMissingNode()) { 104 | this.setTimestamp(new DateTime(timestampNode.textValue())); 105 | } 106 | 107 | JsonNode voidedNode = jsonNode.path("voided"); 108 | if (! voidedNode.isMissingNode()) { 109 | this.setVoided(voidedNode.asBoolean()); 110 | } 111 | 112 | JsonNode attachmentsNode = jsonNode.path("attachments"); 113 | if (! attachmentsNode.isMissingNode()) { 114 | this.attachments = new ArrayList(); 115 | for (JsonNode element : attachmentsNode) { 116 | this.attachments.add(new Attachment(element)); 117 | } 118 | } 119 | } 120 | 121 | public StatementBase(StringOfJSON jsonStr) throws IOException, URISyntaxException, NoSuchAlgorithmException { 122 | this(jsonStr.toJSONNode()); 123 | } 124 | 125 | public StatementBase(Agent actor, Verb verb, StatementTarget object, Result result, Context context) { 126 | this(); 127 | 128 | this.setActor(actor); 129 | this.setVerb(verb); 130 | this.setObject(object); 131 | this.setResult(result); 132 | this.setContext(context); 133 | } 134 | 135 | public StatementBase(Agent actor, Verb verb, StatementTarget object) { 136 | this(actor, verb, object, null, null); 137 | } 138 | 139 | @Override 140 | public ObjectNode toJSONNode(TCAPIVersion version) { 141 | ObjectNode node = Mapper.getInstance().createObjectNode(); 142 | DateTimeFormatter fmt = ISODateTimeFormat.dateTime().withZoneUTC(); 143 | 144 | node.put("actor", this.getActor().toJSONNode(version)); 145 | node.put("verb", this.getVerb().toJSONNode(version)); 146 | node.put("object", this.getObject().toJSONNode(version)); 147 | 148 | if (this.result != null) { 149 | node.put("result", this.getResult().toJSONNode(version)); 150 | } 151 | if (this.context != null) { 152 | node.put("context", this.getContext().toJSONNode(version)); 153 | } 154 | if (this.timestamp != null) { 155 | node.put("timestamp", fmt.print(this.getTimestamp())); 156 | } 157 | 158 | //Include 1.0.x specific fields if asking for 1.0.x version 159 | if (version.ordinal() <= TCAPIVersion.V100.ordinal()) { 160 | if (this.getAttachments() != null && this.getAttachments().size() > 0) { 161 | ArrayNode attachmentsNode = Mapper.getInstance().createArrayNode(); 162 | for (Attachment attachment : this.getAttachments()) { 163 | attachmentsNode.add(attachment.toJSONNode(version)); 164 | } 165 | node.put("attachments", attachmentsNode); 166 | } 167 | } 168 | 169 | return node; 170 | } 171 | 172 | public boolean hasAttachments() { 173 | return (this.getAttachments() != null && this.getAttachments().size() > 0); 174 | } 175 | 176 | public boolean hasAttachmentsWithContent() { 177 | if (this.getAttachments() != null) { 178 | for (Attachment attachment : this.getAttachments()) { 179 | if (attachment.getContent().length > 0) { 180 | return true; 181 | } 182 | } 183 | } 184 | return false; 185 | } 186 | 187 | public void addAttachment(Attachment attachment) { 188 | if (this.getAttachments() == null) { 189 | this.setAttachments(new ArrayList()); 190 | } 191 | this.getAttachments().add(attachment); 192 | } 193 | 194 | public void addAttachments(Attachment attachments) { 195 | if (this.getAttachments() == null) { 196 | this.setAttachments(new ArrayList()); 197 | } 198 | this.getAttachments().add(attachments); 199 | } 200 | 201 | public List getPartList() { 202 | List partList = new ArrayList(); 203 | for (Attachment attachment : this.getAttachments()) { 204 | partList.add(attachment.getPart()); 205 | } 206 | return partList; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/json/JSON.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.json; 17 | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; 19 | import com.rusticisoftware.tincan.TCAPIVersion; 20 | 21 | import java.io.IOException; 22 | 23 | /** 24 | * Interface to implement to provide JSON support for nesting of objects 25 | */ 26 | public interface JSON { 27 | public ObjectNode toJSONNode(TCAPIVersion version); 28 | public ObjectNode toJSONNode(); 29 | public String toJSON(TCAPIVersion version, Boolean pretty); 30 | public String toJSON(TCAPIVersion version); 31 | public String toJSON(Boolean pretty); 32 | public String toJSON(); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/json/JSONBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.json; 17 | 18 | import com.fasterxml.jackson.core.JsonProcessingException; 19 | import com.fasterxml.jackson.databind.ObjectWriter; 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import java.io.IOException; 22 | import com.rusticisoftware.tincan.TCAPIVersion; 23 | 24 | /** 25 | * JSONBase Class Description 26 | */ 27 | public abstract class JSONBase implements JSON { 28 | @Override 29 | public abstract ObjectNode toJSONNode(TCAPIVersion version); 30 | 31 | @Override 32 | public ObjectNode toJSONNode() { 33 | TCAPIVersion version = TCAPIVersion.latest(); 34 | return this.toJSONNode(version); 35 | } 36 | 37 | @Override 38 | public String toJSON(TCAPIVersion version, Boolean pretty) { 39 | ObjectWriter writer = Mapper.getWriter(pretty); 40 | try { 41 | return writer.writeValueAsString(this.toJSONNode(version)); 42 | } catch (JsonProcessingException ex) { 43 | return "Exception in JSONBase Class: " + ex.toString(); 44 | } 45 | } 46 | 47 | 48 | @Override 49 | public String toJSON(TCAPIVersion version) { 50 | return this.toJSON(version, false); 51 | } 52 | 53 | @Override 54 | public String toJSON(Boolean pretty) { 55 | return this.toJSON(TCAPIVersion.latest(), pretty); 56 | } 57 | 58 | @Override 59 | public String toJSON() { 60 | return this.toJSON(TCAPIVersion.latest(), false); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/json/Mapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.json; 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; 19 | import com.fasterxml.jackson.databind.ObjectWriter; 20 | 21 | /** 22 | * Mapper Class provides access to a Jackson ObjectMapper singleton 23 | */ 24 | public class Mapper { 25 | private static class LazyHolder { 26 | private static final ObjectMapper INSTANCE = new ObjectMapper(); 27 | } 28 | 29 | public static ObjectMapper getInstance() { 30 | return LazyHolder.INSTANCE; 31 | } 32 | 33 | public static ObjectWriter getWriter(Boolean pretty) { 34 | ObjectMapper mapper = getInstance(); 35 | 36 | ObjectWriter writer; 37 | if (pretty) { 38 | writer = mapper.writer().withDefaultPrettyPrinter(); 39 | } 40 | else { 41 | writer = mapper.writer(); 42 | } 43 | 44 | return writer; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/json/StringOfJSON.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.json; 17 | 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import java.io.IOException; 20 | 21 | /** 22 | * StringOfJSON Class Description 23 | */ 24 | public class StringOfJSON { 25 | private String source; 26 | 27 | public StringOfJSON(String json) { 28 | this.source = json; 29 | } 30 | 31 | public JsonNode toJSONNode() throws IOException { 32 | if (this.source == null) { 33 | return null; 34 | } 35 | return Mapper.getInstance().readValue(this.source, JsonNode.class); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return this.source; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/AboutLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.About; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class AboutLRSResponse extends LRSResponse{ 29 | private About content; 30 | 31 | public AboutLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/ActivityLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.Activity; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class ActivityLRSResponse extends LRSResponse{ 29 | private Activity content; 30 | 31 | public ActivityLRSResponse (HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/ActivityProfileLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.documents.ActivityProfileDocument; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class ActivityProfileLRSResponse extends LRSResponse{ 29 | private ActivityProfileDocument content; 30 | 31 | public ActivityProfileLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/AgentProfileLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.documents.AgentProfileDocument; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class AgentProfileLRSResponse extends LRSResponse{ 29 | private AgentProfileDocument content; 30 | 31 | public AgentProfileLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/LRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.http.HTTPRequest; 19 | import com.rusticisoftware.tincan.http.HTTPResponse; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | 24 | @Data 25 | @EqualsAndHashCode(callSuper = false) 26 | @NoArgsConstructor 27 | public class LRSResponse { 28 | private Boolean success; 29 | private String errMsg; 30 | private HTTPRequest request; 31 | private HTTPResponse response; 32 | 33 | public LRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) 34 | { 35 | request = initRequest; 36 | response = initResponse; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/PersonLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.Person; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class PersonLRSResponse extends LRSResponse{ 29 | private Person content; 30 | 31 | public PersonLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/ProfileKeysLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.http.HTTPRequest; 19 | import com.rusticisoftware.tincan.http.HTTPResponse; 20 | import lombok.Data; 21 | import lombok.EqualsAndHashCode; 22 | import lombok.NoArgsConstructor; 23 | 24 | import java.util.List; 25 | 26 | @Data 27 | @EqualsAndHashCode(callSuper = false) 28 | @NoArgsConstructor 29 | public class ProfileKeysLRSResponse extends LRSResponse{ 30 | private List content; 31 | 32 | public ProfileKeysLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 33 | super(initRequest, initResponse); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/StateLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.documents.StateDocument; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class StateLRSResponse extends LRSResponse{ 29 | private StateDocument content; 30 | 31 | public StateLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/StatementLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.Statement; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class StatementLRSResponse extends LRSResponse{ 29 | private Statement content; 30 | 31 | public StatementLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/lrsresponses/StatementsResultLRSResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.lrsresponses; 17 | 18 | import com.rusticisoftware.tincan.StatementsResult; 19 | import com.rusticisoftware.tincan.http.HTTPRequest; 20 | import com.rusticisoftware.tincan.http.HTTPResponse; 21 | import lombok.Data; 22 | import lombok.EqualsAndHashCode; 23 | import lombok.NoArgsConstructor; 24 | 25 | @Data 26 | @EqualsAndHashCode(callSuper = false) 27 | @NoArgsConstructor 28 | public class StatementsResultLRSResponse extends LRSResponse{ 29 | private StatementsResult content; 30 | 31 | public StatementsResultLRSResponse(HTTPRequest initRequest, HTTPResponse initResponse) { 32 | super(initRequest, initResponse); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/v095/StatementsQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.v095; 17 | 18 | import lombok.Data; 19 | import lombok.Getter; 20 | import lombok.NoArgsConstructor; 21 | import org.joda.time.DateTime; 22 | import org.joda.time.format.DateTimeFormat; 23 | import org.joda.time.format.DateTimeFormatter; 24 | import org.joda.time.format.ISODateTimeFormat; 25 | 26 | import com.rusticisoftware.tincan.Agent; 27 | import com.rusticisoftware.tincan.QueryableStatementTarget; 28 | import com.rusticisoftware.tincan.StatementsQueryInterface; 29 | import com.rusticisoftware.tincan.TCAPIVersion; 30 | import com.rusticisoftware.tincan.Verb; 31 | 32 | import java.io.IOException; 33 | import java.net.URI; 34 | import java.net.URISyntaxException; 35 | import java.util.HashMap; 36 | import java.util.UUID; 37 | 38 | /** 39 | * Query model class used for building query parameters passed to get statements from LRS 40 | */ 41 | @Data 42 | @NoArgsConstructor 43 | public class StatementsQuery implements StatementsQueryInterface { 44 | @Getter private TCAPIVersion version = TCAPIVersion.V095; 45 | 46 | private URI verbID; 47 | private QueryableStatementTarget object; 48 | private UUID registration; 49 | private Boolean context; 50 | private Agent actor; 51 | private DateTime since; 52 | private DateTime until; 53 | private Integer limit; 54 | private Boolean authoritative; 55 | private Boolean sparse; 56 | private Agent instructor; 57 | private Boolean ascending; 58 | 59 | public void setVerbID(String verbID) throws URISyntaxException { 60 | this.verbID = new URI(verbID); 61 | } 62 | 63 | public void setVerbID(Verb verb) throws URISyntaxException { 64 | this.setVerbID(verb.getId().toString()); 65 | } 66 | 67 | public HashMap toParameterMap() throws IOException { 68 | HashMap params = new HashMap(); 69 | DateTimeFormatter fmt = ISODateTimeFormat.dateTime().withZoneUTC(); 70 | 71 | if (this.getVerbID() != null) { 72 | params.put("verb", this.getVerbID().toString()); 73 | } 74 | if (this.getObject() != null) { 75 | params.put("object", this.getObject().toJSON(version)); 76 | } 77 | if (this.getRegistration() != null) { 78 | params.put("registration", this.getRegistration().toString()); 79 | } 80 | if (this.getContext() != null) { 81 | params.put("context", this.getContext().toString()); 82 | } 83 | if (this.getActor() != null) { 84 | params.put("actor", this.getActor().toJSON(version)); 85 | } 86 | if (this.getSince() != null) { 87 | params.put("since", fmt.print(this.getSince())); 88 | } 89 | if (this.getUntil() != null) { 90 | params.put("until", fmt.print(this.getUntil())); 91 | } 92 | if (this.getLimit() != null) { 93 | params.put("limit", this.getLimit().toString()); 94 | } 95 | if (this.getAuthoritative() != null) { 96 | params.put("authoritative", this.getAuthoritative().toString()); 97 | } 98 | if (this.getSparse() != null) { 99 | params.put("sparse", this.getSparse().toString()); 100 | } 101 | if (this.getInstructor() != null) { 102 | params.put("instructor", this.getInstructor().toJSON(version)); 103 | } 104 | if (this.getAscending() != null) { 105 | params.put("ascending", this.getAscending().toString()); 106 | } 107 | 108 | return params; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/rusticisoftware/tincan/v10x/StatementsQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan.v10x; 17 | 18 | import lombok.Data; 19 | import lombok.Getter; 20 | import lombok.NoArgsConstructor; 21 | import org.joda.time.DateTime; 22 | import org.joda.time.format.DateTimeFormat; 23 | import org.joda.time.format.DateTimeFormatter; 24 | import org.joda.time.format.ISODateTimeFormat; 25 | 26 | import com.rusticisoftware.tincan.Agent; 27 | import com.rusticisoftware.tincan.QueryResultFormat; 28 | import com.rusticisoftware.tincan.QueryableStatementTarget; 29 | import com.rusticisoftware.tincan.StatementsQueryInterface; 30 | import com.rusticisoftware.tincan.TCAPIVersion; 31 | import com.rusticisoftware.tincan.Verb; 32 | 33 | import java.io.IOException; 34 | import java.net.URI; 35 | import java.net.URISyntaxException; 36 | import java.util.HashMap; 37 | import java.util.UUID; 38 | 39 | /** 40 | * Query model class used for building query parameters passed to get statements from LRS 41 | */ 42 | @Data 43 | @NoArgsConstructor 44 | public class StatementsQuery implements StatementsQueryInterface { 45 | @Getter private TCAPIVersion version = TCAPIVersion.V100; 46 | 47 | private Agent agent; 48 | private URI verbID; 49 | private URI activityID; 50 | private UUID registration; 51 | private Boolean relatedActivities; 52 | private Boolean relatedAgents; 53 | private DateTime since; 54 | private DateTime until; 55 | private Integer limit; 56 | private QueryResultFormat format; 57 | private Boolean attachments; 58 | private Boolean ascending; 59 | 60 | public void setVerbID(String verbID) throws URISyntaxException { 61 | this.verbID = new URI(verbID); 62 | } 63 | 64 | public void setVerbID(Verb verb) throws URISyntaxException { 65 | this.setVerbID(verb.getId().toString()); 66 | } 67 | 68 | public HashMap toParameterMap() throws IOException { 69 | HashMap params = new HashMap(); 70 | DateTimeFormatter fmt = ISODateTimeFormat.dateTime().withZoneUTC(); 71 | 72 | if (this.getAgent() != null) { 73 | params.put("agent", this.getAgent().toJSON(version)); 74 | } 75 | if (this.getVerbID() != null) { 76 | params.put("verb", this.getVerbID().toString()); 77 | } 78 | if (this.getActivityID() != null) { 79 | params.put("activity", this.getActivityID().toString()); 80 | } 81 | if (this.getRegistration() != null) { 82 | params.put("registration", this.getRegistration().toString()); 83 | } 84 | if (this.getRelatedActivities() != null) { 85 | params.put("related_activities", this.getRelatedActivities().toString()); 86 | } 87 | if (this.getRelatedAgents() != null) { 88 | params.put("related_agents", this.getRelatedAgents().toString()); 89 | } 90 | if (this.getSince() != null) { 91 | params.put("since", fmt.print(this.getSince())); 92 | } 93 | if (this.getUntil() != null) { 94 | params.put("until", fmt.print(this.getUntil())); 95 | } 96 | if (this.getLimit() != null) { 97 | params.put("limit", this.getLimit().toString()); 98 | } 99 | if (this.getFormat() != null) { 100 | params.put("format", this.getFormat().toString().toLowerCase()); 101 | } 102 | if (this.getAscending() != null) { 103 | params.put("ascending", this.getAscending().toString()); 104 | } 105 | 106 | if (this.getAttachments() != null) { 107 | params.put("attachments", this.getAttachments().toString()); 108 | } 109 | 110 | return params; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ActivityDefinitionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | 23 | import org.junit.Test; 24 | 25 | /** 26 | * Description 27 | */ 28 | public class ActivityDefinitionTest { 29 | 30 | @Test 31 | public void serializeDeserialize() throws Exception { 32 | ActivityDefinition def = new ActivityDefinition(); 33 | 34 | def.setChoices(createInteractionComponent("choice1", "Choice 1")); 35 | 36 | def.setCorrectResponsesPattern( 37 | new ArrayList( 38 | Arrays.asList(new String[]{"correct_response"}))); 39 | 40 | def.setDescription(new LanguageMap()); 41 | def.getDescription().put("en-US", "Activity Definition Description"); 42 | 43 | Extensions extensions = new Extensions(); 44 | extensions.put("http://example.com/extensions", "extensionValue"); 45 | def.setExtensions(extensions); 46 | 47 | 48 | 49 | def.setName(new LanguageMap()); 50 | def.getName().put("en-US", "Activity Definition"); 51 | 52 | def.setScale(createInteractionComponent("scale1", "Scale 1")); 53 | def.setSource(createInteractionComponent("source1", "Source 1")); 54 | def.setSteps(createInteractionComponent("steps1", "Steps 1")); 55 | def.setTarget(createInteractionComponent("target1", "Target 1")); 56 | 57 | def.setType("http://adlnet.gov/expapi/activities/assessment"); 58 | 59 | for (InteractionType intType : InteractionType.values()) { 60 | def.setInteractionType(intType); 61 | assertSerializeDeserialize(def); 62 | } 63 | } 64 | 65 | protected ArrayList createInteractionComponent(String id, String description) { 66 | InteractionComponent comp = new InteractionComponent(); 67 | comp.setId(id); 68 | comp.setDescription(new LanguageMap()); 69 | comp.getDescription().put("en-US", description); 70 | ArrayList lst = new ArrayList(); 71 | lst.add(comp); 72 | return lst; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ActivityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import org.junit.Test; 22 | 23 | public class ActivityTest { 24 | @Test 25 | public void testGetObjectType() throws Exception { 26 | Activity mock = new Activity(); 27 | assertEquals(mock.getObjectType(), "Activity"); 28 | } 29 | 30 | @Test 31 | public void serializeDeserialize() throws Exception { 32 | Activity act = new Activity(); 33 | act.setId("http://example.com/activity"); 34 | 35 | ActivityDefinition def = new ActivityDefinition(); 36 | def.setName(new LanguageMap()); 37 | def.getName().put("en-US", "Example Activity"); 38 | act.setDefinition(def); 39 | 40 | assertSerializeDeserialize(act); 41 | } 42 | 43 | @Test 44 | public void testGetId() throws Exception { 45 | String id = "http://example.com/activity"; 46 | Activity act = new Activity(id); 47 | assertEquals(id, act.getId().toString()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/AgentAccountTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | 20 | import org.junit.Test; 21 | 22 | /** 23 | * Description 24 | */ 25 | public class AgentAccountTest { 26 | 27 | @Test 28 | public void serializeDeserialize() throws Exception { 29 | AgentAccount acct = new AgentAccount(); 30 | acct.setHomePage("http://example.com"); 31 | acct.setName("joeuser"); 32 | assertSerializeDeserialize(acct); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/AgentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | import static com.rusticisoftware.tincan.TestUtils.*; 20 | 21 | import java.util.LinkedHashMap; 22 | import java.util.Map; 23 | 24 | import org.junit.Test; 25 | 26 | import com.rusticisoftware.tincan.json.StringOfJSON; 27 | 28 | /** 29 | * Description 30 | */ 31 | public class AgentTest { 32 | 33 | @Test 34 | public void serializeDeserialize() throws Exception { 35 | Map ids = new LinkedHashMap(); 36 | ids.put("mbox", "mailto:joeuser@example.com"); 37 | ids.put("openid", "http://openid.org/joeuser"); 38 | ids.put("mbox_sha1sum", "b623062e19c5608ab0e1342e5011d48292ce00e3"); 39 | ids.put("account", "http://example.com|joeuser"); 40 | 41 | String name = "Joe User"; 42 | for (String idType : ids.keySet()) { 43 | for (TCAPIVersion version : TCAPIVersion.values()) { 44 | Agent agent = getAgent(name, idType, ids.get(idType)); 45 | String agentJson = agent.toJSON(version); 46 | Agent clone = Agent.fromJson(new StringOfJSON(agentJson).toJSONNode()); 47 | assertEquals(agentJson, clone.toJSON(version)); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/AttachmentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.*; 19 | import java.net.URI; 20 | import java.net.URL; 21 | 22 | import org.junit.Test; 23 | 24 | public class AttachmentTest { 25 | 26 | @Test 27 | public void serializeDeserialize() throws Exception { 28 | Attachment att = new Attachment(); 29 | att.setContentType("text/plain"); 30 | att.setDisplay(new LanguageMap()); 31 | att.getDisplay().put("en-US", "Some attachment"); 32 | att.setDescription(new LanguageMap()); 33 | att.getDescription().put("en-US", "Some attachment description"); 34 | att.setFileUrl(new URL("http://example.com/somefile")); 35 | att.setLength(27); 36 | att.setSha2("495395e777cd98da653df9615d09c0fd6bb2f8d4788394cd53c56a3bfdcd848a"); 37 | att.setUsageType(new URI("http://example.com/attachment-usage/test")); 38 | 39 | assertSerializeDeserialize(att); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ContextActivitiesTest.java: -------------------------------------------------------------------------------- 1 | package com.rusticisoftware.tincan; 2 | 3 | import static com.rusticisoftware.tincan.TestUtils.*; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import com.rusticisoftware.tincan.exceptions.IncompatibleTCAPIVersion; 9 | import org.junit.Test; 10 | 11 | public class ContextActivitiesTest { 12 | 13 | @Test 14 | public void serializeDeserialize() throws Exception { 15 | ContextActivities ctxActs = new ContextActivities(); 16 | ctxActs.setParent(getCtxActList("http://example.com/parent")); 17 | ctxActs.setGrouping(getCtxActList("http://example.com/grouping")); 18 | ctxActs.setOther(getCtxActList("http://example.com/other")); 19 | assertSerializeDeserialize(ctxActs); 20 | } 21 | 22 | // 23 | // 'category' arrived in 1.0.0, so confirm it works in everything 24 | // after that point, which is to say not 0.95 25 | // 26 | @Test 27 | public void serializeDeserializePost10() throws Exception { 28 | ContextActivities ctxActs = new ContextActivities(); 29 | ctxActs.setParent(getCtxActList("http://example.com/parent")); 30 | ctxActs.setGrouping(getCtxActList("http://example.com/grouping")); 31 | ctxActs.setOther(getCtxActList("http://example.com/other")); 32 | ctxActs.setCategory(getCtxActList("http://example.com/category")); 33 | assertSerializeDeserialize(ctxActs, TCAPIVersion.V101); 34 | assertSerializeDeserialize(ctxActs, TCAPIVersion.V100); 35 | } 36 | 37 | // 38 | // 'category' is not supported in 0.95, make sure it isn't 39 | // 40 | @Test(expected = IncompatibleTCAPIVersion.class) 41 | public void serializeDeserialize095Category() throws Exception { 42 | ContextActivities ctxActs = new ContextActivities(); 43 | ctxActs.setCategory(getCtxActList("http://example.com/category")); 44 | assertSerializeDeserialize(ctxActs, TCAPIVersion.V095); 45 | } 46 | 47 | private List getCtxActList(String id) throws Exception { 48 | return Arrays.asList(new Activity[]{ new Activity(id) }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.*; 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import java.util.ArrayList; 22 | import java.util.UUID; 23 | 24 | import lombok.Data; 25 | import org.junit.Test; 26 | 27 | /** 28 | * ContextTest Class Description 29 | */ 30 | @Data 31 | public class ContextTest { 32 | @Test 33 | public void serializeDeserialize() throws Exception { 34 | Context ctx = new Context(); 35 | ctx.setContextActivities(new ContextActivities()); 36 | ctx.getContextActivities().setParent(new ArrayList()); 37 | ctx.getContextActivities().getParent().add(new Activity("http://example.com/activity")); 38 | 39 | ctx.setExtensions(new Extensions()); 40 | ctx.getExtensions().put("http://example.com/extension", "extensionValue"); 41 | 42 | ctx.setInstructor(getAgent("Instructor", "mbox", "mailto:instructor@example.com")); 43 | ctx.setLanguage("en-US"); 44 | ctx.setPlatform("iPhone 5"); 45 | ctx.setRegistration(UUID.randomUUID()); 46 | ctx.setRevision("1.0.4"); 47 | 48 | StatementRef ref = new StatementRef(); 49 | ref.setId(UUID.randomUUID()); 50 | 51 | ctx.setStatement(ref); 52 | 53 | ctx.setTeam(getAgent("Group", "mbox", "mailto:group@example.com")); 54 | 55 | assertSerializeDeserialize(ctx); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ExtensionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.*; 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import org.junit.Test; 22 | 23 | import lombok.Data; 24 | 25 | /** 26 | * ExtensionsTest Class Description 27 | */ 28 | @Data 29 | public class ExtensionsTest { 30 | 31 | @Test 32 | public void serializeDeserialize() throws Exception { 33 | Extensions ext = new Extensions(); 34 | ext.put("http://example.com/string", "extensionValue"); 35 | ext.put("http://example.com/int", 10); 36 | ext.put("http://example.com/double", 1.897); 37 | ext.put("http://example.com/object", 38 | getAgent("Random", "mbox", "mailto:random@example.com")); 39 | 40 | assertSerializeDeserialize(ext); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/GroupTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.*; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import org.junit.Test; 24 | 25 | import com.rusticisoftware.tincan.json.StringOfJSON; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | 29 | public class GroupTest { 30 | @Test 31 | public void testGetObjectType() throws Exception { 32 | Group mock = new Group(); 33 | assertEquals(mock.getObjectType(), "Group"); 34 | } 35 | 36 | @Test 37 | public void serializeDeserialize() throws Exception { 38 | List members = new ArrayList(); 39 | for (int i = 0; i < 10; i++) { 40 | members.add( 41 | getAgent("Member " + i, "mbox", "mailto:member" + i + "@example.com")); 42 | } 43 | Group group = new Group(); 44 | group.setName("Group"); 45 | group.setMbox("mailto:group@example.com"); 46 | group.setMembers(members); 47 | 48 | assertSerializeDeserialize(group); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/InteractionComponentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import lombok.Data; 20 | 21 | import org.junit.Test; 22 | 23 | /** 24 | * InteractionComponentTest Class Description 25 | */ 26 | @Data 27 | public class InteractionComponentTest { 28 | @Test 29 | public void serializeDeserialize() throws Exception { 30 | InteractionComponent comp = new InteractionComponent(); 31 | comp.setId("choice1"); 32 | comp.setDescription(new LanguageMap()); 33 | comp.getDescription().put("en-US", "Some choice"); 34 | assertSerializeDeserialize(comp); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/InteractionTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | * InteractionTypeTest Class Description 22 | */ 23 | @Data 24 | public class InteractionTypeTest { 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/LanguageMapTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertTrue; 21 | 22 | import java.io.IOException; 23 | import java.util.Map; 24 | import java.util.ArrayList; 25 | import java.util.LinkedList; 26 | import java.util.Vector; 27 | 28 | import org.junit.Test; 29 | 30 | /** 31 | * Description 32 | */ 33 | public class LanguageMapTest { 34 | 35 | @Test 36 | public void serializeDeserialize() throws Exception { 37 | LanguageMap lm = new LanguageMap(); 38 | lm.put("en-US", "Some english"); 39 | lm.put("es-ES", "Some espanol"); 40 | assertSerializeDeserialize(lm); 41 | } 42 | 43 | @Test 44 | public void fillAndIterate() { 45 | LanguageMap lm = new LanguageMap(); 46 | LanguageMap lmCopy = new LanguageMap(); 47 | lm.put("und", "Some text"); 48 | lm.put("en-US", "Some english"); 49 | lm.put("es-ES", "Some espanol"); 50 | 51 | for (Map.Entry entry : lm) { 52 | lmCopy.put(entry); 53 | } 54 | 55 | String lmContent = lm.toJSON(); 56 | String lmCopyContent = lmCopy.toJSON(); 57 | 58 | assertEquals(lmContent, lmCopyContent); 59 | 60 | boolean hasKey = lm.containsKey("und"); 61 | boolean hasValue = lm.containsValue("Some english"); 62 | Map.Entry entry = lm.findFirstValue("Some espanol"); 63 | ArrayList arrayOfLangs = new ArrayList(); 64 | LinkedList linkedListOfLangs = new LinkedList(); 65 | Vector vectorOfLangs = new Vector(); 66 | lm.populateWithAvailableLanguages(arrayOfLangs); 67 | lm.populateWithAvailableLanguages(linkedListOfLangs); 68 | lm.populateWithAvailableLanguages(vectorOfLangs); 69 | 70 | assertTrue(hasKey); 71 | assertTrue(hasValue); 72 | assertEquals(entry.getKey(), "es-ES"); 73 | assertEquals(arrayOfLangs.size(), 3); 74 | assertEquals(linkedListOfLangs.size(), 3); 75 | assertEquals(vectorOfLangs.size(), 3); 76 | for (String s : linkedListOfLangs) { 77 | assertTrue(lm.containsKey(s)); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ResultTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | 20 | import lombok.Data; 21 | 22 | import org.joda.time.Period; 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | /** 27 | * ResultTest Class Description 28 | */ 29 | @Data 30 | public class ResultTest { 31 | 32 | @Test 33 | public void serializeDeserialize() throws Exception { 34 | Result res = new Result(); 35 | res.setCompletion(true); 36 | res.setDuration(new Period("P1DT8H")); 37 | res.setExtensions(new Extensions()); 38 | res.getExtensions().put("http://example.com/extension", "extensionValue"); 39 | res.setResponse("Here's a response"); 40 | res.setScore(new Score()); 41 | res.getScore().setRaw(0.43); 42 | res.setSuccess(false); 43 | assertSerializeDeserialize(res); 44 | } 45 | 46 | @Test 47 | public void testToJSONResultDurationTruncation() throws Exception { 48 | Result res = new Result(); 49 | res.setDuration(new Period(1, 2, 16, 43)); 50 | 51 | Assert.assertEquals("{\"duration\":\"PT1H2M16.04S\"}", res.toJSON()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/ScoreTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | 20 | import lombok.Data; 21 | import org.junit.Test; 22 | 23 | /** 24 | * ScoreTest Class Description 25 | */ 26 | @Data 27 | public class ScoreTest { 28 | 29 | @Test 30 | public void serializeDeserialize() throws Exception { 31 | Score sc = new Score(); 32 | sc.setMax(100.0); 33 | sc.setMin(0.0); 34 | sc.setRaw(80.0); 35 | sc.setScaled(0.8); 36 | assertSerializeDeserialize(sc); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/StateTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import lombok.Data; 19 | import org.junit.Test; 20 | 21 | /** 22 | * StateTest Class Description 23 | */ 24 | @Data 25 | public class StateTest { 26 | @Test 27 | public void testGetId() throws Exception { 28 | 29 | } 30 | 31 | @Test 32 | public void testGetUpdated() throws Exception { 33 | 34 | } 35 | 36 | @Test 37 | public void testGetContents() throws Exception { 38 | 39 | } 40 | 41 | @Test 42 | public void testSetId() throws Exception { 43 | 44 | } 45 | 46 | @Test 47 | public void testSetUpdated() throws Exception { 48 | 49 | } 50 | 51 | @Test 52 | public void testSetContents() throws Exception { 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/StatementRefTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import java.util.UUID; 22 | 23 | import lombok.Data; 24 | import org.junit.Test; 25 | 26 | /** 27 | * StatementRefTest Class Description 28 | */ 29 | @Data 30 | public class StatementRefTest { 31 | 32 | @Test 33 | public void testGetObjectType() throws Exception { 34 | StatementRef ref = new StatementRef(); 35 | assertEquals("StatementRef", ref.getObjectType()); 36 | } 37 | 38 | @Test 39 | public void serializeDeserialize() throws Exception { 40 | StatementRef ref = new StatementRef(); 41 | ref.setId(UUID.randomUUID()); 42 | assertSerializeDeserialize(ref); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/StatementTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static com.rusticisoftware.tincan.TestUtils.getAgent; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.UUID; 24 | 25 | import org.joda.time.DateTime; 26 | import org.junit.Test; 27 | 28 | import com.rusticisoftware.tincan.json.StringOfJSON; 29 | 30 | import static org.hamcrest.CoreMatchers.is; 31 | import static org.junit.Assert.assertThat; 32 | /** 33 | * Description 34 | */ 35 | public class StatementTest { 36 | 37 | @Test 38 | public void serializeDeserialize() throws Exception { 39 | 40 | List statementTargets = new ArrayList(); 41 | statementTargets.add(new Activity("http://example.com/activity")); 42 | statementTargets.add(getAgent("Target", "mbox", "mailto:target@example.com")); 43 | statementTargets.add(new StatementRef(UUID.randomUUID())); 44 | 45 | SubStatement sub = new SubStatement(); 46 | sub.setActor(getAgent("Sub", "mbox", "mailto:sub@example.com")); 47 | sub.setVerb(new Verb("http://example.com/verb")); 48 | sub.setObject(new Activity("http://example.com/sub-activity")); 49 | statementTargets.add(sub); 50 | 51 | 52 | Statement st = new Statement(); 53 | st.setActor(getAgent("Joe", "mbox", "mailto:joe@example.com")); 54 | 55 | st.setAttachments(new ArrayList()); 56 | Attachment att = new Attachment(); 57 | att.setSha2("abc"); 58 | st.getAttachments().add(att); 59 | 60 | st.setAuthority(getAgent("Authority", "mbox", "mailto:authority@example.com")); 61 | 62 | st.setContext(new Context()); 63 | st.getContext().setLanguage("en-US"); 64 | 65 | st.setId(UUID.randomUUID()); 66 | 67 | st.setResult(new Result()); 68 | st.getResult().setCompletion(true); 69 | 70 | st.setStored(new DateTime()); 71 | st.setTimestamp(new DateTime()); 72 | st.setVerb(new Verb("http://example.com/verb")); 73 | 74 | for (StatementTarget target : statementTargets) { 75 | st.setObject(target); 76 | assertSerializeDeserialize(st); 77 | } 78 | } 79 | 80 | 81 | /** 82 | * To assert that {@Link Statement(StringOfJSON)} converts all textbased-elements in StringOfJSON to {@Link Statement} 83 | * 84 | * @throws Exception 85 | */ 86 | @Test 87 | public void StatementConstructorTest() throws Exception { 88 | 89 | List statementTargets = new ArrayList(); 90 | statementTargets.add(new Activity("http://example.com/activity")); 91 | statementTargets.add(getAgent("Target", "mbox", "mailto:target@example.com")); 92 | statementTargets.add(new StatementRef(UUID.randomUUID())); 93 | 94 | SubStatement sub = new SubStatement(); 95 | sub.setActor(getAgent("Sub", "mbox", "mailto:sub@example.com")); 96 | sub.setVerb(new Verb("http://example.com/verb")); 97 | sub.setObject(new Activity("http://example.com/sub-activity")); 98 | statementTargets.add(sub); 99 | 100 | Statement st = new Statement(); 101 | st.setActor(getAgent("Joe", "mbox", "mailto:joe@example.com")); 102 | 103 | st.setAttachments(new ArrayList()); 104 | Attachment att = new Attachment(); 105 | att.setSha2("abc"); 106 | st.getAttachments().add(att); 107 | 108 | st.setAuthority(getAgent("Authority", "mbox", "mailto:authority@example.com")); 109 | 110 | st.setContext(new Context()); 111 | st.getContext().setLanguage("en-US"); 112 | 113 | st.setId(UUID.randomUUID()); 114 | 115 | st.setResult(new Result()); 116 | st.getResult().setCompletion(true); 117 | 118 | st.setStored(new DateTime()); 119 | st.setTimestamp(new DateTime()); 120 | st.setVerb(new Verb("http://example.com/verb")); 121 | 122 | 123 | for (StatementTarget target : statementTargets) { 124 | st.setObject(target); 125 | 126 | Statement tmpStatement = new Statement(new StringOfJSON(st.toJSON())); 127 | 128 | assertThat(st.toJSON(), is(tmpStatement.toJSON())); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/StatementsQueryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.*; 19 | import static org.junit.Assert.assertTrue; 20 | 21 | import java.net.URI; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.UUID; 27 | 28 | import lombok.Data; 29 | 30 | import org.joda.time.DateTime; 31 | import org.junit.Test; 32 | 33 | import com.rusticisoftware.tincan.v10x.StatementsQuery; 34 | 35 | /** 36 | * StatementsQueryTest Class Description 37 | */ 38 | @Data 39 | public class StatementsQueryTest { 40 | @Test 41 | public void v10SerializeDeserialize() throws Exception { 42 | StatementsQuery query = new StatementsQuery(); 43 | query.setActivityID(new URI("http://example.com/activity")); 44 | query.setAgent(getAgent("Joe", "mbox", "mailto:joeuser@example.com")); 45 | query.setAscending(true); 46 | query.setFormat(QueryResultFormat.EXACT); 47 | query.setLimit(10); 48 | query.setRegistration(UUID.randomUUID()); 49 | query.setRelatedActivities(true); 50 | query.setRelatedAgents(true); 51 | query.setSince(new DateTime()); 52 | query.setUntil(new DateTime()); 53 | query.setVerbID("http://example.com/verb"); 54 | 55 | //Rudimentary, but something... 56 | List expected = new ArrayList( 57 | Arrays.asList(new String[]{ 58 | "agent", "verb", "activity", "registration", 59 | "related_activities", "related_agents", "since", 60 | "until", "limit", "format", "ascending" 61 | })); 62 | 63 | Map paramMap = query.toParameterMap(); 64 | for (String key : expected) { 65 | assertTrue(paramMap.containsKey(key)); 66 | } 67 | } 68 | 69 | public void v95SerializeDeserialize() throws Exception { 70 | com.rusticisoftware.tincan.v095.StatementsQuery query; 71 | query = new com.rusticisoftware.tincan.v095.StatementsQuery(); 72 | query.setActor(getAgent("Joe", "mbox", "mailto:joeuser@example.com")); 73 | query.setAscending(true); 74 | query.setAuthoritative(true); 75 | query.setContext(true); 76 | query.setInstructor(getAgent("Instructor", "mbox", "mailto:instructor@example.com")); 77 | query.setLimit(10); 78 | query.setObject(new Activity("http://example.com/activity")); 79 | query.setRegistration(UUID.randomUUID()); 80 | query.setSince(new DateTime()); 81 | query.setSparse(true); 82 | query.setUntil(new DateTime()); 83 | query.setVerbID("http://example.com/verb"); 84 | 85 | List expected = new ArrayList( 86 | Arrays.asList(new String[]{ 87 | "actor", "verb", "object", "registration", "context", 88 | "since", "until", "limit", "authoritative", 89 | "sparse", "instructor", "ascending" 90 | })); 91 | 92 | Map paramMap = query.toParameterMap(); 93 | for (String key : expected) { 94 | assertTrue(paramMap.containsKey(key)); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/StatementsResultTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static com.rusticisoftware.tincan.TestUtils.getAgent; 20 | 21 | import java.util.ArrayList; 22 | 23 | import org.junit.Test; 24 | 25 | /** 26 | * Description 27 | */ 28 | public class StatementsResultTest { 29 | @Test 30 | public void serializeDeserialize() throws Exception { 31 | 32 | StatementsResult result = new StatementsResult(); 33 | result.setStatements(new ArrayList()); 34 | Statement st = new Statement(); 35 | st.setActor(getAgent("Joe", "mbox", "mailto:joe@example.com")); 36 | st.setVerb(new Verb("http://example.com/verb")); 37 | st.setObject(new Activity("http://example.com/activity")); 38 | result.getStatements().add(st); 39 | result.getStatements().add(st); 40 | result.setMoreURL("/statements?continueToken=abc"); 41 | 42 | assertSerializeDeserialize(result); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/SubStatementTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | import static com.rusticisoftware.tincan.TestUtils.getAgent; 20 | import lombok.Data; 21 | 22 | import org.joda.time.DateTime; 23 | import org.junit.Test; 24 | 25 | /** 26 | * SubStatementTest Class Description 27 | */ 28 | @Data 29 | public class SubStatementTest { 30 | 31 | @Test 32 | public void serializeDeserialize() throws Exception { 33 | SubStatement st = new SubStatement(); 34 | st.setActor(getAgent("Joe", "mbox", "mailto:joe@example.com")); 35 | 36 | st.setContext(new Context()); 37 | st.getContext().setLanguage("en-US"); 38 | 39 | st.setObject(new Activity("http://example.com/activity")); 40 | 41 | st.setResult(new Result()); 42 | st.getResult().setCompletion(true); 43 | 44 | st.setTimestamp(new DateTime()); 45 | st.setVerb(new Verb("http://example.com/verb")); 46 | 47 | assertSerializeDeserialize(st); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/TestUtils.java: -------------------------------------------------------------------------------- 1 | package com.rusticisoftware.tincan; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import java.lang.reflect.Constructor; 5 | 6 | import com.fasterxml.jackson.databind.JsonNode; 7 | import com.rusticisoftware.tincan.json.JSONBase; 8 | import com.rusticisoftware.tincan.json.StringOfJSON; 9 | 10 | public class TestUtils { 11 | public static Agent getAgent(String name, String idType, String idFields) { 12 | Agent agent = new Agent(); 13 | agent.setName(name); 14 | if ("mbox".equals(idType)) { 15 | agent.setMbox(idFields); 16 | } 17 | else if ("openid".equals(idType)) { 18 | agent.setOpenID(idFields); 19 | } 20 | else if ("mbox_sha1sum".equals(idType)) { 21 | agent.setMboxSHA1Sum(idFields); 22 | } 23 | else if ("account".equals(idType)) { 24 | String[] parts = idFields.split("|"); 25 | AgentAccount acct = new AgentAccount(); 26 | acct.setHomePage(parts[0]); 27 | acct.setName(parts[1]); 28 | agent.setAccount(acct); 29 | } 30 | return agent; 31 | } 32 | 33 | public static void assertSerializeDeserialize(T object) throws Exception { 34 | for (TCAPIVersion version : TCAPIVersion.values()) { 35 | assertSerializeDeserialize(object, version); 36 | } 37 | } 38 | 39 | public static void assertSerializeDeserialize(T object, TCAPIVersion version) throws Exception { 40 | String objJson = object.toJSON(version); 41 | Constructor con = object.getClass().getConstructor(JsonNode.class); 42 | JSONBase clone = (JSONBase)con.newInstance(new StringOfJSON(objJson).toJSONNode()); 43 | assertEquals(objJson, clone.toJSON(version)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/rusticisoftware/tincan/VerbTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Rustici Software 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.rusticisoftware.tincan; 17 | 18 | import static com.rusticisoftware.tincan.TestUtils.assertSerializeDeserialize; 19 | 20 | import org.junit.Test; 21 | 22 | /** 23 | * Description 24 | */ 25 | public class VerbTest { 26 | @Test 27 | public void serializeDeserialize() throws Exception { 28 | Verb verb = new Verb(); 29 | verb.setId("http://example.com/attempted"); 30 | verb.setDisplay(new LanguageMap()); 31 | verb.getDisplay().put("en-US", "attempted"); 32 | assertSerializeDeserialize(verb); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/resources/files/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RusticiSoftware/TinCanJava/a860344066395b835cb24ad81e9a0bd6279ebcd7/src/test/resources/files/image.jpg -------------------------------------------------------------------------------- /src/test/resources/lrs.properties.template: -------------------------------------------------------------------------------- 1 | endpoint= 2 | username= 3 | password= 4 | -------------------------------------------------------------------------------- /src/test/resources/travis-ci.properties: -------------------------------------------------------------------------------- 1 | # 2 | # special app ID and credentials set up specifically for 3 | # OSS library testing via CI 4 | # 5 | endpoint=https://cloud.scorm.com/tc/WFY8RW8IKR/sandbox/ 6 | username=nudTAAxcm3d58SK1ROQ 7 | password=nyN50AXB_rUuq82JG1I 8 | --------------------------------------------------------------------------------