├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── contributing.adoc ├── install.gif ├── java.gif ├── key.png ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── modzy │ │ └── sdk │ │ ├── JobClient.java │ │ ├── ModelClient.java │ │ ├── ModzyClient.java │ │ ├── ResultClient.java │ │ ├── TagClient.java │ │ ├── dto │ │ ├── EmbeddedData.java │ │ ├── JobHistoryResponseWrapper.java │ │ ├── JobHistorySearchParams.java │ │ ├── JobHistorySearchStatus.java │ │ ├── ModelSearchParams.java │ │ ├── Pagination.java │ │ ├── S3FileRef.java │ │ └── TagWrapper.java │ │ ├── exception │ │ └── ApiException.java │ │ ├── filter │ │ └── LoggingFilter.java │ │ ├── model │ │ ├── ContainerImage.java │ │ ├── Feature.java │ │ ├── Image.java │ │ ├── Job.java │ │ ├── JobInput.java │ │ ├── JobInputEmbedded.java │ │ ├── JobInputJDBC.java │ │ ├── JobInputS3.java │ │ ├── JobInputStream.java │ │ ├── JobInputText.java │ │ ├── JobOutput.java │ │ ├── JobOutputJSON.java │ │ ├── JobStatus.java │ │ ├── Model.java │ │ ├── ModelInput.java │ │ ├── ModelOutput.java │ │ ├── ModelTimeout.java │ │ ├── ModelVersion.java │ │ ├── Requirement.java │ │ ├── Statistic.java │ │ ├── Tag.java │ │ └── Team.java │ │ ├── samples │ │ ├── JobAwsInputSample.java │ │ ├── JobEmbeddedInputSample.java │ │ ├── JobFileInputSample.java │ │ ├── JobTextInputSample.java │ │ └── ModelSamples.java │ │ └── util │ │ ├── DataSize.java │ │ ├── EmbeddedSerializer.java │ │ ├── FileUtils.java │ │ └── LoggerFactory.java └── resources │ ├── logging.properties │ └── samples │ ├── config.json │ └── image.png └── test ├── java └── com │ └── modzy │ └── sdk │ ├── TestJobClient.java │ ├── TestModelClient.java │ ├── TestModzyClient.java │ ├── TestResultClient.java │ └── TestTagClient.java └── resources ├── images └── example_1.jpg └── logging.properties /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Checklist 2 | 3 | Please review first that the issue is fully related with this SDK by checking the relevant checkboxes (`[x]`). 4 | 5 | - [ ] I have a Modzy API Key active and have the entitlements to perform the desired action. 6 | - [ ] I review that have access to Modzy API host. 7 | - [ ] I think that is a error specific to the SDK. 8 | - [ ] I review the documentation and existing issues in order to not duplicate existing ones. 9 | - [ ] I am willing to follow-up on comments in a timely manner. 10 | 11 | ### Info 12 | 13 | * Modzy SDK version: 14 | * Java version: 15 | * Operating System: 16 | 17 | ### Description 18 | 19 | 20 | 21 | ### Steps to reproduce 22 | 23 | 24 | 25 | ``` 26 | Paste the command(s) you ran and the output. 27 | ``` 28 | 29 | **Expected results:** 30 | 31 | **Actual results:** 32 | 33 | ### Traceback 34 | 35 |
36 | Logs 37 | 42 | 43 | ``` 44 | Paste the logs that you consider useful for diagnostic. 45 | ``` 46 |
47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Related issues 6 | 7 | 8 | 9 | ## Tests 10 | 11 | 12 | 13 | ## Checklist 14 | 15 | - [ ] I read the Contributing guide. 16 | - [ ] I update the documentation and if the case the README.md file. 17 | - [ ] I am willing to follow-up on review comments in a timely manner. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | bin/ 3 | tmp/ 4 | *.tmp 5 | *.bak 6 | *.swp 7 | *~.nib 8 | local.properties 9 | .settings/ 10 | .idea/ 11 | modzy-sdk.iml 12 | .loadpath 13 | .recommenders 14 | .env 15 | docs 16 | # External tool builders 17 | .externalToolBuilders/ 18 | 19 | # Locally stored "Eclipse launch configurations" 20 | *.launch 21 | 22 | # PyDev specific (Python IDE for Eclipse) 23 | *.pydevproject 24 | 25 | # CDT-specific (C/C++ Development Tooling) 26 | .cproject 27 | 28 | # CDT- autotools 29 | .autotools 30 | 31 | # Java annotation processor (APT) 32 | .factorypath 33 | 34 | # PDT-specific (PHP Development Tools) 35 | .buildpath 36 | 37 | # sbteclipse plugin 38 | .target 39 | 40 | # Tern plugin 41 | .tern-project 42 | 43 | # TeXlipse plugin 44 | .texlipse 45 | 46 | # STS (Spring Tool Suite) 47 | .springBeans 48 | 49 | # Code Recommenders 50 | .recommenders/ 51 | 52 | # Annotation Processing 53 | .apt_generated/ 54 | 55 | # Scala IDE specific (Scala & Java development for Eclipse) 56 | .cache-main 57 | .scala_dependencies 58 | .worksheet 59 | 60 | ### Eclipse Patch ### 61 | # Eclipse Core 62 | .project 63 | 64 | # JDT-specific (Eclipse Java Development Tools) 65 | .classpath 66 | 67 | # Annotation Processing 68 | .apt_generated 69 | 70 | .sts4-cache/ 71 | 72 | ### Git ### 73 | # Created by git for backups. To disable backups in Git: 74 | # $ git config --global mergetool.keepBackup false 75 | *.orig 76 | 77 | # Created by git when using merge tools for conflicts 78 | *.BACKUP.* 79 | *.BASE.* 80 | *.LOCAL.* 81 | *.REMOTE.* 82 | *_BACKUP_*.txt 83 | *_BASE_*.txt 84 | *_LOCAL_*.txt 85 | *_REMOTE_*.txt 86 | 87 | ### Java ### 88 | # Compiled class file 89 | *.class 90 | 91 | # Log file 92 | *.log 93 | 94 | # BlueJ files 95 | *.ctxt 96 | 97 | # Mobile Tools for Java (J2ME) 98 | .mtj.tmp/ 99 | 100 | # Package Files # 101 | *.jar 102 | *.war 103 | *.nar 104 | *.ear 105 | *.zip 106 | *.tar.gz 107 | *.rar 108 | 109 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 110 | hs_err_pid* 111 | 112 | ### Maven ### 113 | target/ 114 | pom.xml.tag 115 | pom.xml.releaseBackup 116 | pom.xml.versionsBackup 117 | pom.xml.next 118 | release.properties 119 | dependency-reduced-pom.xml 120 | buildNumber.properties 121 | .mvn/timing.properties 122 | .mvn/wrapper/maven-wrapper.jar 123 | .flattened-pom.xml 124 | 125 | ### Windows ### 126 | # Windows thumbnail cache files 127 | Thumbs.db 128 | Thumbs.db:encryptable 129 | ehthumbs.db 130 | ehthumbs_vista.db 131 | 132 | # Dump file 133 | *.stackdump 134 | 135 | # Folder config file 136 | [Dd]esktop.ini 137 | 138 | # Recycle Bin used on file shares 139 | $RECYCLE.BIN/ 140 | 141 | # Windows Installer files 142 | *.cab 143 | *.msi 144 | *.msix 145 | *.msm 146 | *.msp 147 | 148 | # Windows shortcuts 149 | *.lnk 150 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 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 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series 87 | of actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or 94 | permanent ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within 114 | the community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.0, available at 120 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 121 | 122 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 123 | enforcement ladder](https://github.com/mozilla/diversity). 124 | 125 | [homepage]: https://www.contributor-covenant.org 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | https://www.contributor-covenant.org/faq. Translations are available at 129 | https://www.contributor-covenant.org/translations. 130 | 131 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modzy Java SDK 2 | 3 | ![Modzy Logo](https://www.modzy.com/wp-content/uploads/2020/06/MODZY-RGB-POS.png) 4 | 5 |
6 | 7 | **Modzy's Java SDK queries models, submits inference jobs, and returns results directly to your editor.** 8 | 9 | 10 | ![GitHub contributors](https://img.shields.io/github/contributors/modzy/sdk-java) 11 | ![GitHub last commit](https://img.shields.io/github/last-commit/modzy/sdk-java) 12 | ![GitHub Release Date](https://img.shields.io/github/issues-raw/modzy/sdk-java) 13 | 14 | 15 | [The job lifecycle](https://docs.modzy.com/reference/the-job-lifecycle) | [API Keys](https://docs.modzy.com/reference/api-keys-1) | [Samples](https://github.com/modzy/sdk-java/tree/main/samples) | [Documentation](https://docs.modzy.com/docs) 16 | 17 |
18 | 19 | ## Installation 20 | 21 | [![installation](https://github.com/modzy/sdk-java/raw/main/install.gif)](https://asciinema.org/a/CMMbns4Pp4TpTkZdXgMFiguDs) 22 | 23 | Clone the repository: 24 | 25 | - `$ git clone https://github.com/modzy/sdk-java.git` 26 | 27 | Use [maven](https://maven.apache.org/) to install the SDK. 28 | 29 | - `$ ./mvnw install -DskipTests=true` 30 | 31 | Add the dependency in your `pom.xml` file: 32 | 33 | ```xml 34 | 35 | com.modzy 36 | modzy-sdk 37 | 0.0.1 38 | 39 | ``` 40 | 41 | 42 | ### Get your API key 43 | 44 | 45 | 46 | API keys are security credentials required to perform API requests to Modzy. Our API keys are composed of an ID that is split by a dot into two parts: a public and private part. 47 | 48 | The *public* part is the API keys' visible part only used to identify the key and by itself, it’s unable to perform API requests. 49 | 50 | The *private* part is the public part's complement and it’s required to perform API requests. Since it’s not stored on Modzy’s servers, it cannot be recovered. Make sure to save it securely. If lost, you can [replace the API key](https://docs.modzy.com/reference/update-a-keys-body). 51 | 52 | 53 | Find your API key in your user profile. To get your full API key click on "Get key": 54 | 55 | get key 56 | 57 | 58 | 59 | ## Initialize 60 | 61 | Once you have a `model` and `version` identified, get authenticated with your API key. 62 | 63 | ```java 64 | ModzyClient modzyClient = new ModzyClient("http://url.to.modzy/api", "API Key"); 65 | ``` 66 | 67 | ## Basic usage 68 | 69 | ![Basic Usage](https://github.com/modzy/sdk-java/raw/main/java.gif) 70 | 71 | ### Browse models 72 | 73 | Modzy’s Marketplace includes pre-trained and re-trainable AI models from industry-leading machine learning companies, accelerating the process from data to value. 74 | 75 | The Model service drives the Marketplace and can be integrated with other applications, scripts, and systems. It provides routes to list, search, and filter model and model-version details. 76 | 77 | [List models](https://docs.modzy.com/reference/list-models): 78 | 79 | ```java 80 | List models = modzyClient.getAllModels(); 81 | for( Model model : models ){ 82 | System.out.println("Model: "+model); 83 | } 84 | ``` 85 | 86 | Tags help categorize and filter models. They make model browsing easier. 87 | 88 | [List tags](https://docs.modzy.com/reference/list-tags): 89 | 90 | ```java 91 | List tags = modzyClient.getTagClient().getAllTags(); 92 | for( Tag tag : tags ){ 93 | System.out.println("Tag: "+tag); 94 | } 95 | ``` 96 | 97 | [List models by tag](https://docs.modzy.com/reference/list-models-by-tag): 98 | 99 | ```java 100 | TagWrapper tagsModels = modzyClient.getTagsAndModels("language_and_text"); 101 | for( Model model : tagsModels.getModels() ){ 102 | System.out.println("Model: "+model); 103 | } 104 | ``` 105 | 106 | ### Get a model's details 107 | 108 | Models accept specific *input file [MIME](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) types*. Some models may require multiple input file types to run data accordingly. In this sample, we use a model that requires `text/plain`. 109 | 110 | Models require inputs to have a specific *input name* declared in the job request. This name can be found in the model’s details. In this sample, we use a model that requires `input.txt`. 111 | 112 | Additionally, users can set their own input names. When multiple input items are processed in a job, these names are helpful to identify and get each input’s results. In this sample, we use a model that requires `input-1` and `input-2`. 113 | 114 | [Get a model's details](https://docs.modzy.com/reference/list-model-details): 115 | 116 | ```java 117 | Model saModel = modzyClient.getModel("ed542963de"); 118 | System.out.println("Model: "+saModel); 119 | ``` 120 | 121 | Model specific sample requests are available in the version details and in the Model Details page. 122 | 123 | [Get version details](https://docs.modzy.com/reference/get-version-details): 124 | 125 | ```java 126 | ModelVersion modelVersion = modzyClient.getModelVersion("ed542963de", "0.0.27"); 127 | // then you'll get all the details about the specific model version 128 | System.out.println(String.format("ModelVersion details properties: %s", getNotNullProperties(modelVersion))); 129 | // Probably the more interesting are the ones related with the inputs and outputs of the model 130 | System.out.println(" inputs:"); 131 | for( ModelInput input : modelVersion.getInputs() ){ 132 | System.out.println( 133 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 134 | ); 135 | } 136 | System.out.println(" outputs:"); 137 | for( ModelOutput output : modelVersion.getOutputs() ){ 138 | System.out.println( 139 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 140 | ); 141 | } 142 | ``` 143 | 144 | ### Submit a job and get results 145 | 146 | A *job* is the process that sends data to a model, sets the model to run the data, and returns results. 147 | 148 | Modzy supports several *input types* such as `text`, `embedded` for Base64 strings, `aws-s3` and `aws-s3-folder` for inputs hosted in buckets, and `jdbc` for inputs stored in databases. In this sample, we use `text`. 149 | 150 | [Here](https://github.com/modzy/sdk-java/blob/readmeUpdates/samples.adoc) are samples to submit jobs with `embedded`, `aws-s3`, `aws-s3-folder`, and `jdbc` input types. 151 | 152 | [Submit a job with the model, version, and input items](https://docs.modzy.com/reference/create-a-job-1): 153 | 154 | ```java 155 | Job job = modzyClient.submitJobText("ed542963de", "0.0.27", "Modzy is great!"); 156 | ``` 157 | 158 | [Hold until the inference is complete and results become available](https://docs.modzy.com/reference/get-job-details): 159 | 160 | ```java 161 | Job job = modzyClient.blockUntilComplete(job, 20000); 162 | ``` 163 | 164 | [Get the results](https://docs.modzy.com/reference/get-results): 165 | 166 | Results are available per input item and can be identified with the name provided for each input item upon job request. You can also add an input name to the route and limit the results to any given input item. 167 | 168 | Jobs requested for multiple input items may have partial results available prior to job completion. 169 | 170 | ```java 171 | JobOutput jobResult = modzyClient.getResult(job); 172 | Map> results = jobResult.getResults(); 173 | ``` 174 | 175 | ### Fetch errors 176 | 177 | Errors may arise for different reasons. Fetch errors to know what is their cause and how to fix them. 178 | 179 | Error | Description 180 | ---------- | --------- 181 | `ApiException` | Wrapper for different exceptions, check the message and the stacktrace. 182 | 183 | 184 | Submitting jobs: 185 | 186 | ```javascript 187 | try{ 188 | Map retValue = this.modzyClient.submitJobTextBlockUntilComplete("ed542963de", "Modzy is great!"); 189 | } 190 | catch(ApiException ae){ 191 | System.out.println("The job submission fails with message "+ae.getMessage()); 192 | as.printStackTrace(); 193 | } 194 | ``` 195 | 196 | ## Features 197 | 198 | Modzy supports [batch processing](https://docs.modzy.com/reference/batch-processing), [explainability](https://docs.modzy.com/reference/explainability), and [model drift detection](https://docs.modzy.com/reference/model-drift-1). 199 | 200 | ## APIs 201 | 202 | Here is a list of Modzy APIs. To see all the APIs, check our [Documentation](https://docs.modzy.com/reference/introduction). 203 | 204 | 205 | | Feature | Code |Api route 206 | | --- | --- | --- 207 | |Get all models|modzyClient.getAllModels()|[api/models](https://docs.modzy.com/reference/get-all-models)| 208 | |List models|modzyClient.getModels()|[api/models](https://docs.modzy.com/reference/list-models)| 209 | |Get model details|modzyClient.getModel()|[api/models/:model-id](https://docs.modzy.com/reference/list-model-details)| 210 | |List models by name|modzyClient.getModelByName()|[api/models](https://docs.modzy.com/reference/list-models)| 211 | |List models by tags|modzyClient.getTagsAndModels()|[api/models/tags/:tag-id](https://docs.modzy.com/reference/list-models-by-tag) | 212 | |Get related models|modzyClient.getRelatedModels()|[api/models/:model-id/related-models](https://docs.modzy.com/reference/get-related-models)| 213 | |Get a model's versions|modzyClient.getModelVersions()|[api/models/:model-id/versions](https://docs.modzy.com/reference/list-versions)| 214 | |Get version details|modzyClient.getModelVersions()|[api/models/:model-id/versions/:version-id](https://docs.modzy.com/reference/get-version-details)| 215 | |List tags|modzyClient.getAllTags()|[api/models/tags](https://docs.modzy.com/reference/list-tags)| 216 | |Submit a Job (Text)|modzyClient.submitJobText()|[api/jobs](https://docs.modzy.com/reference/create-a-job-1)| 217 | |Submit a Job (Embedded)|modzyClient.submitJobEmbedded()|[api/jobs](https://docs.modzy.com/reference/create-a-job-1)| 218 | |Submit a Job (AWS S3)|modzyClient.submitJobAWSS3()|[api/jobs](https://docs.modzy.com/reference/create-a-job-1)| 219 | |Submit a Job (JDBC)|modzyClient.submitJobJDBC()|[api/jobs](https://docs.modzy.com/reference/create-a-job-1)| 220 | |Cancel a job|modzyClient.cancelJob()|[api/jobs/:job-id](https://docs.modzy.com/reference/cancel-a-job) | 221 | |Hold until inference is complete|modzyClient.blockUntilComplete()|[api/jobs/:job-id](https://docs.modzy.com/reference/get-job-details) | 222 | |Get job details|modzyClient.getJob()|[api/jobs/:job-id](https://docs.modzy.com/reference/get-job-details) | 223 | |Get results|modzyClient.getResults()|[api/results/:job-id](https://docs.modzy.com/reference/get-results) | 224 | |List the job history|modzyClient.getJobHistory()|[api/jobs/history](https://docs.modzy.com/reference/list-the-job-history) | 225 | 226 | ## Samples 227 | 228 | Check out our [samples](https://github.com/modzy/sdk-java/tree/main/java/com/modzy/sdk/samples) for details on specific use cases. 229 | 230 | To run samples: 231 | 232 | Set the base url and api key in each sample file: 233 | 234 | ```javascript 235 | // TODO: set the base url of modzy api and you api key 236 | ModzyClient modzyClient = new ModzyClient("https://http://modzy.url", "modzy-api.key"); 237 | ``` 238 | 239 | Or follow the instructions [here](https://github.com/modzy/sdk-java/tree/main/contributing.adoc#set-environment-variables-in-bash) to learn more. 240 | 241 | And then, you can: 242 | 243 | ```bash 244 | $ ./mvnw exec:java -Dexec.mainClass="com.modzy.sdk.samples.ModelSamples" 245 | ``` 246 | ## Contributing 247 | 248 | We are happy to receive contributions from all of our users. Check out our [contributing file](https://github.com/modzy/sdk-java/tree/main/contributing.adoc) to learn more. 249 | 250 | ## Code of conduct 251 | 252 | 253 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/modzy/sdk-java/tree/main//CODE_OF_CONDUCT.md) 254 | -------------------------------------------------------------------------------- /contributing.adoc: -------------------------------------------------------------------------------- 1 | :doctype: article 2 | :icons: font 3 | :source-highlighter: highlightjs 4 | :docname: Java SDK 5 | 6 | 7 | 8 | 9 | 10 | ++++ 11 | 12 |
13 | 14 |

Contributing to Modzy's Java SDK

15 | 16 |
17 |
18 |
19 |
20 | 21 | 22 | 23 | GitHub contributors 24 | 25 | GitHub last commit 26 | 27 | GitHub Release Date 28 | 29 |
30 |
31 | 32 | Contributor Covenant 33 | 34 |
35 | 36 |
37 |
38 | 39 |
40 | Readme | 41 | Documentation 42 | 43 |
44 | 45 |
46 |
47 |
48 |
49 | 50 | ++++ 51 | 52 | Contributions are welcome and they are greatly appreciated! Every little bit helps, and credit will always be given. 53 | 54 | Below you'll find our contributing requirements, a step-by-step guideline, and our features roadmap. 55 | 56 | 57 | == Requirements 58 | 59 | - Search previous link:https://github.com/modzy/sdk-java/issues[issues] before making new ones to avoid duplicates. 60 | - If you are reporting a bug, please include: 61 | . Your operating system name and version. 62 | . Any details about your local setup that might be helpful in troubleshooting. 63 | . Detailed steps to reproduce the bug. 64 | - If you are proposing a feature: 65 | . Explain in detail how it would work. 66 | . Keep the scope as narrow as possible, to make it easier to implement. 67 | . Remember that this is a volunteer-driven project, and that contributions are welcome. 68 | - File an issue to let us know what you're working on. 69 | - Fork the repo, develop and test your code changes, and add supporting documentation. 70 | - Use descriptive comments throughout your code. 71 | - Add test cases and comment them. 72 | //- Check your spelling and grammar. 73 | - Use descriptive commit messages that clearly explain the changes. Reference the original issue in the pull request. 74 | - Make an individual pull request for each issue. 75 | 76 | 77 | 78 | == Guidelines 79 | 80 | 81 | === 1. Fork the repo and set it for local development 82 | 83 | Clone the repository: 84 | 85 | - `$ git clone https://github.com/modzy/sdk-java.git` 86 | 87 | Install dependencies: 88 | 89 | - `$ mvn compile -DskipTests=true` 90 | 91 | Create a branch for your awesome new feature: 92 | 93 | - `$ git checkout -b my-new-awesome-feature` 94 | 95 | 96 | === 2. Develop your changes 97 | 98 | Fix that bug or build your feature. 99 | 100 | === 3. Run unit tests 101 | 102 | Configure the environment variables to easily run all the tests with a single configuration point. 103 | 104 | You can: 105 | 106 | ==== Set environment variables in bash 107 | 108 | ===== Windows 109 | 110 | [source,bash] 111 | ---- 112 | set MODZY_BASE_URL=http://modzy.com/api 113 | set MODZY_API_KEY=my_key.modzy 114 | ---- 115 | 116 | ===== Unix 117 | 118 | [source,bash] 119 | ---- 120 | export MODZY_BASE_URL=http://modzy.com/api 121 | export MODZY_API_KEY=my_key.modzy 122 | ---- 123 | 124 | ==== Use `.env` file 125 | 126 | Create a `.env` file in the root folder with your API key: 127 | 128 | [source,java] 129 | ---- 130 | MODZY_BASE_URL=http://modzy.com/api 131 | MODZY_API_KEY=my_key.modzy 132 | 133 | ---- 134 | 135 | Run tests: 136 | 137 | - `$ mvn test` 138 | 139 | Or specify the test that you want to run: 140 | 141 | - `$ mvn -Dtest=TestModelClient test` 142 | 143 | === 4. Document your changes 144 | 145 | Add supporting documentation for your code. 146 | 147 | //what else would be useful for Raúl? 148 | 149 | === 5. Send a pull request 150 | 151 | Add and commit your changes: 152 | 153 | - `git add .` 154 | 155 | - `$ git commit "A descriptive message"` 156 | 157 | Push your branch to GitHub: 158 | 159 | - `$ git push origin my-new-awesome-feature` 160 | 161 | 162 | //== Code of conduct 163 | 164 | 165 | 166 | == Roadmap 167 | 168 | - Wider API coverage (custom models, accounting, audit, etc). 169 | - [Maybe] Add retry logic for possibly transient issues. 170 | - Fetch model list errors. 171 | 172 | 173 | 174 | 175 | == Support 176 | 177 | Use GitHub to report bugs and send feature requests. + 178 | Reach out to https://www.modzy.com/support/ for support requests. 179 | -------------------------------------------------------------------------------- /install.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modzy/sdk-java/42f188a12e286cd470db9178a33c3ee2e9243def/install.gif -------------------------------------------------------------------------------- /java.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modzy/sdk-java/42f188a12e286cd470db9178a33c3ee2e9243def/java.gif -------------------------------------------------------------------------------- /key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modzy/sdk-java/42f188a12e286cd470db9178a33c3ee2e9243def/key.png -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.modzy 6 | modzy-sdk 7 | jar 8 | 9 | 0.0.1 10 | Modzy Java SDK 11 | Java API client for Modzy 12 | https://github.boozallencsn.com/AI/modzy-java.git 13 | 14 | 15 | 1.8 16 | 1.8 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.glassfish.jersey.core 23 | jersey-client 24 | 2.25.1 25 | 26 | 27 | org.glassfish.jersey.media 28 | jersey-media-json-jackson 29 | 2.31 30 | 31 | 32 | org.glassfish.jersey.media 33 | jersey-media-multipart 34 | 2.30.1 35 | 36 | 37 | javax.xml.bind 38 | jaxb-api 39 | 2.3.1 40 | 41 | 42 | commons-io 43 | commons-io 44 | 2.6 45 | 46 | 47 | io.github.cdimascio 48 | java-dotenv 49 | 5.1.4 50 | 51 | 52 | junit 53 | junit 54 | 4.13-beta-1 55 | test 56 | 57 | 58 | org.projectlombok 59 | lombok 60 | RELEASE 61 | compile 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.codehaus.mojo 69 | cobertura-maven-plugin 70 | 2.7 71 | 72 | 73 | html 74 | xml 75 | 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-javadoc-plugin 82 | 3.0.0 83 | 84 | 85 | attach-javadocs 86 | 87 | jar 88 | 89 | 90 | none 91 | false 92 | 93 | 94 | 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-surefire-plugin 99 | 2.21.0 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/JobClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.logging.Level; 10 | import java.util.logging.Logger; 11 | 12 | import javax.ws.rs.ProcessingException; 13 | import javax.ws.rs.WebApplicationException; 14 | import javax.ws.rs.client.Entity; 15 | import javax.ws.rs.client.Invocation.Builder; 16 | import javax.ws.rs.client.ResponseProcessingException; 17 | import javax.ws.rs.client.WebTarget; 18 | import javax.ws.rs.core.GenericType; 19 | import javax.ws.rs.core.MediaType; 20 | import javax.ws.rs.core.Response; 21 | 22 | 23 | import com.fasterxml.jackson.core.type.TypeReference; 24 | import com.fasterxml.jackson.databind.ObjectMapper; 25 | import com.modzy.sdk.dto.JobHistorySearchParams; 26 | import com.modzy.sdk.exception.ApiException; 27 | import com.modzy.sdk.model.Job; 28 | import com.modzy.sdk.model.JobInput; 29 | import com.modzy.sdk.model.JobInputStream; 30 | import com.modzy.sdk.model.JobStatus; 31 | import com.modzy.sdk.model.Model; 32 | import com.modzy.sdk.model.ModelVersion; 33 | import com.modzy.sdk.util.DataSize; 34 | import org.glassfish.jersey.media.multipart.MultiPart; 35 | import com.modzy.sdk.util.LoggerFactory; 36 | import org.glassfish.jersey.media.multipart.MultiPartFeature; 37 | import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart; 38 | 39 | /** 40 | * 41 | * Client of the Job API Services 42 | * 43 | */ 44 | public class JobClient { 45 | 46 | private static final String REST_PATH = "jobs"; 47 | 48 | private WebTarget restTarget; 49 | 50 | private String apiKey; 51 | 52 | private Logger logger; 53 | 54 | public JobClient(WebTarget baseTarget, String apiKey) { 55 | super(); 56 | this.logger = LoggerFactory.getLogger(this); 57 | this.restTarget = baseTarget.path(JobClient.REST_PATH); 58 | this.apiKey = apiKey; 59 | } 60 | 61 | /** 62 | * Wrapper of the GenericType necesary for process the response of the API 63 | * 64 | * @return A GenericType object for parse a list of Job instances 65 | */ 66 | private GenericType> getListType(){ 67 | return new GenericType>() {}; 68 | } 69 | 70 | /** 71 | * 72 | * Call the Modzy API Service and query on the history of jobs 73 | * 74 | * @param searchParams search parameters see {@link JobHistorySearchParams class} 75 | * @return List of Jobs according to the search params 76 | * @throws ApiException if there is something wrong with the service or the call 77 | */ 78 | public List getJobHistory(JobHistorySearchParams searchParams) throws ApiException{ 79 | WebTarget webTarget = this.restTarget.path("history"); 80 | ObjectMapper objMapper = new ObjectMapper(); 81 | Map map = objMapper.convertValue(searchParams, new TypeReference>() {} ); 82 | for( Map.Entry entry : map.entrySet() ) { 83 | webTarget = webTarget.queryParam( entry.getKey(), entry.getValue() ); 84 | } 85 | Builder builder = webTarget.request(MediaType.APPLICATION_JSON); 86 | builder.header("Authorization", "ApiKey "+this.apiKey); 87 | try { 88 | logger.info("querying job history "+webTarget.getUri()); 89 | return builder.get(this.getListType()); 90 | } 91 | catch(ResponseProcessingException rpe) { 92 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 93 | throw new ApiException(rpe); 94 | } 95 | catch(ProcessingException pr) { 96 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 97 | throw new ApiException(pr); 98 | } 99 | catch(WebApplicationException wae) { 100 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 101 | throw new ApiException(wae); 102 | } 103 | } 104 | 105 | 106 | /** 107 | * 108 | * Call the Modzy API Service that post a new job and return it's instance 109 | * 110 | * @param job the job instance to pass to Modzy 111 | * @return the updated instance of the Job returned by Modzy API 112 | * @throws ApiException if there is something wrong with the service or the call 113 | */ 114 | public Job submitJob(Job job) throws ApiException{ 115 | if( job.getInput() != null && job.getInput() instanceof JobInputStream){ 116 | return submitOpenJob(job); 117 | } 118 | Builder builder = this.restTarget.request(MediaType.APPLICATION_JSON); 119 | builder.header("Authorization", "ApiKey "+this.apiKey); 120 | try { 121 | logger.info("creating job: "+job); 122 | job = builder.post(Entity.entity(job, MediaType.APPLICATION_JSON), Job.class); 123 | job.setStatus( JobStatus.SUBMITTED ); 124 | return job; 125 | } catch(ResponseProcessingException rpe) { 126 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 127 | throw new ApiException(rpe); 128 | } catch(ProcessingException pr) { 129 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 130 | throw new ApiException(pr); 131 | } 132 | } 133 | 134 | /** 135 | * Call the Modzy API Services that post an open job and return it's final instance 136 | * 137 | * @param job 138 | * @return 139 | * @throws ApiException 140 | */ 141 | private Job submitOpenJob(Job job) throws ApiException{ 142 | //Open the job 143 | Job openJob = this.submitJob(new Job(job.getModel())); 144 | // 145 | int chunkSize = 1024*1024; 146 | try{ 147 | Map features = this.getFeatures(); 148 | DataSize dataSize = new DataSize(features.get("inputChunkMaximumSize")); 149 | chunkSize = dataSize.getBytes().intValue(); 150 | } catch(ApiException ae){ 151 | this.logger.log(Level.WARNING, "Unexpected exception parsing the features, asuming defaults", ae); 152 | } 153 | //Iterate and submit the inputs 154 | try { 155 | JobInput jobInput = (JobInput) job.getInput(); 156 | for (Map.Entry> inputItem : jobInput.getSources().entrySet()) { 157 | for (Map.Entry dataItem : inputItem.getValue().entrySet()) { 158 | appendInput(openJob, inputItem.getKey(), dataItem.getKey(), dataItem.getValue(), chunkSize); 159 | } 160 | } 161 | } catch( ApiException ae ){ 162 | this.logger.log(Level.SEVERE, ae.getMessage(), ae); 163 | try{ 164 | this.cancelJob(openJob); 165 | } catch( ApiException e2 ){ 166 | this.logger.log(Level.WARNING, "Unexpected exception trying to cancel the job", e2); 167 | } 168 | throw ae; 169 | } 170 | //Close the job 171 | return this.closeJob(openJob); 172 | } 173 | 174 | private void appendInput(Job job, String inputItemKey, String dataItemKey, InputStream inputValue, int chunkSize) throws ApiException{ 175 | Builder builder = this.restTarget 176 | .register(MultiPartFeature.class) 177 | .path(job.getJobIdentifier()).path(inputItemKey).path(dataItemKey) 178 | .request(MediaType.MULTIPART_FORM_DATA); 179 | builder.header("Authorization", "ApiKey "+this.apiKey); 180 | BufferedInputStream bis; 181 | MultiPart data; 182 | byte inputBuffer[] = new byte[chunkSize]; 183 | int chunkByteCount; 184 | try { 185 | bis = new BufferedInputStream(inputValue, chunkSize); 186 | while( (chunkByteCount = bis.read(inputBuffer)) != -1 ){ 187 | logger.info("Adding input: "+job.getJobIdentifier()+" "+inputItemKey+" "+dataItemKey+" ["+chunkByteCount+"]"); 188 | data = new MultiPart(); 189 | data.bodyPart( new StreamDataBodyPart("input", new ByteArrayInputStream(inputBuffer, 0, chunkByteCount), dataItemKey) ); 190 | Response response = builder.post(Entity.entity(data, data.getMediaType())); 191 | if( response.getStatus() >= 400 ){ 192 | throw new ApiException("The server respond with a status "+response.getStatus()); 193 | } 194 | } 195 | } catch(ResponseProcessingException rpe) { 196 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 197 | throw new ApiException(rpe); 198 | } catch(ProcessingException pr) { 199 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 200 | throw new ApiException(pr); 201 | } catch (IOException ioe) { 202 | this.logger.log(Level.SEVERE, ioe.getMessage(), ioe); 203 | throw new ApiException("Error reading the input provided ["+inputItemKey+"/"+dataItemKey+"]", ioe); 204 | } 205 | } 206 | 207 | private Job closeJob(Job job) throws ApiException{ 208 | Builder builder = this.restTarget.path(job.getJobIdentifier()).path("close").request(MediaType.APPLICATION_JSON); 209 | builder.header("Authorization", "ApiKey "+this.apiKey); 210 | try { 211 | logger.info("closing job: "+job); 212 | job = builder.post(Entity.entity(null, MediaType.APPLICATION_JSON), Job.class); 213 | job.setStatus( JobStatus.SUBMITTED ); 214 | return job; 215 | } catch(ResponseProcessingException rpe) { 216 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 217 | throw new ApiException(rpe); 218 | } catch(ProcessingException pr) { 219 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 220 | throw new ApiException(pr); 221 | } 222 | } 223 | 224 | /** 225 | * 226 | * Create a new Job for the model at specific version with the input provided 227 | * 228 | * @param model The model instance in which the model will run 229 | * @param modelVersion The specific version of the model 230 | * @param jobInput The inputs of the model to pass to Modzy 231 | * @return the updated instance of the Job returned by Modzy API 232 | * @throws ApiException if there is something wrong with the service or the call 233 | */ 234 | public Job submitJob(Model model, ModelVersion modelVersion, JobInput jobInput) throws ApiException{ 235 | return this.submitJob( new Job(model, modelVersion, jobInput) ); 236 | } 237 | 238 | /** 239 | * 240 | * Create a new Job for the model at specific version with the input provided 241 | * 242 | * @param modelId identifier of the model 243 | * @param modelVersionId identifier of the model version 244 | * @param jobInput the inputs of the model to pass to Modzy 245 | * @return the updated instance of the Job returned by Modzy API 246 | * @throws ApiException if there is something wrong with the service or the call 247 | */ 248 | public Job submitJob(String modelId, String modelVersionId, JobInput jobInput) throws ApiException{ 249 | Model model = new Model(); 250 | model.setIdentifier(modelId); 251 | ModelVersion modelVersion = new ModelVersion(); 252 | modelVersion.setVersion(modelVersionId); 253 | return this.submitJob( new Job(model, modelVersion, jobInput) ); 254 | } 255 | 256 | /** 257 | * 258 | * Call the Modzy API Service that return a job instance by it's identifier 259 | * 260 | * @param jobId identifier of the job 261 | * @return A Job instance if the jobId param is valid 262 | * @throws ApiException if there is something wrong with the service or the call 263 | */ 264 | public Job getJob(String jobId) throws ApiException{ 265 | Builder builder = this.restTarget.path(jobId).request(MediaType.APPLICATION_JSON); 266 | builder.header("Authorization", "ApiKey "+this.apiKey); 267 | try { 268 | return builder.get(Job.class); 269 | } 270 | catch(ResponseProcessingException rpe) { 271 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 272 | throw new ApiException(rpe); 273 | } 274 | catch(ProcessingException pr) { 275 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 276 | throw new ApiException(pr); 277 | } 278 | catch(WebApplicationException wae) { 279 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 280 | throw new ApiException(wae); 281 | } 282 | } 283 | 284 | /** 285 | * 286 | * Refresh the state of the Job provided, this method is a shortcut to 287 | * {@link JobClient#getJob(String) getJob(jobId)} 288 | * 289 | * @param job the Job instance that will be refreshed 290 | * @return a updated job instance 291 | * @throws ApiException if there is something wrong with the service or the call 292 | */ 293 | public Job getJob(Job job) throws ApiException{ 294 | return this.getJob(job.getJobIdentifier()); 295 | } 296 | 297 | /** 298 | * 299 | * Call the Modzy API Service that cancel the Job by it's identifier 300 | * 301 | * @param jobId identifier of the Job 302 | * @return a Job Instance if the jobId param is a valid identifier 303 | * @throws ApiException if there is something wrong with the service or the call 304 | */ 305 | public Job cancelJob(String jobId) throws ApiException{ 306 | Builder builder = this.restTarget.path(jobId).request(MediaType.APPLICATION_JSON); 307 | builder.header("Authorization", "ApiKey "+this.apiKey); 308 | try { 309 | logger.info("canceling job "+jobId); 310 | return builder.delete(Job.class); 311 | } 312 | catch(ResponseProcessingException rpe) { 313 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 314 | throw new ApiException(rpe); 315 | } 316 | catch(ProcessingException pr) { 317 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 318 | throw new ApiException(pr); 319 | } 320 | catch(WebApplicationException wae) { 321 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 322 | throw new ApiException(wae); 323 | } 324 | } 325 | 326 | /** 327 | * 328 | * Cancel the Job provided, this method is a shortcut to 329 | * {@link JobClient#cancelJob(String) getJob(jobId)} 330 | * 331 | * @param job the Job instance that will be canceled 332 | * @return a updated job instance (hopefully canceled) 333 | * @throws ApiException if there is something wrong with the service or the call 334 | */ 335 | public Job cancelJob(Job job) throws ApiException{ 336 | this.logger.info("canceling job "+job); 337 | return this.cancelJob(job.getJobIdentifier()); 338 | } 339 | 340 | 341 | public Map getFeatures() throws ApiException{ 342 | Builder builder = this.restTarget.path("features").request(MediaType.APPLICATION_JSON); 343 | builder.header("Authorization", "ApiKey "+this.apiKey); 344 | try { 345 | return builder.get(Map.class); 346 | } 347 | catch(ResponseProcessingException rpe) { 348 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 349 | throw new ApiException(rpe); 350 | } 351 | catch(ProcessingException pr) { 352 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 353 | throw new ApiException(pr); 354 | } 355 | catch(WebApplicationException wae) { 356 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 357 | throw new ApiException(wae); 358 | } 359 | } 360 | 361 | } 362 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/ModelClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | import javax.ws.rs.ProcessingException; 9 | import javax.ws.rs.WebApplicationException; 10 | import javax.ws.rs.client.Invocation.Builder; 11 | import javax.ws.rs.client.ResponseProcessingException; 12 | import javax.ws.rs.client.WebTarget; 13 | import javax.ws.rs.core.GenericType; 14 | import javax.ws.rs.core.MediaType; 15 | 16 | import com.fasterxml.jackson.core.type.TypeReference; 17 | import com.fasterxml.jackson.databind.ObjectMapper; 18 | import com.modzy.sdk.dto.ModelSearchParams; 19 | import com.modzy.sdk.exception.ApiException; 20 | import com.modzy.sdk.model.Model; 21 | import com.modzy.sdk.model.ModelVersion; 22 | import com.modzy.sdk.util.LoggerFactory; 23 | 24 | /** 25 | * 26 | * Client of the Model API Services 27 | * 28 | */ 29 | public class ModelClient { 30 | 31 | private static final String REST_PATH = "models"; 32 | 33 | private WebTarget restTarget; 34 | 35 | private String apiKey; 36 | 37 | private Logger logger; 38 | 39 | public ModelClient(WebTarget baseTarget, String apiKey) { 40 | super(); 41 | this.logger = LoggerFactory.getLogger(this); 42 | this.restTarget = baseTarget.path(ModelClient.REST_PATH); 43 | this.apiKey = apiKey; 44 | } 45 | 46 | /** 47 | * Wrapper of the GenericType necesary for process the response of the API 48 | * 49 | * @return A GenericType object for parse a list of Model instances 50 | */ 51 | private GenericType> getListType(){ 52 | return new GenericType>() {}; 53 | } 54 | 55 | /** 56 | * Wrapper of the GenericType necesary for process the response of the ModelVersion API 57 | * 58 | * @return A GenericType object for parse a list of ModelVersion instances 59 | */ 60 | private GenericType> getVersionListType(){ 61 | return new GenericType>() {}; 62 | } 63 | 64 | /** 65 | * 66 | * Call the Modzy service that retrieve all models basic info (modelId, versions, and latestVersion) 67 | * 68 | * @return A list of all the Modzy models 69 | * @throws ApiException if there is something wrong with the service or the call 70 | */ 71 | public List getAllModels() throws ApiException{ 72 | return this.getModels(new ModelSearchParams() ); 73 | } 74 | 75 | /** 76 | * 77 | * Call the Modzy service that retrieve models basic info (modelId, versions, and latestVersion) 78 | * 79 | * @param searchParams filter for this api call 80 | * @return A list of all the Modzy models 81 | * @throws ApiException if there is something wrong with the service or the call 82 | */ 83 | public List getModels(ModelSearchParams searchParams) throws ApiException{ 84 | WebTarget webTarget = this.restTarget; 85 | ObjectMapper objMapper = new ObjectMapper(); 86 | Map map = objMapper.convertValue(searchParams, new TypeReference>() {} ); 87 | for( Map.Entry entry : map.entrySet() ) { 88 | webTarget = webTarget.queryParam( entry.getKey(), entry.getValue() ); 89 | } 90 | Builder builder = webTarget.request(MediaType.APPLICATION_JSON); 91 | builder.header("Authorization", "ApiKey "+this.apiKey); 92 | try { 93 | logger.info("getModels() :: "+webTarget.getUri()); 94 | return builder.get(this.getListType()); 95 | } 96 | catch(ResponseProcessingException rpe) { 97 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 98 | throw new ApiException(rpe); 99 | } 100 | catch(ProcessingException pr) { 101 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 102 | throw new ApiException(pr); 103 | } 104 | catch(WebApplicationException wae) { 105 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 106 | throw new ApiException(wae); 107 | } 108 | } 109 | 110 | /** 111 | * 112 | * Call the Modzy API Service that return a model instance by it's identifier 113 | * 114 | * @param modelId identifier of the model 115 | * @return A Model instance if the modelId param is valid 116 | * @throws ApiException if there is something wrong with the service or the call 117 | */ 118 | public Model getModel(String modelId) throws ApiException{ 119 | Builder builder = this.restTarget.path(modelId).request(MediaType.APPLICATION_JSON); 120 | builder.header("Authorization", "ApiKey "+this.apiKey); 121 | try { 122 | logger.info("getModel("+modelId+") :: Ready to call modzy api"); 123 | return builder.get(Model.class); 124 | } 125 | catch(ResponseProcessingException rpe) { 126 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 127 | throw new ApiException(rpe); 128 | } 129 | catch(ProcessingException pr) { 130 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 131 | throw new ApiException(pr); 132 | } 133 | catch(WebApplicationException wae) { 134 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 135 | throw new ApiException(wae); 136 | } 137 | } 138 | 139 | /** 140 | * 141 | * Call the Modzy API Service that return a model instance by it's identifier. 142 | * 143 | * @param modelName name of the model 144 | * @return A Model instance if the model name is valid 145 | * @throws ApiException if there is something wrong with the service or the call 146 | */ 147 | public Model getModelByName(String modelName) throws ApiException{ 148 | ModelSearchParams searchParams = new ModelSearchParams(); 149 | searchParams.setName(modelName); 150 | List models = this.getModels(searchParams); 151 | if( models != null && !models.isEmpty() ){ 152 | return this.getModel(models.get(0).getIdentifier()); 153 | } 154 | throw new ApiException("Model "+modelName+" not found"); 155 | } 156 | 157 | /** 158 | * 159 | * Call the Modzy API Service that return a model list related to a model identifier 160 | * 161 | * @param modelId identifier of the model 162 | * @return A list of Modzy Models related to the modelId param 163 | * @throws ApiException if there is something wrong with the service or the call 164 | */ 165 | public List getRelatedModels(String modelId) throws ApiException{ 166 | Builder builder = this.restTarget.path(modelId).path("related-models").request(MediaType.APPLICATION_JSON); 167 | builder.header("Authorization", "ApiKey "+this.apiKey); 168 | try { 169 | logger.info("getRelatedModels("+modelId+") :: Ready to call modzy api"); 170 | return builder.get(this.getListType()); 171 | } 172 | catch(ResponseProcessingException rpe) { 173 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 174 | throw new ApiException(rpe); 175 | } 176 | catch(ProcessingException pr) { 177 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 178 | throw new ApiException(pr); 179 | } 180 | catch(WebApplicationException wae) { 181 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 182 | throw new ApiException(wae); 183 | } 184 | } 185 | 186 | /** 187 | * 188 | * Call the Modzy API Service that return a model list related to a model 189 | * 190 | * @param model a valid model 191 | * @return A list of Modzy Models related to the model param 192 | * @throws ApiException if there is something wrong with the service or the call 193 | */ 194 | public List getRelatedModels(Model model) throws ApiException{ 195 | return this.getRelatedModels(model.getIdentifier()); 196 | } 197 | 198 | /** 199 | * Call the Modzy API Service that return a version list of a given model 200 | * @param modelId a valid model identificator 201 | * @return a list of Modzy versions of the model param 202 | * @throws ApiException if there is something wrong with the service or the call 203 | */ 204 | public List getModelVersions(String modelId) throws ApiException{ 205 | Builder builder = this.restTarget.path(modelId).path("versions").request(MediaType.APPLICATION_JSON); 206 | builder.header("Authorization", "ApiKey "+this.apiKey); 207 | try { 208 | logger.info("getModelVersions("+modelId+") :: Ready to call modzy api"); 209 | return builder.get(this.getVersionListType()); 210 | } 211 | catch(ResponseProcessingException rpe) { 212 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 213 | throw new ApiException(rpe); 214 | } 215 | catch(ProcessingException pr) { 216 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 217 | throw new ApiException(pr); 218 | } 219 | catch(WebApplicationException wae) { 220 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 221 | throw new ApiException(wae); 222 | } 223 | } 224 | 225 | /** 226 | * Call the Modzy API Service that return a version list of a given model 227 | * @param model a valid model 228 | * @return a list of Modzy versions of the model param 229 | * @throws ApiException if there is something wrong with the service or the call 230 | */ 231 | public List getModelVersions(Model model) throws ApiException{ 232 | return this.getModelVersions(model.getIdentifier()); 233 | } 234 | 235 | /** 236 | * Call the Modzy API Service that return a version object 237 | * @param modelId a valid model id 238 | * @param versionId a valid version id 239 | * @return a ModelVersion instance with the information 240 | * @throws ApiException if there is something wrong with the service or the call 241 | */ 242 | public ModelVersion getModelVersion(String modelId, String versionId) throws ApiException{ 243 | Builder builder = this.restTarget.path(modelId).path("versions").path(versionId).request(MediaType.APPLICATION_JSON); 244 | builder.header("Authorization", "ApiKey "+this.apiKey); 245 | try { 246 | logger.info("getModelVersion("+modelId+","+versionId+") :: Ready to call modzy api"); 247 | return builder.get(ModelVersion.class); 248 | } 249 | catch(ResponseProcessingException rpe) { 250 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 251 | throw new ApiException(rpe); 252 | } 253 | catch(ProcessingException pr) { 254 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 255 | throw new ApiException(pr); 256 | } 257 | catch(WebApplicationException wae) { 258 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 259 | throw new ApiException(wae); 260 | } 261 | } 262 | 263 | /** 264 | * Call the Modzy API Service that return the sample input for a model version 265 | * @param modelId a valid model id 266 | * @param versionId a valid version id 267 | * @return a json string instance with the information 268 | * @throws ApiException if there is something wrong with the service or the call 269 | */ 270 | public String getModelVersionInputSample(String modelId, String versionId) throws ApiException{ 271 | Builder builder = this.restTarget.path(modelId) 272 | .path("versions").path(versionId) 273 | .path("sample-input") 274 | .request(MediaType.APPLICATION_JSON); 275 | builder.header("Authorization", "ApiKey "+this.apiKey); 276 | try { 277 | logger.info("getModelVersion("+modelId+","+versionId+") :: Ready to call modzy api"); 278 | return builder.get(String.class); 279 | } 280 | catch(ResponseProcessingException rpe) { 281 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 282 | throw new ApiException(rpe); 283 | } 284 | catch(ProcessingException pr) { 285 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 286 | throw new ApiException(pr); 287 | } 288 | catch(WebApplicationException wae) { 289 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 290 | throw new ApiException(wae); 291 | } 292 | } 293 | 294 | /** 295 | * Call the Modzy API Service that return the sample output for a model version 296 | * @param modelId a valid model id 297 | * @param versionId a valid version id 298 | * @return a json string instance with the information 299 | * @throws ApiException if there is something wrong with the service or the call 300 | */ 301 | public String getModelVersionOutputSample(String modelId, String versionId) throws ApiException{ 302 | Builder builder = this.restTarget.path(modelId) 303 | .path("versions").path(versionId) 304 | .path("sample-output") 305 | .request(MediaType.APPLICATION_JSON); 306 | builder.header("Authorization", "ApiKey "+this.apiKey); 307 | try { 308 | logger.info("getModelVersion("+modelId+","+versionId+") :: Ready to call modzy api"); 309 | return builder.get(String.class); 310 | } 311 | catch(ResponseProcessingException rpe) { 312 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 313 | throw new ApiException(rpe); 314 | } 315 | catch(ProcessingException pr) { 316 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 317 | throw new ApiException(pr); 318 | } 319 | catch(WebApplicationException wae) { 320 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 321 | throw new ApiException(wae); 322 | } 323 | } 324 | 325 | } 326 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/ResultClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import java.util.logging.Level; 4 | import java.util.logging.Logger; 5 | 6 | import javax.ws.rs.ProcessingException; 7 | import javax.ws.rs.WebApplicationException; 8 | import javax.ws.rs.client.Invocation.Builder; 9 | import javax.ws.rs.client.ResponseProcessingException; 10 | import javax.ws.rs.client.WebTarget; 11 | import javax.ws.rs.core.MediaType; 12 | 13 | import com.fasterxml.jackson.databind.JsonNode; 14 | import com.modzy.sdk.exception.ApiException; 15 | import com.modzy.sdk.model.Job; 16 | import com.modzy.sdk.model.JobOutput; 17 | import com.modzy.sdk.model.JobOutputJSON; 18 | import com.modzy.sdk.util.LoggerFactory; 19 | 20 | /** 21 | * 22 | * Client of the Result API Services 23 | * 24 | */ 25 | public class ResultClient { 26 | 27 | private static final String REST_PATH = "results"; 28 | 29 | private WebTarget restTarget; 30 | 31 | private String apiKey; 32 | 33 | private Logger logger; 34 | 35 | public ResultClient(WebTarget baseTarget, String apiKey) { 36 | super(); 37 | this.logger = LoggerFactory.getLogger(this); 38 | this.restTarget = baseTarget.path(ResultClient.REST_PATH); 39 | this.apiKey = apiKey; 40 | } 41 | 42 | /** 43 | * 44 | * Get the result object of the job on the result format provided 45 | * 46 | * @param Subclass of JobOutput in which the result will be formatted 47 | * @param jobId The job identifier which results we want to get 48 | * @param outputClass Subclass of JobOutput in which the result will be formatted 49 | * @return the job result {@link JobOutput} 50 | * @throws ApiException if there is something wrong with the service or the call of is the job is on submitted state 51 | */ 52 | public > T getResult(String jobId, Class outputClass) throws ApiException{ 53 | Builder builder = this.restTarget.path(jobId).request(MediaType.APPLICATION_JSON); 54 | builder.header("Authorization", "ApiKey "+this.apiKey); 55 | try { 56 | logger.info("querying job results "+jobId); 57 | return builder.get(outputClass);//TODO: By now is just JSON 58 | } 59 | catch(ResponseProcessingException rpe) { 60 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 61 | throw new ApiException(rpe); 62 | } 63 | catch(ProcessingException pr) { 64 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 65 | throw new ApiException(pr); 66 | } 67 | catch(WebApplicationException wae) { 68 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 69 | throw new ApiException(wae); 70 | } 71 | } 72 | 73 | /** 74 | * 75 | * Get the result object of the job on the result format provided 76 | * 77 | * @param Subclass of JobOutput in which the result will be formatted 78 | * @param job the job which reuslt we want to get 79 | * @param outputClass Subclass of JobOutput in which the result will be formatted 80 | * @return the job result {@link JobOutput} 81 | * @throws ApiException if there is something wrong with the service or the call of is the job is on submitted state 82 | */ 83 | public > T getResult(Job job, Class outputClass) throws ApiException{ 84 | return this.getResult(job.getJobIdentifier(), outputClass); 85 | } 86 | 87 | /** 88 | * 89 | * Get the result of the job in the default format (JSON) 90 | * 91 | * @param jobId The job identifier which results we want to get 92 | * @return the job result {@link JobOutput} 93 | * @throws ApiException if there is something wrong with the service or the call of is the job is on submitted state 94 | */ 95 | public JobOutput getResult(String jobId) throws ApiException{ 96 | return this.getResult(jobId, JobOutputJSON.class); 97 | } 98 | 99 | /** 100 | * 101 | * Get the result of the job in the default format (JSON) 102 | * 103 | * @param job The job which results we want to get 104 | * @return the job result {@link JobOutput} 105 | * @throws ApiException if there is something wrong with the service or the call of is the job is on submitted state 106 | */ 107 | public JobOutput getResult(Job job) throws ApiException{ 108 | return this.getResult(job.getJobIdentifier(), JobOutputJSON.class); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/TagClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import java.util.List; 4 | import java.util.logging.Level; 5 | import java.util.logging.Logger; 6 | 7 | import javax.ws.rs.ProcessingException; 8 | import javax.ws.rs.WebApplicationException; 9 | import javax.ws.rs.client.Invocation.Builder; 10 | import javax.ws.rs.client.ResponseProcessingException; 11 | import javax.ws.rs.client.WebTarget; 12 | import javax.ws.rs.core.GenericType; 13 | import javax.ws.rs.core.MediaType; 14 | 15 | import com.modzy.sdk.dto.TagWrapper; 16 | import com.modzy.sdk.exception.ApiException; 17 | import com.modzy.sdk.model.Tag; 18 | import com.modzy.sdk.util.LoggerFactory; 19 | 20 | /** 21 | * 22 | * Client of the Tag API Services 23 | * 24 | */ 25 | public class TagClient { 26 | 27 | private static final String REST_PATH = "models/tags"; 28 | 29 | private WebTarget restTarget; 30 | 31 | private String apiKey; 32 | 33 | private Logger logger; 34 | 35 | public TagClient(WebTarget baseTarget, String apiKey) { 36 | super(); 37 | this.logger = LoggerFactory.getLogger(this); 38 | this.restTarget = baseTarget.path(TagClient.REST_PATH); 39 | this.apiKey = apiKey; 40 | } 41 | 42 | /** 43 | * Wrapper of the GenericType necesary for process the response of the API 44 | * 45 | * @return A GenericType object for parse a list of Tag instances 46 | */ 47 | private GenericType> getListType(){ 48 | return new GenericType>() {}; 49 | } 50 | 51 | /** 52 | * 53 | * Call the Modzy service that returns all the tags 54 | * 55 | * @return A list of all the Modzy tags 56 | * @throws ApiException if there is something wrong with the service or the call 57 | */ 58 | public List getAllTags() throws ApiException { 59 | Builder builder = this.restTarget.request(MediaType.APPLICATION_JSON); 60 | builder.header("Authorization", "ApiKey "+this.apiKey); 61 | try { 62 | logger.info("Ready to call modzy api"); 63 | return builder.get(this.getListType()); 64 | } 65 | catch(ResponseProcessingException rpe) { 66 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 67 | throw new ApiException(rpe); 68 | } 69 | catch(ProcessingException pr) { 70 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 71 | throw new ApiException(pr); 72 | } 73 | catch(WebApplicationException wae) { 74 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 75 | throw new ApiException(wae); 76 | } 77 | } 78 | 79 | /** 80 | * 81 | * Call the Modzy API Service that return a tag Wrapper with the list of Tag and Model instances 82 | * 83 | * @param tagsId identifier(s) of the tag(s) 84 | * @return A TagWrapper instance if the tagsId is valid 85 | * @throws ApiException if there is something wrong with the service or the call 86 | */ 87 | public TagWrapper getTagsAndModels(String ...tagsId) throws ApiException{ 88 | Builder builder = this.restTarget.path(String.join(",", tagsId)).request(MediaType.APPLICATION_JSON); 89 | builder.header("Authorization", "ApiKey "+this.apiKey); 90 | try { 91 | return builder.get(TagWrapper.class); 92 | } 93 | catch(ResponseProcessingException rpe) { 94 | this.logger.log(Level.SEVERE, rpe.getMessage(), rpe); 95 | throw new ApiException(rpe); 96 | } 97 | catch(ProcessingException pr) { 98 | this.logger.log(Level.SEVERE, pr.getMessage(), pr); 99 | throw new ApiException(pr); 100 | } 101 | catch(WebApplicationException wae) { 102 | this.logger.log(Level.SEVERE, wae.getMessage(), wae); 103 | throw new ApiException(wae); 104 | } 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/EmbeddedData.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 4 | import com.modzy.sdk.util.EmbeddedSerializer; 5 | import lombok.Data; 6 | 7 | @Data 8 | @JsonSerialize(using = EmbeddedSerializer.class) 9 | public class EmbeddedData { 10 | 11 | String mediaType; 12 | 13 | String encoding; 14 | 15 | byte[] data; 16 | 17 | public EmbeddedData() { 18 | super(); 19 | this.mediaType = "text/plain"; 20 | this.encoding = "charset=US-ASCII"; 21 | this.data = null; 22 | } 23 | 24 | public EmbeddedData(byte[] data) { 25 | super(); 26 | this.mediaType = "application/octet-stream"; 27 | this.encoding = "base64"; 28 | this.data = data; 29 | } 30 | 31 | public EmbeddedData(String mediaType, byte[] data) { 32 | super(); 33 | this.mediaType = mediaType; 34 | this.encoding = "base64"; 35 | this.data = data; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/JobHistoryResponseWrapper.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import java.util.List; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 6 | import com.modzy.sdk.model.Job; 7 | import lombok.Data; 8 | 9 | @Data 10 | @JsonIgnoreProperties(ignoreUnknown=true) 11 | public class JobHistoryResponseWrapper { 12 | 13 | private List data; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/JobHistorySearchParams.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import java.util.Date; 4 | 5 | import com.fasterxml.jackson.annotation.JsonFormat; 6 | import com.fasterxml.jackson.annotation.JsonIgnore; 7 | import com.fasterxml.jackson.annotation.JsonInclude; 8 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 9 | import com.modzy.sdk.model.JobStatus; 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @JsonInclude(Include.NON_EMPTY) 18 | public class JobHistorySearchParams extends Pagination{ 19 | 20 | private String user; 21 | 22 | private String accessKey; 23 | 24 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") 25 | private Date startDate; 26 | 27 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") 28 | private Date endDate; 29 | 30 | private String model; 31 | 32 | private JobHistorySearchStatus status = JobHistorySearchStatus.ALL; 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/JobHistorySearchStatus.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | public enum JobHistorySearchStatus { 4 | ALL, 5 | PENDING, 6 | TERMINATED 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/ModelSearchParams.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.util.Date; 11 | 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 16 | public class ModelSearchParams extends Pagination{ 17 | 18 | protected String modelId; 19 | 20 | protected String author; 21 | 22 | protected String createdByEmail; 23 | 24 | protected String name; 25 | 26 | protected String description; 27 | 28 | @JsonProperty("isActive") 29 | protected Boolean active; 30 | 31 | @JsonProperty("isExpired") 32 | protected Boolean expired; 33 | 34 | @JsonProperty("isRecommended") 35 | protected Boolean recommended; 36 | 37 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") 38 | protected Date lastActiveDateTime; 39 | 40 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") 41 | protected Date expirationDateTime; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/Pagination.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 13 | public class Pagination { 14 | 15 | protected Integer page; 16 | 17 | @JsonProperty("per-page") 18 | protected Integer perPage = 1000; 19 | 20 | @JsonProperty("sort-by") 21 | protected String sortBy; 22 | 23 | protected String direction; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/S3FileRef.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class S3FileRef { 11 | 12 | private String bucket; 13 | 14 | private String key; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/dto/TagWrapper.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.dto; 2 | 3 | import java.util.List; 4 | 5 | import com.modzy.sdk.model.Model; 6 | import com.modzy.sdk.model.Tag; 7 | import lombok.Data; 8 | 9 | @Data 10 | public class TagWrapper { 11 | 12 | private List tags; 13 | 14 | private List models; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/exception/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.exception; 2 | 3 | public class ApiException extends Exception{ 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 8483284489941313684L; 9 | 10 | public ApiException() { 11 | super(); 12 | } 13 | 14 | public ApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 15 | super(message, cause, enableSuppression, writableStackTrace); 16 | } 17 | 18 | public ApiException(String message, Throwable cause) { 19 | super(message, cause); 20 | } 21 | 22 | public ApiException(String message) { 23 | super(message); 24 | } 25 | 26 | public ApiException(Throwable cause) { 27 | super(cause); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return super.toString(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/filter/LoggingFilter.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.filter; 2 | 3 | import java.io.IOException; 4 | import java.util.logging.Logger; 5 | 6 | import javax.ws.rs.client.ClientRequestContext; 7 | import javax.ws.rs.client.ClientRequestFilter; 8 | import javax.ws.rs.client.ClientResponseContext; 9 | import javax.ws.rs.client.ClientResponseFilter; 10 | 11 | import com.fasterxml.jackson.databind.ObjectMapper; 12 | import com.modzy.sdk.util.LoggerFactory; 13 | 14 | public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter { 15 | 16 | private Logger logger; 17 | private ObjectMapper objectMapper; 18 | 19 | public LoggingFilter() { 20 | super(); 21 | this.logger = LoggerFactory.getLogger(this); 22 | this.objectMapper = new ObjectMapper(); 23 | } 24 | 25 | public void filter(ClientRequestContext requestContext) throws IOException { 26 | if( requestContext.hasEntity() ) { 27 | this.logger.info(this.objectMapper/*.writerWithDefaultPrettyPrinter()*/.writeValueAsString(requestContext.getEntity())); 28 | } 29 | } 30 | 31 | public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { 32 | this.logger.info(responseContext.toString()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/ContainerImage.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | 6 | @Data 7 | @JsonIgnoreProperties(ignoreUnknown=true) 8 | public class ContainerImage { 9 | 10 | private String uploadStatus; 11 | 12 | private String loadStatus; 13 | 14 | private Integer uploadPercentage; 15 | 16 | private Integer loadPercentage; 17 | 18 | private Long containerImageSize; 19 | 20 | private String registryHost; 21 | 22 | private String repositoryNamespace; 23 | 24 | private String imagePrefix; 25 | 26 | private String repositoryName; 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Feature.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | 6 | @Data 7 | @JsonIgnoreProperties(ignoreUnknown=true) 8 | public class Feature { 9 | 10 | private String identifier; 11 | 12 | private String name; 13 | 14 | private String description; 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Image.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | 6 | @Data 7 | @JsonIgnoreProperties(ignoreUnknown=true) 8 | public class Image { 9 | 10 | private String url; 11 | 12 | private String caption; 13 | 14 | private String alt; 15 | 16 | private String relationType; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Job.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.util.Date; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 8 | import lombok.Data; 9 | import lombok.ToString; 10 | 11 | @Data 12 | @JsonInclude(Include.NON_EMPTY) 13 | @JsonIgnoreProperties(ignoreUnknown=true) 14 | @ToString(onlyExplicitlyIncluded = true) 15 | public class Job { 16 | 17 | @ToString.Include 18 | private String jobIdentifier; 19 | 20 | private String submittedBy; 21 | 22 | @ToString.Include 23 | private Model model; 24 | 25 | @ToString.Include 26 | private JobStatus status; 27 | 28 | @ToString.Include 29 | private JobInput input; 30 | 31 | private Date createdAt; 32 | 33 | private Date updatedAt; 34 | 35 | private Date submittedAt; 36 | 37 | private Integer total; 38 | 39 | private Integer completed; 40 | 41 | private Integer failed; 42 | 43 | private Long elapsedTime; 44 | 45 | public Job() { 46 | super(); 47 | } 48 | 49 | public Job(Model model) { 50 | this(); 51 | this.model = new Model(); 52 | this.model.setIdentifier(model.getIdentifier()); 53 | this.model.setName(model.getName()); 54 | this.model.setVersion(model.getVersion()); 55 | } 56 | 57 | public Job(Model model, ModelVersion modelVersion) { 58 | this(model); 59 | this.model.setVersion( modelVersion.getVersion() ); 60 | } 61 | 62 | public Job(Model model, ModelVersion modelVersion, JobInput input) { 63 | this(model, modelVersion); 64 | this.input = input; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInput.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.List; 6 | 7 | import com.fasterxml.jackson.annotation.JsonIgnore; 8 | import com.fasterxml.jackson.annotation.JsonSubTypes; 9 | import com.fasterxml.jackson.annotation.JsonSubTypes.Type; 10 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 11 | import lombok.Data; 12 | import lombok.ToString; 13 | 14 | @JsonTypeInfo( 15 | use = JsonTypeInfo.Id.NAME, 16 | include = JsonTypeInfo.As.PROPERTY, 17 | property = "type") 18 | @JsonSubTypes({ 19 | @Type(value = JobInputText.class, name = "text"), 20 | @Type(value = JobInputS3.class, name = "aws-s3"), 21 | @Type(value = JobInputEmbedded.class, name = "embedded"), 22 | @Type(value = JobInputJDBC.class, name = "jdbc"), 23 | }) 24 | /** 25 | * 26 | * This class is an input wrapper for the jobs services, it allows to add 27 | * input params for n calls 28 | * 29 | * @author Raul Casallas 30 | * 31 | * @param 32 | */ 33 | @Data 34 | @ToString 35 | public class JobInput { 36 | 37 | protected Map> sources = new HashMap>(); 38 | 39 | @JsonIgnore 40 | protected ModelVersion modelVersion; 41 | 42 | public JobInput() { 43 | super(); 44 | } 45 | 46 | public JobInput(ModelVersion modelVersion) { 47 | this.modelVersion = modelVersion; 48 | } 49 | 50 | /** 51 | * 52 | * Add a combination of inputs by searching the source input names, this method requires 53 | * that the {@link JobInput#modelVersion modelVersion} attribute was setted before in order 54 | * to find the keys to the map and use {@link JobInput#addSource(String, Map) addSource} 55 | * method to finally add the source map to the input. 56 | * 57 | * @param sourceName Name of the input, if its null it will be generated 58 | * @param sources Sequence if source inputs according to the model version specification 59 | */ 60 | public void addSourceByName(String sourceName, List sources) { 61 | if( sources == null ) { 62 | return; 63 | } 64 | if( this.modelVersion == null ) { 65 | throw new UnsupportedOperationException("This "+this.getClass().getSimpleName()+" instance should be intializated with the model version"); 66 | } 67 | if( sources.size() != this.modelVersion.getInputs().size() ) { 68 | throw new IllegalArgumentException("The number of sources provided "+sources.size()+" doesn't match the model input size of "+this.modelVersion.getInputs().size() ); 69 | } 70 | Map sourceMap = new HashMap(); 71 | for( int i = 0; i < sources.size(); i++ ){ 72 | sourceMap.put(this.modelVersion.getInputs().get(i).getName(), sources.get(i)); 73 | } 74 | this.addSource(sourceName, sourceMap); 75 | } 76 | 77 | /** 78 | * 79 | * Add a combination of inputs by searching the source input names, this method is a 80 | * convenience shortcut to {@link JobInput#addSourceByName(String, Object...) addSource(sourceName, sources)} 81 | * method 82 | * 83 | * @param sources Sequence if source inputs according to the model version specification 84 | */ 85 | public void addSource(List sources) { 86 | this.addSourceByName(null, sources); 87 | } 88 | 89 | /** 90 | * 91 | * Add a source map (combination of inputs) to this input, referenced by the sourceName key, 92 | * the key names should be settled according the specific model version input names. 93 | * 94 | * This method is not thread safe, so you should add sources in order. 95 | * 96 | * @param sourceName Name of the input, if its null it will be generated 97 | * @param sourceMap input map with keys according the model version input names 98 | */ 99 | public void addSource(String sourceName, Map sourceMap) { 100 | sourceName = sourceName != null ? sourceName : "input-"+(this.sources.size()+1); 101 | this.sources.put(sourceName, sourceMap); 102 | } 103 | 104 | /** 105 | * 106 | * Add a source map (combination of inputs) to this input, this method is a 107 | * convenience shortcut to {@link JobInput#addSource(String, Map) addSource} 108 | * 109 | * @param sourceMap input map with keys according the model version input names 110 | */ 111 | public void addSource(Map sourceMap) { 112 | this.addSource(null, sourceMap); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInputEmbedded.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.modzy.sdk.dto.EmbeddedData; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class JobInputEmbedded extends JobInput{ 8 | 9 | public JobInputEmbedded() { 10 | super(); 11 | } 12 | 13 | public JobInputEmbedded(ModelVersion modelVersion) { 14 | super(modelVersion); 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInputJDBC.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class JobInputJDBC extends JobInput{ 11 | 12 | private String url; 13 | 14 | private String username; 15 | 16 | private String password; 17 | 18 | private String driver; 19 | 20 | private String query; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInputS3.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.modzy.sdk.dto.S3FileRef; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class JobInputS3 extends JobInput{ 8 | 9 | private String accessKeyID; 10 | 11 | private String secretAccessKey; 12 | 13 | private String region; 14 | 15 | public JobInputS3() { 16 | super(); 17 | } 18 | 19 | public JobInputS3(ModelVersion modelVersion) { 20 | super(modelVersion); 21 | } 22 | 23 | public JobInputS3(ModelVersion modelVersion, String accessKeyID, String secretAccessKey, String region) { 24 | super(modelVersion); 25 | this.accessKeyID = accessKeyID; 26 | this.secretAccessKey = secretAccessKey; 27 | this.region = region; 28 | } 29 | 30 | public JobInputS3(String accessKeyID, String secretAccessKey, String region) { 31 | super(); 32 | this.accessKeyID = accessKeyID; 33 | this.secretAccessKey = secretAccessKey; 34 | this.region = region; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInputStream.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.io.InputStream; 4 | 5 | public class JobInputStream extends JobInput{ 6 | 7 | public JobInputStream() { 8 | super(); 9 | } 10 | 11 | public JobInputStream(ModelVersion modelVersion) { 12 | super(modelVersion); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobInputText.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class JobInputText extends JobInput{ 7 | 8 | public JobInputText() { 9 | super(); 10 | } 11 | 12 | public JobInputText(ModelVersion modelVersion) { 13 | super(modelVersion); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobOutput.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | 7 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 8 | import com.fasterxml.jackson.databind.JsonNode; 9 | import lombok.Data; 10 | 11 | @Data 12 | @JsonIgnoreProperties(ignoreUnknown=true) 13 | public class JobOutput { 14 | 15 | private String jobIdentifier; 16 | 17 | protected Map results; 18 | 19 | protected Map failures; 20 | 21 | private Integer total; 22 | 23 | private Integer completed; 24 | 25 | private Integer failed; 26 | 27 | private Boolean finished; 28 | 29 | private String submittedByKey; 30 | 31 | private String accountIdentifier; 32 | 33 | private Team team; 34 | 35 | private Boolean explained; 36 | 37 | /** 38 | * Getter of the results with a fix to avoid the double nesting 39 | * 40 | * @return A result map with the double nesting fixed 41 | */ 42 | public Map> getResults() { 43 | Map> realResult = new HashMap>(); 44 | Map mapResult; 45 | JsonNode nodeResult; 46 | Iterator> nrIterator; 47 | Map.Entry nEntry; 48 | for( String resultKey : this.results.keySet() ) { 49 | mapResult = new HashMap(); 50 | nodeResult = this.results.get(resultKey); 51 | nrIterator = nodeResult.fields(); 52 | while(nrIterator.hasNext()) { 53 | nEntry = nrIterator.next(); 54 | if( nEntry.getKey().contains(".") ) { 55 | mapResult.put(nEntry.getKey(), (T)nEntry.getValue() ); 56 | } 57 | } 58 | realResult.put(resultKey, mapResult); 59 | } 60 | return realResult; 61 | } 62 | 63 | public Map getFailures() { 64 | Map realFailures = new HashMap(); 65 | JsonNode nodeResult; 66 | for( String resultKey : this.failures.keySet() ) { 67 | nodeResult = this.failures.get(resultKey).get("error"); 68 | realFailures.put(resultKey, nodeResult != null ? nodeResult.asText() : "Undefined error" ); 69 | } 70 | return realFailures; 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobOutputJSON.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class JobOutputJSON extends JobOutput{ 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/JobStatus.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | public enum JobStatus { 4 | OPEN, 5 | SUBMITTED, 6 | IN_PROGRESS, 7 | COMPLETED, 8 | TIMEDOUT, 9 | CANCELED, 10 | ERROR, 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Model.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.annotation.JsonAlias; 7 | import com.fasterxml.jackson.annotation.JsonIgnore; 8 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 9 | import com.fasterxml.jackson.annotation.JsonInclude; 10 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 11 | import com.fasterxml.jackson.annotation.JsonProperty; 12 | import lombok.Data; 13 | import lombok.ToString; 14 | 15 | @Data 16 | @ToString(onlyExplicitlyIncluded = true) 17 | @JsonIgnoreProperties(ignoreUnknown=true) 18 | @JsonInclude(Include.NON_EMPTY) 19 | public class Model { 20 | 21 | @ToString.Include 22 | @JsonAlias("modelId") 23 | private String identifier; 24 | 25 | private String permalink; 26 | 27 | @ToString.Include 28 | private String name; 29 | 30 | @ToString.Include 31 | private String version; 32 | 33 | private String description; 34 | 35 | private String longDescription; 36 | 37 | private String author; 38 | 39 | @ToString.Include 40 | private List versions; 41 | 42 | private String latestActiveVersion; 43 | 44 | private Boolean isAvailable; 45 | 46 | private Boolean isRecommended; 47 | 48 | private String sourceType; 49 | 50 | private Boolean isExperimental; 51 | 52 | private List tags; 53 | 54 | private List features; 55 | 56 | private List images; 57 | 58 | private Date createdAt; 59 | 60 | private Date updatedAt; 61 | 62 | private String imagePrefix; 63 | 64 | private String repositoryName; 65 | 66 | private Date creationDateTime; 67 | 68 | private Date updateDateTime; 69 | 70 | private Boolean isActive; 71 | 72 | private String latestVersion; 73 | 74 | private Boolean isExpired; 75 | 76 | private Date lastActiveDateTime; 77 | 78 | private String createdByEmail; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/ModelInput.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | @Data 8 | @ToString(onlyExplicitlyIncluded = true) 9 | @JsonIgnoreProperties(ignoreUnknown=true) 10 | public class ModelInput { 11 | 12 | @ToString.Include 13 | private String name; 14 | 15 | @ToString.Include 16 | private String acceptedMediaTypes; 17 | 18 | private Long maximumSize; 19 | 20 | private String description; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/ModelOutput.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | @Data 8 | @ToString(onlyExplicitlyIncluded = true) 9 | @JsonIgnoreProperties(ignoreUnknown=true) 10 | public class ModelOutput { 11 | 12 | @ToString.Include 13 | private String name; 14 | 15 | @ToString.Include 16 | private String mediaType; 17 | 18 | private Long maximumSize; 19 | 20 | private String description; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/ModelTimeout.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | @Data 8 | @JsonIgnoreProperties(ignoreUnknown=true) 9 | public class ModelTimeout { 10 | 11 | private Integer status; 12 | 13 | private Integer run; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/ModelVersion.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | import lombok.Data; 9 | import lombok.ToString; 10 | 11 | @Data 12 | @ToString(onlyExplicitlyIncluded = true) 13 | @JsonIgnoreProperties(ignoreUnknown=true) 14 | public class ModelVersion implements Comparable{ 15 | 16 | @ToString.Include 17 | private String version; 18 | 19 | private Date createdAt; 20 | 21 | private Date updatedAt; 22 | 23 | private String inputValidationSchema; 24 | 25 | private String createdBy; 26 | 27 | @ToString.Include 28 | private ModelTimeout timeout; 29 | 30 | private Requirement requirement; 31 | 32 | private ContainerImage containerImage; 33 | 34 | @ToString.Include 35 | private List inputs; 36 | 37 | @ToString.Include 38 | private List outputs; 39 | 40 | private List statistics; 41 | 42 | @JsonProperty("isActive") 43 | private Boolean active; 44 | 45 | private String longDescription; 46 | 47 | private String technicalDetails; 48 | 49 | private String sampleInput; 50 | 51 | private String sampleOutput; 52 | 53 | @JsonProperty("isAvailable") 54 | private Boolean available; 55 | 56 | private String sourceType; 57 | 58 | private String versionHistory; 59 | 60 | private String performanceSummary; 61 | 62 | private String status; 63 | 64 | @Override 65 | public int compareTo(ModelVersion otherModelVersion) { 66 | return this.version.compareTo(otherModelVersion.version); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Requirement.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | 6 | @Data 7 | @JsonIgnoreProperties(ignoreUnknown=true) 8 | public class Requirement { 9 | 10 | private Integer gpuUnits; 11 | 12 | private String cpuAmount; 13 | 14 | private String memoryAmount; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Statistic.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | 6 | @Data 7 | @JsonIgnoreProperties(ignoreUnknown=true) 8 | public class Statistic { 9 | 10 | private String label; 11 | 12 | private String category; 13 | 14 | private String type; 15 | 16 | private String description; 17 | 18 | private Boolean highlight; 19 | 20 | private Integer order; 21 | 22 | private Object value; 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Tag.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | @Data 8 | @ToString(onlyExplicitlyIncluded = true) 9 | @JsonIgnoreProperties(ignoreUnknown=true) 10 | public class Tag { 11 | 12 | @ToString.Include 13 | private String identifier; 14 | 15 | @ToString.Include 16 | private String name; 17 | 18 | private String dataType; 19 | 20 | private Boolean isCategorical; 21 | 22 | private Boolean isUserCreated; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/model/Team.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.model; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class Team { 7 | 8 | private String identifier; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/samples/JobAwsInputSample.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.samples; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | 8 | import com.fasterxml.jackson.databind.JsonNode; 9 | import com.modzy.sdk.ModzyClient; 10 | import com.modzy.sdk.dto.S3FileRef; 11 | import com.modzy.sdk.exception.ApiException; 12 | 13 | import com.modzy.sdk.model.*; 14 | import io.github.cdimascio.dotenv.Dotenv; 15 | 16 | public class JobAwsInputSample { 17 | 18 | public static void main(String[] args) throws ApiException { 19 | 20 | // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. 21 | // You can config those params as is described in the readme file (as environment variables, or by using the .env file), 22 | // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). 23 | 24 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 25 | 26 | // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. 27 | // (ie: https://modzy.example.com/api). 28 | String baseURL = dotenv.get("MODZY_BASE_URL"); 29 | // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character and a private part 30 | // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). 31 | String apiKey = dotenv.get("MODZY_API_KEY"); 32 | 33 | // Client initialization 34 | // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments 35 | // for the following API calls. 36 | ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); 37 | 38 | // Create a Job with a aws input, wait, and retrieve results 39 | 40 | // Get the model object: 41 | // If you already know the model identifier (i.e.: you get from the URL of the model details page or the input sample), 42 | // you can skip this step, if you don't you can find the model identifier by using its name as follows: 43 | Model model = modzyClient.getModelByName("Facial Embedding"); 44 | // Or if you already know the model id and want to know more about the model, you can use this instead: 45 | // Model model = modzyClient.getModel("f7e252e26a"); 46 | // You can find more information about how to query the models on the ModelSamples.java file 47 | 48 | // The model identifier is under the identifier property. You can take a look at the other properties under Model class 49 | // Or just log the model identifier, and potencially the latest version 50 | System.out.println(String.format("The model identifier is %s and the latest version is %s", model.getIdentifier(), model.getLatestVersion())); 51 | 52 | // Get the model version object: 53 | // If you already know the model version and the input key(s) of the model version you can skip this step. Also, you can 54 | // use the following code block to know about the inputs keys, and skip the call on future job submissions. 55 | ModelVersion modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion() ); 56 | // The info stored in modelVersion provides insights about the amount of time that the model can spend processing, 57 | // the inputs, and output keys of the model. 58 | System.out.println(String.format("The model version is %s", modelVersion)); 59 | System.out.println(String.format(" timeouts: status %sms, run %sms ",modelVersion.getTimeout().getStatus(), modelVersion.getTimeout().getRun())); 60 | System.out.println(" inputs:"); 61 | for( ModelInput input : modelVersion.getInputs() ){ 62 | System.out.println( 63 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 64 | ); 65 | } 66 | System.out.println(" outputs:"); 67 | for( ModelOutput output : modelVersion.getOutputs() ){ 68 | System.out.println( 69 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 70 | ); 71 | } 72 | 73 | // Send the job: 74 | // Amazon Simple Storage Service (AWS S3) is an object storage service (more info: https://aws.amazon.com/s3/?nc1=h_ls), 75 | // it allows the storage of images, videos or any content as file. In order to use as input type, we will need that you 76 | // provide the following properties: 77 | // Access Key: replace on <> 78 | String ACCESS_KEY="<>"; 79 | // Secret Access Key: replace on <> 80 | String SECRET_ACCESS_KEY="<>"; 81 | // Default Region 82 | String REGION="<>"; 83 | // The Bucket Name: replace on <> 84 | String BUCKET_NAME="<>"; 85 | // The File Key: replace on <> (remember, this model needs an image as input) 86 | String FILE_KEY="<>"; 87 | 88 | // Build the job input 89 | JobInput jobInput = new JobInputS3(modelVersion, ACCESS_KEY, SECRET_ACCESS_KEY, REGION); 90 | Map mapSource = new HashMap<>(); 91 | mapSource.put("image", new S3FileRef(BUCKET_NAME, FILE_KEY)); 92 | jobInput.addSource("source-key", mapSource); 93 | // An inference job groups input data that you send to a model. You can send any amount of inputs to 94 | // process and you can identify and refer to a specific input by the key that you assign, for example we can add: 95 | mapSource = new HashMap<>(); 96 | mapSource.put("image", new S3FileRef(BUCKET_NAME, FILE_KEY)); 97 | jobInput.addSource("second-key", mapSource); 98 | // 99 | mapSource = new HashMap<>(); 100 | mapSource.put("image", new S3FileRef(BUCKET_NAME, FILE_KEY)); 101 | jobInput.addSource("another-key", mapSource); 102 | //If you send a wrong input key, the model fails to process the input. 103 | mapSource = new HashMap<>(); 104 | mapSource.put("a.wrong.key", new S3FileRef(BUCKET_NAME, FILE_KEY)); 105 | jobInput.addSource("wrong-key", mapSource); 106 | // If you send a correct input key, but a wrong AWS S3 value key, the model fails to process the input. 107 | mapSource = new HashMap<>(); 108 | mapSource.put("image", new S3FileRef(BUCKET_NAME, "wrong-aws-file-key.png")); 109 | jobInput.addSource("wrong-value", mapSource); 110 | 111 | // When you have all your inputs ready, you can use our helper method to submit the job as follows: 112 | Job job = modzyClient.submitJob(model, modelVersion, jobInput); 113 | // Modzy creates the job and queue for processing. The job object contains all the info that you need to keep track 114 | // of the process, the most important being the job_identifier and the job status. 115 | System.out.println(String.format("job: %s", job)); 116 | // The job moves to SUBMITTED, meaning that Modzy acknowledged the job and sent it to the queue to be processed. 117 | // We provide a helper method to hold until the job finishes processing. Its a good practice to set a max timeout 118 | // if you're doing a test (ie: 2*status+run). in any case, it will hold until the job 119 | // finishes and moves to COMPLETED, CANCELED, or TIMEOUT. 120 | job = modzyClient.blockUntilComplete(job, null); 121 | 122 | // Get the results: 123 | // Check the status of the job. Jobs may be canceled or can reach a timeout. 124 | if( JobStatus.COMPLETED.equals( job.getStatus() ) ){ 125 | // A completed job means that all the inputs were processed by the model. Check the results for each 126 | // input key provided in the source map to see the model output. 127 | JobOutput result = modzyClient.getResult(job); 128 | // The result object has some useful info: 129 | System.out.println( 130 | String.format("Result: finished: %s, total: %s, completed: %s, failed: %s", 131 | result.getFinished(), result.getTotal(), result.getCompleted(), result.getFailed() 132 | ) 133 | ); 134 | // Notice that we are iterating thought the same keys of the input sources 135 | for( String key : jobInput.getSources().keySet() ){ 136 | // The result object has the individual results of each job input. In this case the output key is called 137 | // results.json, so we can get that specific model result as follows: 138 | if( result.getResults().containsKey(key) ){ 139 | JsonNode modelResult = result.getResults().get(key).get("results.json"); 140 | // The output for this model comes in a JSON format, so we can directly log the model results: 141 | System.out.print(String.format(" %s: ", key)); 142 | Entry field; 143 | for (Iterator> it = modelResult.fields(); it.hasNext(); ) { 144 | field = it.next(); 145 | System.out.print( String.format(" %s: %s", field.getKey(), field.getValue().asText()) ); 146 | } 147 | System.out.println(); 148 | } 149 | else{ 150 | // If the model raises an error, we can get the specific error message: 151 | System.err.println(String.format(" %s: failure: %s", key, result.getFailures().get(key))); 152 | } 153 | } 154 | } 155 | else{ 156 | System.err.println(String.format("processing failed: %s", job)); 157 | } 158 | 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/samples/JobEmbeddedInputSample.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.samples; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | import java.util.Map.Entry; 9 | 10 | import com.modzy.sdk.dto.S3FileRef; 11 | import com.modzy.sdk.model.*; 12 | import org.apache.commons.io.IOUtils; 13 | 14 | import com.fasterxml.jackson.databind.JsonNode; 15 | import com.modzy.sdk.ModzyClient; 16 | import com.modzy.sdk.dto.EmbeddedData; 17 | import com.modzy.sdk.exception.ApiException; 18 | 19 | import io.github.cdimascio.dotenv.Dotenv; 20 | 21 | public class JobEmbeddedInputSample { 22 | 23 | public static void main(String[] args) throws ApiException, IOException { 24 | 25 | // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. 26 | // You can config those params as is described in the readme file (as environment variables, or by using the .env file), 27 | // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). 28 | 29 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 30 | 31 | // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. 32 | // (ie: https://modzy.example.com/api). 33 | String baseURL = dotenv.get("MODZY_BASE_URL"); 34 | // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character and a private part 35 | // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). 36 | String apiKey = dotenv.get("MODZY_API_KEY"); 37 | 38 | // Client initialization 39 | // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments 40 | // for the following API calls. 41 | ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); 42 | 43 | // Create a Job with a embedded input, wait, and retrieve results 44 | 45 | // Get the model object: 46 | // If you already know the model identifier (i.e.: you get from the URL of the model details page or the input sample), 47 | // you can skip this step, if you don't you can find the model identifier by using its name as follows: 48 | Model model = modzyClient.getModelByName("Multi-Language OCR"); 49 | // Or if you already know the model id and want to know more about the model, you can use this instead: 50 | // Model model = modzyClient.getModel("c60c8dbd79"); 51 | // You can find more information about how to query the models on the ModelSamples.java file 52 | 53 | // The model identifier is under the identifier property. You can take a look at the other properties under Model class 54 | // Or just log the model identifier, and potencially the latest version 55 | System.out.println(String.format("The model identifier is %s and the latest version is %s", model.getIdentifier(), model.getLatestVersion())); 56 | 57 | // Get the model version object: 58 | // If you already know the model version and the input key(s) of the model version you can skip this step. Also, you can 59 | // use the following code block to know about the inputs keys, and skip the call on future job submissions. 60 | ModelVersion modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion() ); 61 | // The info stored in modelVersion provides insights about the amount of time that the model can spend processing, 62 | // the inputs, and output keys of the model. 63 | System.out.println(String.format("The model version is %s", modelVersion)); 64 | System.out.println(String.format(" timeouts: status %sms, run %sms ",modelVersion.getTimeout().getStatus(), modelVersion.getTimeout().getRun())); 65 | System.out.println(" inputs:"); 66 | for( ModelInput input : modelVersion.getInputs() ){ 67 | System.out.println( 68 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 69 | ); 70 | } 71 | System.out.println(" outputs:"); 72 | for( ModelOutput output : modelVersion.getOutputs() ){ 73 | System.out.println( 74 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 75 | ); 76 | } 77 | 78 | // Send the job: 79 | // An embedded input is a byte array encoded as a string in Base64, that's very handy for small to middle size files, for 80 | // bigger files can be a memory issue because you need to load the file in memory (load + encode). 81 | 82 | byte[] imageBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/image.png") ); 83 | byte[] configBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/config.json") ); 84 | 85 | // With the info about the model (identifier), the model version (version string, input/output keys), you are ready to 86 | // submit the job. Just prepare the source object: 87 | JobInput jobInput = new JobInputEmbedded(modelVersion); 88 | Map mapSource = new HashMap<>(); 89 | mapSource.put("input", new EmbeddedData("image/png", imageBytes)); 90 | mapSource.put("config.json", new EmbeddedData("application/json", configBytes)); 91 | jobInput.addSource("source-key", mapSource); 92 | // An inference job groups input data that you send to a model. You can send any amount of inputs to 93 | // process and you can identify and refer to a specific input by the key that you assign, for example we can add: 94 | mapSource = new HashMap<>(); 95 | mapSource.put("input", new EmbeddedData("image/png", imageBytes)); 96 | mapSource.put("config.json", new EmbeddedData("application/json", configBytes)); 97 | jobInput.addSource("second-key", mapSource); 98 | // You don't need to load all the inputs from files, just convert to bytes as follows: 99 | configBytes = "{\"languages\": [\"spa\"]}".getBytes(); 100 | mapSource = new HashMap<>(); 101 | mapSource.put("input", new EmbeddedData("image/png", imageBytes)); 102 | mapSource.put("config.json", new EmbeddedData("application/json", configBytes)); 103 | jobInput.addSource("another-key", mapSource); 104 | //If you send a wrong input key, the model fails to process the input. 105 | mapSource = new HashMap<>(); 106 | mapSource.put("a.wrong.key", new EmbeddedData("image/png", imageBytes)); 107 | mapSource.put("config.json", new EmbeddedData("application/json", configBytes)); 108 | jobInput.addSource("wrong-key", mapSource); 109 | // If you send a correct input key, but some wrong values, the model fails to process the input. 110 | mapSource = new HashMap<>(); 111 | mapSource.put("input", new EmbeddedData("application/json", configBytes)); 112 | mapSource.put("config.json", new EmbeddedData("image/png", imageBytes)); 113 | jobInput.addSource("wrong-values", mapSource); 114 | 115 | // When you have all your inputs ready, you can use our helper method to submit the job as follows: 116 | Job job = modzyClient.submitJob(model, modelVersion, jobInput); 117 | // Modzy creates the job and queue for processing. The job object contains all the info that you need to keep track 118 | // of the process, the most important being the job_identifier and the job status. 119 | System.out.println(String.format("job: %s", job)); 120 | // The job moves to SUBMITTED, meaning that Modzy acknowledged the job and sent it to the queue to be processed. 121 | // We provide a helper method to hold until the job finishes processing. Its a good practice to set a max timeout 122 | // if you're doing a test (ie: 2*status+run). in any case, it will hold until the job 123 | // finishes and moves to COMPLETED, CANCELED, or TIMEOUT. 124 | job = modzyClient.blockUntilComplete(job, null); 125 | 126 | // Get the results: 127 | // Check the status of the job. Jobs may be canceled or can reach a timeout. 128 | if( JobStatus.COMPLETED.equals( job.getStatus() ) ){ 129 | // A completed job means that all the inputs were processed by the model. Check the results for each 130 | // input key provided in the source map to see the model output. 131 | JobOutput result = modzyClient.getResult(job); 132 | // The result object has some useful info: 133 | System.out.println( 134 | String.format("Result: finished: %s, total: %s, completed: %s, failed: %s", 135 | result.getFinished(), result.getTotal(), result.getCompleted(), result.getFailed() 136 | ) 137 | ); 138 | // Notice that we are iterating thought the same keys of the input sources 139 | for( String key : jobInput.getSources().keySet() ){ 140 | // The result object has the individual results of each job input. In this case the output key is called 141 | // results.json, so we can get that specific model result as follows: 142 | if( result.getResults().containsKey(key) ){ 143 | JsonNode modelResult = result.getResults().get(key).get("results.json"); 144 | // The output for this model comes in a JSON format, so we can directly log the model results: 145 | System.out.print(String.format(" %s: ", key)); 146 | Entry field; 147 | String textValue; 148 | for (Iterator> it = modelResult.fields(); it.hasNext(); ) { 149 | field = it.next(); 150 | textValue = field.getValue().asText().replace('\n', ' '); 151 | System.out.print( String.format(" %s: %s", field.getKey(), textValue) ); 152 | } 153 | System.out.println(); 154 | } 155 | else{ 156 | // If the model raises an error, we can get the specific error message: 157 | System.err.println(String.format(" %s: failure: %s", key, result.getFailures().get(key))); 158 | } 159 | } 160 | } 161 | else{ 162 | System.err.println(String.format("processing failed: %s", job)); 163 | } 164 | 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/samples/JobFileInputSample.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.samples; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.modzy.sdk.ModzyClient; 5 | import com.modzy.sdk.dto.EmbeddedData; 6 | import com.modzy.sdk.exception.ApiException; 7 | import com.modzy.sdk.model.Job; 8 | import com.modzy.sdk.model.JobInput; 9 | import com.modzy.sdk.model.JobInputStream; 10 | import com.modzy.sdk.model.JobOutput; 11 | import com.modzy.sdk.model.JobStatus; 12 | import com.modzy.sdk.model.Model; 13 | import com.modzy.sdk.model.ModelInput; 14 | import com.modzy.sdk.model.ModelOutput; 15 | import com.modzy.sdk.model.ModelVersion; 16 | import io.github.cdimascio.dotenv.Dotenv; 17 | import org.apache.commons.io.IOUtils; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.util.HashMap; 25 | import java.util.Iterator; 26 | import java.util.Map; 27 | 28 | public class JobFileInputSample { 29 | 30 | public static void main(String[] args) throws ApiException, IOException { 31 | 32 | // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. 33 | // You can config those params as is described in the readme file (as environment variables, or by using the .env file), 34 | // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). 35 | 36 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 37 | 38 | // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. 39 | // (ie: https://modzy.example.com/api). 40 | String baseURL = dotenv.get("MODZY_BASE_URL"); 41 | // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character, and a private part 42 | // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). 43 | String apiKey = dotenv.get("MODZY_API_KEY"); 44 | 45 | // Client initialization 46 | // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments 47 | // for the following API calls. 48 | ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); 49 | 50 | // Create a Job with a embedded input, wait, and retrieve results 51 | 52 | // Get the model object: 53 | // If you already know the model identifier (i.e.: you get from the URL of the model details page or the input sample), 54 | // you can skip this step, if you don't you can find the model identifier by using its name as follows: 55 | Model model = modzyClient.getModelByName("Multi-Language OCR"); 56 | // Or if you already know the model id and want to know more about the model, you can use this instead: 57 | // Model model = modzyClient.getModel("c60c8dbd79"); 58 | // You can find more information about how to query the models on the ModelSamples.java file 59 | 60 | // The model identifier is under the identifier property. You can take a look at the other properties under Model class 61 | // Or just log the model identifier, and potencially the latest version 62 | System.out.println(String.format("The model identifier is %s and the latest version is %s", model.getIdentifier(), model.getLatestVersion())); 63 | 64 | // Get the model version object: 65 | // If you already know the model version and the input key(s) of the model version you can skip this step. Also, you can 66 | // use the following code block to know about the inputs keys, and skip the call on future job submissions. 67 | ModelVersion modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion() ); 68 | // The info stored in modelVersion provides insights about the amount of time that the model can spend processing, 69 | // the inputs, and output keys of the model. 70 | System.out.println(String.format("The model version is %s", modelVersion)); 71 | System.out.println(String.format(" timeouts: status %sms, run %sms ",modelVersion.getTimeout().getStatus(), modelVersion.getTimeout().getRun())); 72 | System.out.println(" inputs:"); 73 | for( ModelInput input : modelVersion.getInputs() ){ 74 | System.out.println( 75 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 76 | ); 77 | } 78 | System.out.println(" outputs:"); 79 | for( ModelOutput output : modelVersion.getOutputs() ){ 80 | System.out.println( 81 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 82 | ); 83 | } 84 | 85 | // Send the job: 86 | // A file input will be submitted individually, so this method is best for large or multiple input files 87 | // You can use as a drop-in replacement instead of embedded inputs 88 | 89 | //byte[] imageBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/image.png") ); 90 | //byte[] configBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/config.json") ); 91 | 92 | String imagePath = "src/main/resources/samples/image.png"; 93 | String configPath = "src/main/resources/samples/config.json"; 94 | 95 | // With the info about the model (identifier), the model version (version string, input/output keys), you are ready to 96 | // submit the job. Just prepare the source object: 97 | JobInput jobInput = new JobInputStream(modelVersion); 98 | Map mapSource = new HashMap<>(); 99 | mapSource.put("input", new FileInputStream( imagePath )); 100 | mapSource.put("config.json", new FileInputStream( configPath ) ); 101 | jobInput.addSource("source-key", mapSource); 102 | // An inference job groups input data that you send to a model. You can send any amount of inputs to 103 | // process and you can identify and refer to a specific input by the key that you assign, for example we can add: 104 | mapSource = new HashMap<>(); 105 | mapSource.put("input", new FileInputStream( imagePath ) ); 106 | mapSource.put("config.json", new FileInputStream( configPath ) ); 107 | jobInput.addSource("second-key", mapSource); 108 | // You don't need to load all the inputs from files, just convert from bytes as follows: 109 | byte[] configBytes = "{\"languages\": [\"spa\"]}".getBytes(); 110 | mapSource = new HashMap<>(); 111 | mapSource.put("input", new FileInputStream( imagePath ) ); 112 | mapSource.put("config.json", new ByteArrayInputStream(configBytes)); 113 | jobInput.addSource("another-key", mapSource); 114 | //If you send a wrong input key, the model fails to process the input. 115 | mapSource = new HashMap<>(); 116 | mapSource.put("a.wrong.key", new FileInputStream( imagePath )); 117 | mapSource.put("config.json", new FileInputStream( configPath )); 118 | jobInput.addSource("wrong-key", mapSource); 119 | // If you send a correct input key, but some wrong values, the model fails to process the input. 120 | mapSource = new HashMap<>(); 121 | mapSource.put("input", new FileInputStream( configPath )); 122 | mapSource.put("config.json", new FileInputStream( imagePath )); 123 | jobInput.addSource("wrong-values", mapSource); 124 | 125 | // When you have all your inputs ready, you can use our helper method to submit the job as follows: 126 | Job job = modzyClient.submitJob(model, modelVersion, jobInput); 127 | // Modzy creates the job and queue for processing. The job object contains all the info that you need to keep track 128 | // of the process, the most important being the job_identifier and the job status. 129 | System.out.println(String.format("job: %s", job)); 130 | // The job moves to SUBMITTED, meaning that Modzy acknowledged the job and sent it to the queue to be processed. 131 | // We provide a helper method to hold until the job finishes processing. Its a good practice to set a max timeout 132 | // if you're doing a test (ie: 2*status+run). in any case, it will hold until the job 133 | // finishes and moves to COMPLETED, CANCELED, or TIMEOUT. 134 | job = modzyClient.blockUntilComplete(job, null); 135 | 136 | // Get the results: 137 | // Check the status of the job. Jobs may be canceled or can reach a timeout. 138 | if( JobStatus.COMPLETED.equals( job.getStatus() ) ){ 139 | // A completed job means that all the inputs were processed by the model. Check the results for each 140 | // input key provided in the source map to see the model output. 141 | JobOutput result = modzyClient.getResult(job); 142 | // The result object has some useful info: 143 | System.out.println( 144 | String.format("Result: finished: %s, total: %s, completed: %s, failed: %s", 145 | result.getFinished(), result.getTotal(), result.getCompleted(), result.getFailed() 146 | ) 147 | ); 148 | // Notice that we are iterating thought the same keys of the input sources 149 | for( String key : jobInput.getSources().keySet() ){ 150 | // The result object has the individual results of each job input. In this case the output key is called 151 | // results.json, so we can get that specific model result as follows: 152 | if( result.getResults().containsKey(key) ){ 153 | JsonNode modelResult = result.getResults().get(key).get("results.json"); 154 | // The output for this model comes in a JSON format, so we can directly log the model results: 155 | System.out.print(String.format(" %s: ", key)); 156 | Map.Entry field; 157 | String textValue; 158 | for (Iterator> it = modelResult.fields(); it.hasNext(); ) { 159 | field = it.next(); 160 | textValue = field.getValue().asText().replace('\n', ' '); 161 | System.out.print( String.format(" %s: %s", field.getKey(), textValue) ); 162 | } 163 | System.out.println(); 164 | } 165 | else{ 166 | // If the model raises an error, we can get the specific error message: 167 | System.err.println(String.format(" %s: failure: %s", key, result.getFailures().get(key))); 168 | } 169 | } 170 | } 171 | else{ 172 | System.err.println(String.format("processing failed: %s", job)); 173 | } 174 | 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/samples/JobTextInputSample.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.samples; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | 8 | import com.fasterxml.jackson.databind.JsonNode; 9 | import com.modzy.sdk.ModzyClient; 10 | import com.modzy.sdk.exception.ApiException; 11 | 12 | import com.modzy.sdk.model.*; 13 | import io.github.cdimascio.dotenv.Dotenv; 14 | 15 | public class JobTextInputSample { 16 | 17 | public static void main(String[] args) throws ApiException { 18 | 19 | // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. 20 | // You can config those params as is described in the readme file (as environment variables, or by using the .env file), 21 | // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). 22 | 23 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 24 | 25 | // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. 26 | // (ie: https://modzy.example.com/api). 27 | String baseURL = dotenv.get("MODZY_BASE_URL"); 28 | // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character and a private part 29 | // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). 30 | String apiKey = dotenv.get("MODZY_API_KEY"); 31 | 32 | // Client initialization 33 | // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments 34 | // for the following API calls. 35 | ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); 36 | 37 | // Create a Job with a text input, wait, and retrieve results: 38 | 39 | // Get the model object: 40 | // If you already know the model identifier (i.e.: you get from the URL of the model details page or the input sample), 41 | // you can skip this step, if you don't you can find the model identifier by using its name as follows: 42 | Model model = modzyClient.getModelByName("Sentiment Analysis"); 43 | // Or if you already know the model id and want to know more about the model, you can use this instead: 44 | // Model model = modzyClient.getModel("ed542963de"); 45 | // You can find more information about how to query the models on the ModelSamples.java file 46 | 47 | // The model identifier is under the identifier property. You can take a look at the other properties under Model class 48 | // Or just log the model identifier, and potencially the latest version 49 | System.out.println(String.format("The model identifier is %s and the latest version is %s", model.getIdentifier(), model.getLatestVersion())); 50 | 51 | // Get the model version object: 52 | // If you already know the model version and the input key(s) of the model version you can skip this step. Also, you can 53 | // use the following code block to know about the inputs keys, and skip the call on future job submissions. 54 | ModelVersion modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion() ); 55 | // The info stored in modelVersion provides insights about the amount of time that the model can spend processing, 56 | // the inputs, and output keys of the model. 57 | System.out.println(String.format("The model version is %s", modelVersion)); 58 | System.out.println(String.format(" timeouts: status %sms, run %sms ",modelVersion.getTimeout().getStatus(), modelVersion.getTimeout().getRun())); 59 | System.out.println(" inputs:"); 60 | for( ModelInput input : modelVersion.getInputs() ){ 61 | System.out.println( 62 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 63 | ); 64 | } 65 | System.out.println(" outputs:"); 66 | for( ModelOutput output : modelVersion.getOutputs() ){ 67 | System.out.println( 68 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 69 | ); 70 | } 71 | 72 | // Send the job: 73 | // With the info about the model (identifier), the model version (version string, input/output keys), you are ready to 74 | // submit the job. Just prepare the source object: 75 | JobInput jobInput = new JobInputText(); 76 | Map mapSource = new HashMap<>(); 77 | mapSource.put("input.txt", "Modzy is great!"); 78 | jobInput.addSource("source-key", mapSource); 79 | // An inference job groups input data that you send to a model. You can send any amount of inputs to 80 | // process and you can identify and refer to a specific input by the key that you assign, for example we can add: 81 | mapSource = new HashMap<>(); 82 | mapSource.put("input.txt", "Sometimes I really hate ribs"); 83 | jobInput.addSource("second-key", mapSource); 84 | // 85 | mapSource = new HashMap<>(); 86 | mapSource.put("input.txt", "Born and raised in Pennsylvania, Swift moved to Nashville, Tennessee, at the age of 14 to pursue a career in country music"); 87 | jobInput.addSource("another-key", mapSource); 88 | //If you send a wrong input key, the model fails to process the input. 89 | mapSource = new HashMap<>(); 90 | mapSource.put("a.wrong.key", "This input is wrong!"); 91 | jobInput.addSource("wrong-key", mapSource); 92 | // When you have all your inputs ready, you can use our helper method to submit the job as follows: 93 | Job job = modzyClient.submitJob(model, modelVersion, jobInput); 94 | // Modzy creates the job and queue for processing. The job object contains all the info that you need to keep track 95 | // of the process, the most important being the job_identifier and the job status. 96 | System.out.println(String.format("job: %s", job)); 97 | // The job moves to SUBMITTED, meaning that Modzy acknowledged the job and sent it to the queue to be processed. 98 | // We provide a helper method to hold until the job finishes processing. Its a good practice to set a max timeout 99 | // if you're doing a test (ie: 2*status+run). in any case, it will hold until the job 100 | // finishes and moves to COMPLETED, CANCELED, or TIMEOUT. 101 | job = modzyClient.blockUntilComplete(job, null); 102 | 103 | // Get the results: 104 | // Check the status of the job. Jobs may be canceled or can reach a timeout. 105 | if( JobStatus.COMPLETED.equals( job.getStatus() ) ){ 106 | // A completed job means that all the inputs were processed by the model. Check the results for each 107 | // input key provided in the source map to see the model output. 108 | JobOutput result = modzyClient.getResult(job); 109 | // The result object has some useful info: 110 | System.out.println( 111 | String.format("Result: finished: %s, total: %s, completed: %s, failed: %s", 112 | result.getFinished(), result.getTotal(), result.getCompleted(), result.getFailed() 113 | ) 114 | ); 115 | // Notice that we are iterating thought the same keys of the input sources 116 | for( String key : jobInput.getSources().keySet() ){ 117 | // The result object has the individual results of each job input. In this case the output key is called 118 | // results.json, so we can get that specific model result as follows: 119 | if( result.getResults().containsKey(key) ){ 120 | JsonNode modelResult = result.getResults().get(key).get("results.json"); 121 | // The output for this model comes in a JSON format, so we can directly log the model results: 122 | System.out.print(String.format(" %s: ", key)); 123 | Entry field; 124 | for (Iterator> it = modelResult.fields(); it.hasNext(); ) { 125 | field = it.next(); 126 | System.out.print( String.format(" %s: %s", field.getKey(), field.getValue().asText()) ); 127 | } 128 | System.out.println(); 129 | } 130 | else{ 131 | // If the model raises an error, we can get the specific error message: 132 | System.err.println(String.format(" %s: failure: %s", key, result.getFailures().get(key))); 133 | } 134 | } 135 | } 136 | else{ 137 | System.err.println(String.format("processing failed: %s", job)); 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/samples/ModelSamples.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.samples; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import com.modzy.sdk.ModzyClient; 8 | import com.modzy.sdk.dto.ModelSearchParams; 9 | import com.modzy.sdk.exception.ApiException; 10 | import com.modzy.sdk.model.Model; 11 | import com.modzy.sdk.model.ModelInput; 12 | import com.modzy.sdk.model.ModelOutput; 13 | import com.modzy.sdk.model.ModelVersion; 14 | 15 | import io.github.cdimascio.dotenv.Dotenv; 16 | 17 | public class ModelSamples { 18 | 19 | public static void main(String[] args) throws ApiException { 20 | 21 | // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. 22 | // You can config those params as is described in the readme file (as environment variables, or by using the .env file), 23 | // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). 24 | 25 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 26 | 27 | // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. 28 | // (ie: https://modzy.example.com/api). 29 | String baseURL = dotenv.get("MODZY_BASE_URL"); 30 | // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character and a private part 31 | // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). 32 | String apiKey = dotenv.get("MODZY_API_KEY"); 33 | 34 | // Client initialization 35 | // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments 36 | // for the following API calls. 37 | ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); 38 | 39 | // Get all models 40 | // You can get the full list of models from Modzy by using getAllModels method, this call will return just the 41 | // identifier and the latest version of each model 42 | List models = modzyClient.getAllModels(); 43 | System.out.println(String.format("all models: %s", models.size())); 44 | // Also, you can do more interesting search by the get_models method: 45 | // Search by author 46 | ModelSearchParams searchParams = new ModelSearchParams(); 47 | searchParams.setAuthor("Open Source"); 48 | models = modzyClient.getModels(searchParams); 49 | System.out.println(String.format("Open source models: %s", models.size())); 50 | // Active models 51 | searchParams = new ModelSearchParams(); 52 | searchParams.setActive(true); 53 | models = modzyClient.getModels(searchParams); 54 | System.out.println(String.format("Active models: %s", models.size())); 55 | // Search by name (and limiting the results) 56 | searchParams = new ModelSearchParams(); 57 | searchParams.setName("Image"); 58 | searchParams.setPerPage(5); 59 | models = modzyClient.getModels(searchParams); 60 | System.out.println(String.format("Models with name start with 'Image': %s", models.size())); 61 | // Combined search 62 | searchParams = new ModelSearchParams(); 63 | searchParams.setName("Image"); 64 | searchParams.setAuthor("Open Source"); 65 | searchParams.setActive(true); 66 | models = modzyClient.getModels(searchParams); 67 | System.out.println(String.format("Active open source models which name starts with 'Image': %s", models.size())); 68 | // Get model details 69 | // the models route didn't return much info about the models, just modelId, latestVersion and versions: 70 | ModelVersion modelVersion; 71 | for( Model model : models ){ 72 | System.out.println(String.format(" %s", model)); 73 | // In order to get more info about the models you need to get the details by identifier 74 | model = modzyClient.getModel(model.getIdentifier()); 75 | // then you'll get all the details about the model 76 | System.out.println(String.format("Model details properties: %s", getNotNullProperties(model))); 77 | // In order to get information about the input/output keys and types you need to get the model version 78 | // details as follows: 79 | modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion()); 80 | // then you'll get all the details about the specific model version 81 | System.out.println(String.format("ModelVersion details properties: %s", getNotNullProperties(modelVersion))); 82 | // Probably the more interesting are the ones related with the inputs and outputs of the model 83 | System.out.println(" inputs:"); 84 | for( ModelInput input : modelVersion.getInputs() ){ 85 | System.out.println( 86 | String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) 87 | ); 88 | } 89 | System.out.println(" outputs:"); 90 | for( ModelOutput output : modelVersion.getOutputs() ){ 91 | System.out.println( 92 | String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) 93 | ); 94 | } 95 | } 96 | // Get model by name 97 | // If you aren't familiar with the models ids, you can find the model by name as follows 98 | Model model = modzyClient.getModelByName("Dataset Joining"); 99 | // the method will return the first coincidence and return the details 100 | System.out.println( 101 | String.format( 102 | "Dataset Joining: id:%s, author: %s, is_active: %s, description: %s", 103 | model.getIdentifier(), 104 | model.getAuthor(), 105 | model.getIsActive(), 106 | model.getDescription() 107 | ) 108 | ); 109 | // Finally, you can find the models related with this search 110 | models = modzyClient.getRelatedModels(model.getIdentifier()); 111 | System.out.println("Related models"); 112 | for( Model modelAux : models ){ 113 | System.out.println( 114 | String.format(" %s :: %s (%s)", modelAux.getIdentifier(), modelAux.getName(), modelAux.getAuthor()) 115 | ); 116 | } 117 | } 118 | 119 | private static List getNotNullProperties(Object object){ 120 | List notNullProperties = new ArrayList<>(); 121 | Class theClass = object.getClass(); 122 | Object value; 123 | for(Field field : theClass.getDeclaredFields()){ 124 | try { 125 | field.setAccessible(true); 126 | value = field.get(object); 127 | if( value != null ){ 128 | notNullProperties.add(field.getName()); 129 | } 130 | } catch (IllegalAccessException e) { 131 | 132 | } 133 | } 134 | return notNullProperties; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/util/DataSize.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.util; 2 | 3 | import java.text.DecimalFormat; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | /** 8 | * Helper class to convert size units that comes as string on the yaml file. 9 | * 10 | * @see Spring implementation 11 | */ 12 | public class DataSize { 13 | 14 | /** 15 | * The pattern for parsing. 16 | */ 17 | private static final Pattern PATTERN = Pattern.compile("^(\\d+(\\.\\d+)?)([a-zA-Z]{0,2})$"); 18 | 19 | private Long bytes; 20 | 21 | private String strSize; 22 | 23 | public DataSize(Long bytesSize){ 24 | this.setBytes(bytesSize); 25 | } 26 | 27 | public DataSize(String stringSize){ 28 | this.setBytes(stringSize); 29 | } 30 | 31 | public DataSize(Object objectSize){ 32 | this.setBytes(objectSize); 33 | } 34 | 35 | public void setBytes(Long bytesSize){ 36 | this.bytes = bytesSize; 37 | } 38 | 39 | public void setBytes(Number bytesSize){ 40 | this.bytes = bytesSize.longValue(); 41 | } 42 | 43 | public void setBytes(String stringSize){ 44 | Matcher matcher = DataSize.PATTERN.matcher(stringSize); 45 | if( matcher.matches() ){ 46 | DataUnit dataUnit = DataUnit.findValueOf(matcher.group(3)); 47 | this.bytes = (long)((double)dataUnit.size()*Double.parseDouble(matcher.group(1))); 48 | this.strSize = stringSize; 49 | } 50 | } 51 | 52 | public void setBytes(Object objectSize){ 53 | if( objectSize instanceof Number ){ 54 | this.setBytes((Number)objectSize); 55 | } 56 | else{ 57 | this.setBytes(String.valueOf(objectSize)); 58 | } 59 | } 60 | 61 | public Long getBytes(){ 62 | return this.bytes; 63 | } 64 | 65 | @Override 66 | public String toString(){ 67 | if(this.strSize != null){ 68 | return this.strSize; 69 | } 70 | Double size = null; 71 | DataUnit unit = null; 72 | if( this.bytes != null ) { 73 | for (DataUnit dataUnit : DataUnit.values()) { 74 | long div = this.bytes / dataUnit.size(); 75 | if (div > 0) { 76 | double div2 = (double)this.bytes / (double)dataUnit.size(); 77 | if (size == null || div2 < size) { 78 | size = div2; 79 | unit = dataUnit; 80 | } 81 | } 82 | } 83 | } 84 | DecimalFormat decimalFormat = new DecimalFormat("#.##"); 85 | return decimalFormat.format(size)+unit.suffix(); 86 | } 87 | 88 | } 89 | 90 | enum DataUnit{ 91 | 92 | /** 93 | * Bytes, represented by suffix {@code i}. 94 | */ 95 | BYTES("i", 1l), 96 | 97 | /** 98 | * Kilobytes, represented by suffix {@code K}. 99 | */ 100 | KILOBYTES("K", 1000l), 101 | 102 | /** 103 | * Megabytes, represented by suffix {@code M}. 104 | */ 105 | MEGABYTES("M", 1000l*1000l), 106 | 107 | /** 108 | * Gigabytes, represented by suffix {@code G}. 109 | */ 110 | GIGABYTES("G", 1000l*1000l*1000l), 111 | 112 | /** 113 | * Terabytes, represented by suffix {@code T}. 114 | */ 115 | TERABYTES("T", 1000l*1000l*1000l*1000l), 116 | 117 | /** 118 | * Kibibytes, represented by suffix {@code Ki}. 119 | */ 120 | KIBIBYTES("Ki", 1024l), 121 | 122 | /** 123 | * Mebibytes, represented by suffix {@code Mi}. 124 | */ 125 | MEBIBYTES("Mi", 1024l*1024l), 126 | 127 | /** 128 | * Gibibytes, represented by suffix {@code Gi}. 129 | */ 130 | GIBIBYTES("Gi", 1024l*1024l*1024l), 131 | 132 | /** 133 | * Tebibytes, represented by suffix {@code Ti}. 134 | */ 135 | TEBIBYTES("Ti", 1024l*1024l*1024l*1024l), 136 | 137 | /** 138 | * Kibibytes (non decimal Kilobytes), represented by suffix {@code KB}. 139 | */ 140 | KIBIBYTES_LEGACY("KB", 1024l), 141 | 142 | /** 143 | * Mebibytes (non decimal Megabytes), represented by suffix {@code MB}. 144 | */ 145 | MEBIBYTES_LEGACY("MB", 1024l*1024l), 146 | 147 | /** 148 | * Gibibytes (non decimal Gigabytes), represented by suffix {@code GB}. 149 | */ 150 | GIBIBYTES_LEGACY("GB", 1024l*1024l*1024l), 151 | 152 | /** 153 | * Tebibytes (non decimal Terabytes), represented by suffix {@code TB}. 154 | */ 155 | TEBIBYTES_LEGACY("TB", 1024l*1024l*1024l*1024l); 156 | 157 | private final String suffix; 158 | private final long size; 159 | 160 | DataUnit(String suffix, long size){ 161 | this.suffix = suffix; 162 | this.size = size; 163 | } 164 | 165 | String suffix(){return this.suffix;}; 166 | 167 | long size(){return this.size;} 168 | 169 | public static DataUnit findValueOf(String suffix){ 170 | for(DataUnit dataUnit : DataUnit.values() ){ 171 | if( dataUnit.suffix().compareToIgnoreCase(suffix) == 0 ){ 172 | return dataUnit; 173 | } 174 | } 175 | return null; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/util/EmbeddedSerializer.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.util; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.xml.bind.DatatypeConverter; 6 | 7 | import com.fasterxml.jackson.core.JsonGenerationException; 8 | import com.fasterxml.jackson.core.JsonGenerator; 9 | import com.fasterxml.jackson.databind.SerializerProvider; 10 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 11 | import com.modzy.sdk.dto.EmbeddedData; 12 | 13 | public class EmbeddedSerializer extends StdSerializer{ 14 | 15 | /** 16 | * 17 | */ 18 | private static final long serialVersionUID = 6281183029679558216L; 19 | 20 | public EmbeddedSerializer() { 21 | super(EmbeddedData.class); 22 | } 23 | 24 | @Override 25 | public void serialize(EmbeddedData value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { 26 | jgen.writeString("data:"+value.getMediaType()+";"+value.getEncoding()+","+DatatypeConverter.printBase64Binary(value.getData())); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.util; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | 9 | public class FileUtils { 10 | 11 | public static byte[] readFile( String path ) throws IOException { 12 | return IOUtils.toByteArray( new FileInputStream( new File(path) ) ); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/modzy/sdk/util/LoggerFactory.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.logging.Level; 6 | import java.util.logging.LogManager; 7 | import java.util.logging.Logger; 8 | 9 | public class LoggerFactory { 10 | 11 | static { 12 | InputStream is = LoggerFactory.class.getResourceAsStream("/logging.properties"); 13 | try { 14 | LogManager.getLogManager().readConfiguration(is); 15 | } 16 | catch(IOException ioe) { 17 | Logger.getAnonymousLogger().log(Level.WARNING, "Custom logging configuration not found, using jvm defaults ", ioe); 18 | } 19 | finally { 20 | try { 21 | is.close(); 22 | } 23 | catch( Throwable e ) { 24 | 25 | } 26 | } 27 | } 28 | 29 | public static Logger getLogger(Object myClass) { 30 | return Logger.getLogger(myClass.getClass().getCanonicalName()); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers= java.util.logging.ConsoleHandler 2 | 3 | java.util.logging.ConsoleHandler.level = WARNING 4 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 5 | java.util.logging.SimpleFormatter.format = [%1$tF %1$tT] [%4$-7s] [%2$s] %5$s %6$s %n -------------------------------------------------------------------------------- /src/main/resources/samples/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "languages": ["eng", "deu", "fra"] 3 | } -------------------------------------------------------------------------------- /src/main/resources/samples/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modzy/sdk-java/42f188a12e286cd470db9178a33c3ee2e9243def/src/main/resources/samples/image.png -------------------------------------------------------------------------------- /src/test/java/com/modzy/sdk/TestJobClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | import static org.junit.Assert.fail; 7 | 8 | import java.util.Calendar; 9 | import java.util.Date; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.logging.Logger; 14 | 15 | import javax.ws.rs.client.Client; 16 | import javax.ws.rs.client.ClientBuilder; 17 | import javax.ws.rs.client.WebTarget; 18 | 19 | import com.modzy.sdk.dto.JobHistorySearchStatus; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import com.modzy.sdk.dto.EmbeddedData; 24 | import com.modzy.sdk.dto.JobHistorySearchParams; 25 | import com.modzy.sdk.dto.S3FileRef; 26 | import com.modzy.sdk.exception.ApiException; 27 | import com.modzy.sdk.filter.LoggingFilter; 28 | import com.modzy.sdk.model.Job; 29 | import com.modzy.sdk.model.JobInput; 30 | import com.modzy.sdk.model.JobInputEmbedded; 31 | import com.modzy.sdk.model.JobInputS3; 32 | import com.modzy.sdk.model.JobInputText; 33 | import com.modzy.sdk.model.JobStatus; 34 | import com.modzy.sdk.model.Model; 35 | import com.modzy.sdk.model.ModelVersion; 36 | import com.modzy.sdk.util.LoggerFactory; 37 | import io.github.cdimascio.dotenv.Dotenv; 38 | 39 | public class TestJobClient { 40 | 41 | private ModelClient modelClient; 42 | private JobClient jobClient; 43 | private String apiKey; 44 | 45 | private Logger logger; 46 | 47 | @Before 48 | public void setUp() throws Exception { 49 | this.logger = LoggerFactory.getLogger(this); 50 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 51 | Client client = ClientBuilder.newClient().register(LoggingFilter.class); 52 | WebTarget baseTarget = client.target(dotenv.get("MODZY_BASE_URL")); 53 | this.apiKey = dotenv.get("MODZY_API_KEY"); 54 | this.modelClient = new ModelClient(baseTarget, this.apiKey); 55 | this.jobClient = new JobClient(baseTarget, dotenv.get("MODZY_API_KEY")); 56 | } 57 | 58 | @Test 59 | public void testSubmitJob(){ 60 | Model model = null; 61 | try { 62 | model = this.modelClient.getModel("ed542963de");//sentiment-analysis 63 | } catch (ApiException e) { 64 | fail(e.getMessage()); 65 | } 66 | assertNotNull(model); 67 | assertNotEquals(model.getVersions().size(), 0); 68 | ModelVersion modelVersion = null; 69 | try { 70 | modelVersion = this.modelClient.getModelVersion(model.getIdentifier(), model.getLatestVersion()); 71 | } catch (ApiException e) { 72 | fail(e.getMessage()); 73 | } 74 | assertNotNull(modelVersion); 75 | assertNotEquals(modelVersion.getInputs().size(), 0); 76 | assertNotEquals(modelVersion.getOutputs().size(), 0); 77 | // 78 | Map sourceMap = new HashMap(); 79 | sourceMap.put("input.txt", "Modzy is great!"); 80 | JobInput jobInput = new JobInputText(); 81 | jobInput.addSource(sourceMap); 82 | Job job = null; 83 | try { 84 | job = this.jobClient.submitJob(model, modelVersion, jobInput); 85 | this.logger.info( job.toString() ); 86 | } catch (ApiException e) { 87 | fail(e.getMessage()); 88 | } 89 | assertNotNull(job); 90 | this.logger.info(job.toString()); 91 | assertNotNull(job.getJobIdentifier()); 92 | assertNotNull(job.getStatus()); 93 | } 94 | 95 | @Test 96 | public void testGetJob() { 97 | Model model = null; 98 | try { 99 | model = this.modelClient.getModel("ed542963de");//sentiment-analysis 100 | } catch (ApiException e) { 101 | fail(e.getMessage()); 102 | } 103 | assertNotNull(model); 104 | assertNotEquals(model.getVersions(), 0); 105 | ModelVersion modelVersion = null; 106 | try { 107 | modelVersion = this.modelClient.getModelVersion(model.getIdentifier(), model.getLatestVersion()); 108 | } catch (ApiException e) { 109 | fail(e.getMessage()); 110 | } 111 | assertNotNull(modelVersion); 112 | assertNotEquals(modelVersion.getInputs(), 0); 113 | assertNotEquals(modelVersion.getOutputs(), 0); 114 | // 115 | Map sourceMap = new HashMap(); 116 | sourceMap.put("input.txt", "Modzy is great!"); 117 | JobInput jobInput = new JobInputText(); 118 | jobInput.addSource(sourceMap); 119 | Job job = null; 120 | try { 121 | job = this.jobClient.submitJob(model, modelVersion, jobInput); 122 | this.logger.info( job.toString() ); 123 | } catch (ApiException e) { 124 | fail(e.getMessage()); 125 | } 126 | assertNotNull(job); 127 | this.logger.info(job.toString()); 128 | assertNotNull(job.getJobIdentifier()); 129 | assertNotNull(job.getStatus()); 130 | try { 131 | Thread.sleep(5000l); 132 | } catch (InterruptedException e) { 133 | fail(e.getMessage()); 134 | } 135 | // 136 | Job job2 = null; 137 | try { 138 | job2 = this.jobClient.getJob(job); 139 | } catch (ApiException e) { 140 | fail(e.getMessage()); 141 | } 142 | assertNotNull(job2); 143 | assertNotNull(job2.getJobIdentifier()); 144 | this.logger.info( "Job after get call "+job2.toString() ); 145 | assertEquals(job.getJobIdentifier(), job2.getJobIdentifier()); 146 | } 147 | 148 | @Test 149 | public void testCancelJob() { 150 | Model model = null; 151 | try { 152 | model = this.modelClient.getModel("ed542963de");//sentiment-analysis 153 | } catch (ApiException e) { 154 | fail(e.getMessage()); 155 | } 156 | assertNotNull(model); 157 | assertNotEquals(model.getVersions(), 0); 158 | ModelVersion modelVersion = null; 159 | try { 160 | modelVersion = this.modelClient.getModelVersion(model.getIdentifier(), model.getLatestVersion()); 161 | } catch (ApiException e) { 162 | fail(e.getMessage()); 163 | } 164 | assertNotNull(modelVersion); 165 | assertNotEquals(modelVersion.getInputs(), 0); 166 | assertNotEquals(modelVersion.getOutputs(), 0); 167 | // 168 | Map sourceMap = new HashMap(); 169 | sourceMap.put("input.txt", "Modzy is great!"); 170 | JobInput jobInput = new JobInputText(); 171 | jobInput.addSource(sourceMap); 172 | Job job = null; 173 | try { 174 | job = this.jobClient.submitJob(model, modelVersion, jobInput); 175 | this.logger.info( job.toString() ); 176 | } catch (ApiException e) { 177 | fail(e.getMessage()); 178 | } 179 | assertNotNull(job); 180 | this.logger.info(job.toString()); 181 | assertNotNull(job.getJobIdentifier()); 182 | assertNotNull(job.getStatus()); 183 | // 184 | try { 185 | Thread.sleep(5000l); 186 | } catch (InterruptedException e) { 187 | fail(e.getMessage()); 188 | } 189 | // 190 | Job job2 = null; 191 | try { 192 | job2 = this.jobClient.getJob(job); 193 | } catch (ApiException e) { 194 | fail(e.getMessage()); 195 | } 196 | // 197 | if( JobStatus.COMPLETED != job2.getStatus() ){ 198 | Job job3 = null; 199 | try { 200 | job3 = this.jobClient.cancelJob(job); 201 | } catch (ApiException e) { 202 | fail(e.getMessage()); 203 | } 204 | assertNotNull(job3); 205 | assertNotNull(job3.getJobIdentifier()); 206 | this.logger.info("Job after cancel call "+job3.toString() ); 207 | assertEquals(job.getJobIdentifier(), job3.getJobIdentifier()); 208 | assertEquals(JobStatus.CANCELED, job3.getStatus()); 209 | } 210 | } 211 | 212 | @Test 213 | public void testGetJobHistoryByName() { 214 | JobHistorySearchParams searchParams = new JobHistorySearchParams(); 215 | searchParams.setUser("a"); 216 | List jobs = null; 217 | try { 218 | jobs = this.jobClient.getJobHistory(searchParams); 219 | } catch (ApiException e) { 220 | fail(e.getMessage()); 221 | } 222 | assertNotNull(jobs); 223 | assertNotEquals(jobs.size(), 0); 224 | String userName; 225 | for( Job job : jobs ) { 226 | this.logger.info( job.toString() ); 227 | assertNotNull(job.getJobIdentifier() ); 228 | assertNotNull(job.getStatus()); 229 | assertNotNull(job.getModel()); 230 | } 231 | } 232 | 233 | @Test 234 | public void testGetJobHistoryByModel() { 235 | JobHistorySearchParams searchParams = new JobHistorySearchParams(); 236 | //Search by model name 237 | searchParams.setModel( "Sentiment Analysis" ); 238 | List jobs = null; 239 | try { 240 | jobs = this.jobClient.getJobHistory(searchParams); 241 | } catch (ApiException e) { 242 | fail(e.getMessage()); 243 | } 244 | assertNotNull(jobs); 245 | assertNotEquals(jobs.size(), 0); 246 | for( Job job : jobs ) { 247 | this.logger.info( job.toString() ); 248 | assertNotNull(job.getJobIdentifier() ); 249 | assertNotNull(job.getStatus()); 250 | assertNotNull(job.getModel()); 251 | } 252 | } 253 | 254 | @Test 255 | public void testGetJobHistoryByAccessKey() { 256 | JobHistorySearchParams searchParams = new JobHistorySearchParams(); 257 | searchParams.setAccessKey( this.apiKey.split("\\.")[0] ); 258 | List jobs = null; 259 | try { 260 | jobs = this.jobClient.getJobHistory(searchParams); 261 | } catch (ApiException e) { 262 | fail(e.getMessage()); 263 | } 264 | assertNotNull(jobs); 265 | assertNotEquals(jobs.size(), 0); 266 | for( Job job : jobs ) { 267 | this.logger.info( job.toString() ); 268 | assertNotNull(job.getJobIdentifier() ); 269 | assertNotNull(job.getStatus()); 270 | assertNotNull(job.getModel()); 271 | } 272 | } 273 | 274 | @Test 275 | public void testGetJobHistoryByDate() { 276 | JobHistorySearchParams searchParams = new JobHistorySearchParams(); 277 | Calendar calendar = Calendar.getInstance(); 278 | calendar.add(Calendar.WEEK_OF_YEAR, -1); 279 | // Only Start Date 280 | searchParams.setStartDate(calendar.getTime()); 281 | List jobs = null; 282 | try { 283 | jobs = this.jobClient.getJobHistory(searchParams); 284 | } catch (ApiException e) { 285 | fail(e.getMessage()); 286 | } 287 | assertNotNull(jobs); 288 | assertNotEquals(jobs.size(), 0); 289 | // Only End Date 290 | searchParams.setStartDate(null); 291 | searchParams.setEndDate( new Date() ); 292 | try { 293 | jobs = this.jobClient.getJobHistory(searchParams); 294 | fail("This call should fail"); 295 | } catch (ApiException e) { 296 | // With only the end data it should fail 297 | } 298 | // Start and End Date 299 | searchParams.setStartDate(calendar.getTime()); 300 | try { 301 | jobs = this.jobClient.getJobHistory(searchParams); 302 | } catch (ApiException e) { 303 | fail(e.getMessage()); 304 | } 305 | assertNotNull(jobs); 306 | assertNotEquals(jobs.size(), 0); 307 | } 308 | 309 | @Test 310 | public void testGetJobHistoryByStatus() { 311 | JobHistorySearchParams searchParams = new JobHistorySearchParams(); 312 | searchParams.setStatus(JobHistorySearchStatus.TERMINATED); 313 | List jobs = null; 314 | try { 315 | jobs = this.jobClient.getJobHistory(searchParams); 316 | } catch (ApiException e) { 317 | fail(e.getMessage()); 318 | } 319 | assertNotNull(jobs); 320 | assertNotEquals(jobs.size(), 0); 321 | String userName; 322 | for( Job job : jobs ) { 323 | this.logger.info( job.toString() ); 324 | assertNotNull(job.getJobIdentifier() ); 325 | assertNotNull(job.getStatus()); 326 | assertNotNull(job.getModel()); 327 | } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /src/test/java/com/modzy/sdk/TestModelClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import static org.junit.Assert.assertNotEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.fail; 6 | 7 | import java.util.List; 8 | import java.util.logging.Logger; 9 | 10 | import javax.ws.rs.client.Client; 11 | import javax.ws.rs.client.ClientBuilder; 12 | import javax.ws.rs.client.WebTarget; 13 | 14 | import org.junit.After; 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | 18 | import com.modzy.sdk.exception.ApiException; 19 | import com.modzy.sdk.filter.LoggingFilter; 20 | import com.modzy.sdk.model.Model; 21 | import com.modzy.sdk.model.ModelVersion; 22 | import com.modzy.sdk.util.LoggerFactory; 23 | 24 | import io.github.cdimascio.dotenv.Dotenv; 25 | 26 | public class TestModelClient { 27 | 28 | private ModelClient modelClient; 29 | private Logger logger; 30 | 31 | @Before 32 | public void setUp() throws Exception { 33 | this.logger = LoggerFactory.getLogger(this); 34 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 35 | Client client = ClientBuilder.newClient().register(LoggingFilter.class); 36 | WebTarget baseTarget = client.target(dotenv.get("MODZY_BASE_URL")); 37 | this.modelClient = new ModelClient(baseTarget, dotenv.get("MODZY_API_KEY")); 38 | } 39 | 40 | @After 41 | public void tearDown() throws Exception { 42 | 43 | } 44 | 45 | @Test 46 | public void testGetAllModels(){ 47 | List models = null; 48 | try { 49 | models = this.modelClient.getAllModels(); 50 | } 51 | catch(ApiException ae) { 52 | fail(ae.getMessage()); 53 | } 54 | assertNotNull(models); 55 | assertNotEquals(models.size(), 0); 56 | for( Model model : models ) { 57 | this.logger.info( model.toString() ); 58 | assertNotNull(model.getIdentifier()); 59 | assertNotNull(model.getLatestVersion()); 60 | assertNotNull(model.getVersions()); 61 | } 62 | } 63 | 64 | @Test 65 | public void testGetModelByName(){ 66 | Model model = null; 67 | try { 68 | model = this.modelClient.getModelByName("Military Equipment Classification"); 69 | } 70 | catch(ApiException ae) { 71 | fail(ae.getMessage()); 72 | } 73 | assertNotNull(model); 74 | this.logger.info( model.toString() ); 75 | assertNotNull(model.getIdentifier()); 76 | assertNotNull(model.getName()); 77 | assertNotNull(model.getDescription()); 78 | assertNotNull(model.getAuthor()); 79 | } 80 | 81 | @Test 82 | public void testGetModel() { 83 | Model model = null; 84 | try { 85 | model = this.modelClient.getModel("ed542963de"); 86 | } 87 | catch(ApiException ae) { 88 | fail(ae.getMessage()); 89 | } 90 | assertNotNull(model); 91 | this.logger.info( model.toString() ); 92 | assertNotNull(model.getIdentifier()); 93 | assertNotNull(model.getName()); 94 | assertNotNull(model.getDescription()); 95 | assertNotNull(model.getAuthor()); 96 | } 97 | 98 | @Test 99 | public void testGetRelatedModelsString() { 100 | List models = null; 101 | try { 102 | models = this.modelClient.getRelatedModels("ed542963de"); 103 | } 104 | catch(ApiException ae) { 105 | fail(ae.getMessage()); 106 | } 107 | assertNotNull(models); 108 | assertNotEquals(models.size(), 0); 109 | this.logger.info( models.toString() ); 110 | for( Model model : models ) { 111 | assertNotNull(model.getIdentifier()); 112 | assertNotNull(model.getName()); 113 | assertNotNull(model.getAuthor()); 114 | } 115 | } 116 | 117 | @Test 118 | public void testGetRelatedModelsModel() { 119 | Model saModel = null; 120 | try { 121 | saModel = this.modelClient.getModel("ed542963de"); 122 | } 123 | catch(ApiException ae) { 124 | fail(ae.getMessage()); 125 | } 126 | assertNotNull(saModel); 127 | assertNotNull(saModel.getIdentifier()); 128 | this.logger.info( saModel.toString() ); 129 | List models = null; 130 | try { 131 | models = this.modelClient.getRelatedModels(saModel); 132 | } 133 | catch(ApiException ae) { 134 | fail(ae.getMessage()); 135 | } 136 | assertNotNull(models); 137 | assertNotEquals(models.size(), 0); 138 | this.logger.info( models.toString() ); 139 | for( Model model : models ) { 140 | assertNotNull(model.getIdentifier()); 141 | assertNotNull(model.getName()); 142 | assertNotNull(model.getAuthor()); 143 | } 144 | 145 | } 146 | 147 | @Test 148 | public void testGetModelVersionsString() { 149 | List modelVersions = null; 150 | try { 151 | modelVersions = this.modelClient.getModelVersions("ed542963de"); 152 | } 153 | catch(ApiException ae) { 154 | fail(ae.getMessage()); 155 | } 156 | assertNotNull(modelVersions); 157 | assertNotEquals(modelVersions.size(), 0); 158 | this.logger.info( modelVersions.toString() ); 159 | for( ModelVersion modelVersion : modelVersions ) { 160 | assertNotNull(modelVersion.getVersion()); 161 | try { 162 | modelVersion = this.modelClient.getModelVersion("ed542963de", modelVersion.getVersion()); 163 | } 164 | catch(ApiException ae) { 165 | fail(ae.getMessage()); 166 | } 167 | assertNotNull(modelVersion.getCreatedBy()); 168 | assertNotNull(modelVersion.getCreatedAt()); 169 | } 170 | } 171 | 172 | @Test 173 | public void testGetModelVersionsModel() { 174 | Model saModel = null; 175 | try { 176 | saModel = this.modelClient.getModel("ed542963de"); 177 | } 178 | catch(ApiException ae) { 179 | fail(ae.getMessage()); 180 | } 181 | assertNotNull(saModel); 182 | assertNotNull(saModel.getIdentifier()); 183 | this.logger.info( saModel.toString() ); 184 | List modelVersions = null; 185 | try { 186 | modelVersions = this.modelClient.getModelVersions(saModel); 187 | } 188 | catch(ApiException ae) { 189 | fail(ae.getMessage()); 190 | } 191 | assertNotNull(modelVersions); 192 | assertNotEquals(modelVersions.size(), 0); 193 | this.logger.info( modelVersions.toString() ); 194 | for( ModelVersion modelVersion : modelVersions ) { 195 | assertNotNull(modelVersion.getVersion()); 196 | try { 197 | modelVersion = this.modelClient.getModelVersion("ed542963de", modelVersion.getVersion()); 198 | } 199 | catch(ApiException ae) { 200 | fail(ae.getMessage()); 201 | } 202 | assertNotNull(modelVersion.getCreatedBy()); 203 | assertNotNull(modelVersion.getCreatedAt()); 204 | } 205 | } 206 | 207 | @Test 208 | public void testGetModelVersion() { 209 | ModelVersion modelVersion = null; 210 | try { 211 | modelVersion = this.modelClient.getModelVersion("c60c8dbd79", "0.0.1"); 212 | } 213 | catch(ApiException ae) { 214 | fail(ae.getMessage()); 215 | } 216 | assertNotNull(modelVersion); 217 | } 218 | 219 | @Test 220 | public void testGetModelVersionInputSample() { 221 | String inputSample = null; 222 | try { 223 | inputSample = this.modelClient.getModelVersionInputSample("c60c8dbd79", "0.0.1"); 224 | } 225 | catch(ApiException ae) { 226 | fail(ae.getMessage()); 227 | } 228 | assertNotNull(inputSample); 229 | } 230 | 231 | @Test 232 | public void testGetModelVersionOutputSample() { 233 | String outputSample = null; 234 | try { 235 | outputSample = this.modelClient.getModelVersionOutputSample("c60c8dbd79", "0.0.1"); 236 | } 237 | catch(ApiException ae) { 238 | fail(ae.getMessage()); 239 | } 240 | assertNotNull(outputSample); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/test/java/com/modzy/sdk/TestModzyClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import static org.junit.Assert.assertNotEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.fail; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.Arrays; 10 | import java.util.Map; 11 | import java.util.logging.Level; 12 | import java.util.logging.Logger; 13 | 14 | import javax.ws.rs.client.Client; 15 | import javax.ws.rs.client.ClientBuilder; 16 | import javax.ws.rs.client.WebTarget; 17 | 18 | import org.apache.commons.io.IOUtils; 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | 22 | import com.fasterxml.jackson.databind.JsonNode; 23 | import com.modzy.sdk.dto.EmbeddedData; 24 | import com.modzy.sdk.exception.ApiException; 25 | import com.modzy.sdk.filter.LoggingFilter; 26 | import com.modzy.sdk.util.LoggerFactory; 27 | 28 | import io.github.cdimascio.dotenv.Dotenv; 29 | 30 | public class TestModzyClient { 31 | 32 | private ModzyClient modzyClient; 33 | private Logger logger; 34 | 35 | @Before 36 | public void setUp() throws Exception { 37 | Client client = ClientBuilder.newClient().register(LoggingFilter.class); 38 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 39 | WebTarget baseTarget = client.target(dotenv.get("MODZY_BASE_URL")); 40 | this.modzyClient = new ModzyClient(baseTarget, dotenv.get("MODZY_API_KEY")); 41 | this.logger = LoggerFactory.getLogger(this); 42 | } 43 | 44 | 45 | @Test 46 | public void testSentimentAnalysis() { 47 | Map retValue = null; 48 | try { 49 | retValue = this.modzyClient.submitJobTextBlockUntilComplete("ed542963de", "Modzy is great!"); 50 | } catch (ApiException e) { 51 | this.logger.log(Level.SEVERE, e.getMessage(), e); 52 | fail(e.getMessage()); 53 | } 54 | assertNotNull(retValue); 55 | assertNotEquals(0,retValue.values().size()); 56 | for( String key : retValue.keySet() ) { 57 | this.logger.info(retValue.get(key).toString()); 58 | assertNotNull(retValue.get(key)); 59 | } 60 | this.logger.info(retValue.toString()); 61 | } 62 | 63 | @Test 64 | public void testSentimentAnalysisWithJDBC() { 65 | Map retValue = null; 66 | try { 67 | retValue = this.modzyClient.submitJobJDBCBlockUntilComplete( 68 | "ed542963de", "0.0.27", 69 | "jdbc:postgresql://testdb-postgres:5432/test", 70 | "test", "test", 71 | "org.postgresql.Driver", 72 | "select text_sample as 'input.txt' from text_samples" 73 | ); 74 | } catch (ApiException e) { 75 | this.logger.log(Level.SEVERE, e.getMessage(), e); 76 | fail(e.getMessage()); 77 | } 78 | assertNotNull(retValue); 79 | assertNotEquals(0,retValue.values().size()); 80 | for( String key : retValue.keySet() ) { 81 | this.logger.info(retValue.get(key).toString()); 82 | assertNotNull(retValue.get(key)); 83 | } 84 | this.logger.info(retValue.toString()); 85 | } 86 | 87 | 88 | @Test 89 | public void testRussianToEnglishTranslation() { 90 | Map retValue = null; 91 | try { 92 | retValue = this.modzyClient.submitJobTextBlockUntilComplete("cbf9e8d6da", "Машинное обучение - это здорово!"); 93 | } catch (ApiException e) { 94 | this.logger.log(Level.SEVERE, e.getMessage(), e); 95 | fail(e.getMessage()); 96 | } 97 | assertNotNull(retValue); 98 | assertNotEquals(0,retValue.values().size()); 99 | for( String key : retValue.keySet() ) { 100 | this.logger.info(retValue.get(key).toString()); 101 | assertNotNull(retValue.get(key)); 102 | } 103 | this.logger.info(retValue.toString()); 104 | } 105 | 106 | @Test 107 | public void testNSFW() { 108 | // 109 | Map retValue = null; 110 | InputStream is =TestModzyClient.class.getResourceAsStream("/images/example_1.jpg"); 111 | byte[] imageBytes = null; 112 | try { 113 | imageBytes = IOUtils.toByteArray( is ); 114 | } catch (IOException e) { 115 | this.logger.log(Level.SEVERE, e.getMessage(), e); 116 | fail(e.getMessage()); 117 | } 118 | assertNotNull(imageBytes); 119 | try { 120 | retValue = this.modzyClient.submitJobEmbeddedBlockUntilComplete("e3f73163d3", Arrays.asList(new EmbeddedData(imageBytes))); 121 | } catch (ApiException e) { 122 | this.logger.log(Level.SEVERE, e.getMessage(), e); 123 | fail(e.getMessage()); 124 | } 125 | assertNotEquals(0,retValue.values().size()); 126 | for( String key : retValue.keySet() ) { 127 | this.logger.info(retValue.get(key).toString()); 128 | assertNotNull(retValue.get(key)); 129 | } 130 | this.logger.info(retValue.toString()); 131 | } 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/test/java/com/modzy/sdk/TestResultClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | import static org.junit.Assert.fail; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.logging.Logger; 11 | 12 | import javax.ws.rs.client.Client; 13 | import javax.ws.rs.client.ClientBuilder; 14 | import javax.ws.rs.client.WebTarget; 15 | 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | 19 | import com.modzy.sdk.exception.ApiException; 20 | import com.modzy.sdk.filter.LoggingFilter; 21 | import com.modzy.sdk.model.Job; 22 | import com.modzy.sdk.model.JobInput; 23 | import com.modzy.sdk.model.JobInputText; 24 | import com.modzy.sdk.model.JobOutput; 25 | import com.modzy.sdk.model.JobStatus; 26 | import com.modzy.sdk.model.Model; 27 | import com.modzy.sdk.model.ModelVersion; 28 | import com.modzy.sdk.util.LoggerFactory; 29 | 30 | import io.github.cdimascio.dotenv.Dotenv; 31 | 32 | public class TestResultClient { 33 | 34 | private ModelClient modelClient; 35 | private JobClient jobClient; 36 | private ResultClient resultClient; 37 | 38 | private Logger logger; 39 | 40 | @Before 41 | public void setUp() throws Exception { 42 | this.logger = LoggerFactory.getLogger(this); 43 | Client client = ClientBuilder.newClient().register(LoggingFilter.class); 44 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 45 | WebTarget baseTarget = client.target(dotenv.get("MODZY_BASE_URL")); 46 | this.modelClient = new ModelClient(baseTarget, dotenv.get("MODZY_API_KEY")); 47 | this.jobClient = new JobClient(baseTarget, dotenv.get("MODZY_API_KEY")); 48 | this.resultClient = new ResultClient(baseTarget, dotenv.get("MODZY_API_KEY")); 49 | } 50 | 51 | @Test 52 | public void testGetResult(){ 53 | Model model = null; 54 | try { 55 | model = this.modelClient.getModel("ed542963de");//sentiment-analysis 56 | } catch (ApiException e) { 57 | fail(e.getMessage()); 58 | } 59 | assertNotNull(model); 60 | assertNotEquals(model.getVersions(), 0); 61 | ModelVersion modelVersion = null; 62 | try { 63 | modelVersion = this.modelClient.getModelVersion(model.getIdentifier(), model.getLatestVersion()); 64 | } catch (ApiException e) { 65 | fail(e.getMessage()); 66 | } 67 | assertNotNull(modelVersion); 68 | assertNotEquals(modelVersion.getInputs(), 0); 69 | assertNotEquals(modelVersion.getOutputs(), 0); 70 | // 71 | Map sourceMap = new HashMap(); 72 | sourceMap.put("input.txt", "Modzy is great!"); 73 | JobInput jobInput = new JobInputText(); 74 | jobInput.addSource(sourceMap); 75 | Job job = null; 76 | try { 77 | job = this.jobClient.submitJob(model, modelVersion, jobInput); 78 | this.logger.info( job.toString() ); 79 | } catch (ApiException e) { 80 | fail(e.getMessage()); 81 | } 82 | assertNotNull(job); 83 | do { 84 | this.logger.info("Waiting... for run"); 85 | try { 86 | Thread.sleep( 15000 ); 87 | } catch (InterruptedException e) { 88 | fail(e.getMessage()); 89 | } 90 | try { 91 | job = this.jobClient.getJob(job); 92 | } catch (ApiException e) { 93 | fail(e.getMessage()); 94 | } 95 | } 96 | while(!job.getStatus().equals(JobStatus.COMPLETED) && !job.getStatus().equals(JobStatus.CANCELED)); 97 | // 98 | JobOutput jobOutput = null; 99 | try { 100 | jobOutput = this.resultClient.getResult(job); 101 | } catch (ApiException e) { 102 | fail(e.getMessage()); 103 | } 104 | assertNotNull(jobOutput); 105 | assertEquals(job.getJobIdentifier(), jobOutput.getJobIdentifier()); 106 | assertNotNull(jobOutput.getResults()); 107 | Map mapResult; 108 | Object result; 109 | for( String resultsKey : jobOutput.getResults().keySet() ) { 110 | mapResult = jobOutput.getResults().get(resultsKey); 111 | assertNotEquals(0, mapResult.size()); 112 | for( String resultKey : mapResult.keySet() ){ 113 | result = mapResult.get(resultKey); 114 | this.logger.info("res["+resultsKey+"]["+resultKey+"]: "+result.getClass()+" => "+result.toString()); 115 | } 116 | } 117 | 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/test/java/com/modzy/sdk/TestTagClient.java: -------------------------------------------------------------------------------- 1 | package com.modzy.sdk; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotEquals; 5 | import static org.junit.Assert.assertNotNull; 6 | import static org.junit.Assert.fail; 7 | 8 | import java.util.List; 9 | 10 | import javax.ws.rs.client.Client; 11 | import javax.ws.rs.client.ClientBuilder; 12 | import javax.ws.rs.client.WebTarget; 13 | 14 | import org.junit.After; 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | 18 | import com.modzy.sdk.dto.TagWrapper; 19 | import com.modzy.sdk.exception.ApiException; 20 | import com.modzy.sdk.filter.LoggingFilter; 21 | import com.modzy.sdk.model.Model; 22 | import com.modzy.sdk.model.Tag; 23 | 24 | import io.github.cdimascio.dotenv.Dotenv; 25 | 26 | public class TestTagClient { 27 | 28 | private TagClient tagClient; 29 | 30 | @Before 31 | public void setUp() throws Exception { 32 | Client client = ClientBuilder.newClient().register(LoggingFilter.class); 33 | Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); 34 | WebTarget baseTarget = client.target(dotenv.get("MODZY_BASE_URL")); 35 | this.tagClient = new TagClient(baseTarget, dotenv.get("MODZY_API_KEY")); 36 | } 37 | 38 | @After 39 | public void tearDown() throws Exception { 40 | 41 | } 42 | 43 | @Test 44 | public void testGetAllTags() { 45 | List tags = null; 46 | try { 47 | tags = this.tagClient.getAllTags(); 48 | } 49 | catch(ApiException ae) { 50 | fail(ae.getMessage()); 51 | } 52 | assertNotNull(tags); 53 | assertNotEquals(tags.size(), 0); 54 | for( Tag tag : tags ) { 55 | assertNotNull(tag.getIdentifier()); 56 | assertNotNull(tag.getName()); 57 | assertNotNull(tag.getDataType()); 58 | } 59 | } 60 | 61 | @Test 62 | public void testGetTagsAndModels() { 63 | TagWrapper tagWrapper = null; 64 | try { 65 | tagWrapper = this.tagClient.getTagsAndModels("computer_vision"); 66 | } 67 | catch(ApiException ae) { 68 | fail(ae.getMessage()); 69 | } 70 | assertNotNull(tagWrapper); 71 | assertNotNull(tagWrapper.getTags()); 72 | assertNotEquals(tagWrapper.getTags().size(), 0); 73 | for( Tag tag : tagWrapper.getTags() ) { 74 | assertNotNull(tag.getIdentifier()); 75 | assertNotNull(tag.getName()); 76 | assertNotNull(tag.getDataType()); 77 | } 78 | assertNotNull(tagWrapper.getModels()); 79 | assertNotEquals(tagWrapper.getModels().size(), 0); 80 | for( Model model : tagWrapper.getModels() ) { 81 | assertNotNull(model.getIdentifier()); 82 | assertNotNull(model.getName()); 83 | assertNotNull(model.getTags()); 84 | } 85 | } 86 | 87 | @Test 88 | public void testGetModelsByInvalidTagId() { 89 | TagWrapper tagWrapper = null; 90 | try { 91 | tagWrapper = this.tagClient.getTagsAndModels("computer-vision"); 92 | } 93 | catch(ApiException ae) { 94 | fail(ae.getMessage()); 95 | } 96 | assertNotNull(tagWrapper); 97 | assertNotNull(tagWrapper.getTags()); 98 | assertEquals(0, tagWrapper.getTags().size()); 99 | assertNotNull(tagWrapper.getModels()); 100 | assertEquals(0, tagWrapper.getModels().size()); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/resources/images/example_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modzy/sdk-java/42f188a12e286cd470db9178a33c3ee2e9243def/src/test/resources/images/example_1.jpg -------------------------------------------------------------------------------- /src/test/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers= java.util.logging.ConsoleHandler 2 | 3 | java.util.logging.ConsoleHandler.level = INFO 4 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 5 | java.util.logging.SimpleFormatter.format = [%1$tF %1$tT] [%4$-7s] [%2$s] %5$s %6$s %n --------------------------------------------------------------------------------