diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..d8e9561
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+ * Note: This method is useful if you want to fetch the collection from the server to check if it exists before using it. + *
+ */ + public Collection fetchCollection(String collectionName) throws IOException, URISyntaxException { + URL url = new URI("https://api.marcsync.dev/v0/collection/" + collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to fetch collection: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return new Collection(_accessToken, collectionName); + } + + /** + * + * @param collectionName The name of the collection to create + * @return A new instance of the MarcSync collection + * + * @throws IOException + * @throws URISyntaxException + */ + public Collection createCollection(String collectionName) throws IOException, URISyntaxException { + URL url = new URI("https://api.marcsync.dev/v0/collection/" + collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to create collection: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return new Collection(_accessToken, collectionName); + } +} diff --git a/src/main/java/MarcSync/Collection.java b/src/main/java/MarcSync/Collection.java new file mode 100644 index 0000000..c77f104 --- /dev/null +++ b/src/main/java/MarcSync/Collection.java @@ -0,0 +1,314 @@ +package MarcSync; + +import MarcSync.classes.*; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.gson.*; + +import java.io.*; +import java.net.*; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +public class Collection { + + private final String _accessToken; + private final String _collectionName; + private final ObjectMapper _mapper; + + /** + * Creates a new instance of the MarcSync collection + * @param accessToken The access token to use for communication with MarcSync + * @param collectionName The name of the collection to use + * + * @see Client + **/ + public Collection(String accessToken, String collectionName) { + _accessToken = accessToken; + _collectionName = collectionName; + + _mapper = new ObjectMapper(); + _mapper.enable(SerializationFeature.INDENT_OUTPUT); + _mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + } + + /** + * + * Warning: + * @throws URISyntaxException + * @throws IOException + *+ * Note: This method will delete the collection and all of its entries. This action cannot be undone. + *
+ * + */ + public void drop() throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v0/collection/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("DELETE"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to drop collection: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } + + /** + * @return The name of the collection + */ + public String setName(String name) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v0/collection/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("PUT"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(new Gson().toJson(new CollectionUpdatePayload(name)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to rename collection: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return name; + } + + /** + * @return The name of the collection + */ + public String getName() { + return _collectionName; + } + + /** + * + * @return Whether or not the collection exists + * + *+ * Note: This method is useful if you want to fetch the collection from the server to check if it exists before using it. + *
+ * + */ + public boolean exists() { + try { + URL url = new URI("https://api.marcsync.dev/v0/collection/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + + return connection.getResponseCode() == 200; + } catch (Exception e) { + return false; + } + } + + /** + * Creates an entry in the collection + * + * @return A new instance of the MarcSync entry + * + */ + public Entry createEntry(EntryData entryData) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v0/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryDataPayload(entryData)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to create entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return new Entry(_accessToken, _collectionName, entryData); + } + + + /** + * + * @return The entry with the specified ID + * + */ + public Entry getEntryById(String id) throws URISyntaxException, IOException, InterruptedException { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .method("GET", HttpRequest.BodyPublishers.ofString(_mapper.writeValueAsString(new EntryFilterPayload(new EntryData() {{ + put("_id", id); + }})))) + .uri(new URI("https://api.marcsync.dev/v1/entries/" + _collectionName)) + .header("accept", "application/json") + .header("authorization", _accessToken) + .header("content-type", "application/json") + .build(); + + HttpResponse+ * Note: This method is useful if you want to fetch multiple entries from the server at once. + *
+ * + * @see Entry + * @see EntryData + * + */ + public Entry[] getEntries(EntryData filters) throws IOException, InterruptedException, URISyntaxException { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .method("GET", HttpRequest.BodyPublishers.ofString(_mapper.writeValueAsString(new EntryFilterPayload(filters)))) + .uri(new URI("https://api.marcsync.dev/v1/entries/" + _collectionName)) + .header("accept", "application/json") + .header("authorization", _accessToken) + .header("content-type", "application/json") + .build(); + + HttpResponse+ * Note: Will delete the entry from the collection. This action cannot be undone. + *
+ * + */ + public void deleteEntryById(String id) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("DELETE"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(new Gson().toJson(new EntryFilterPayload(new EntryData() {{ + put("_id", id); + }})).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to delete entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } + + /** + * + * Deletes the entries matching with the specified filter + *+ * Note: Will delete the matching entries from the collection. This action cannot be undone. + *
+ * + * @see EntryData + */ + public void deleteEntries(EntryData filters) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("DELETE"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryFilterPayload(filters)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to delete entries: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } + + /** + * + * Updates the entry with the specified ID + * + * @see Entry + * @see EntryData + */ + public void updateEntryById(String id, EntryData entryData) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("PUT"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryUpdatePayload(new EntryData() {{ + put("_id", id); + }}, entryData)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to update entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } + + /** + * + * Updates the entries matching with the specified filter + * + * @see Entry + * @see EntryData + */ + public void updateEntries(EntryData filters, EntryData entryData) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("PUT"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryUpdatePayload(filters, entryData)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to update entries: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } + + private static String readResponse(InputStream inputStream) throws IOException { + StringBuilder response = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + } + return response.toString(); + } +} diff --git a/src/main/java/MarcSync/Entry.java b/src/main/java/MarcSync/Entry.java new file mode 100644 index 0000000..3a4a8f1 --- /dev/null +++ b/src/main/java/MarcSync/Entry.java @@ -0,0 +1,169 @@ +package MarcSync; + +import MarcSync.classes.EntryData; +import MarcSync.classes.EntryFilterPayload; +import MarcSync.classes.EntryUpdatePayload; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.*; +import java.nio.charset.StandardCharsets; + +public class Entry { + + private final String _accessToken; + private final String _collectionName; + private final EntryData _entryData; + private final ObjectMapper _mapper; + + public Entry(String accessToken, String collectionName, EntryData entryData) { + _accessToken = accessToken; + _collectionName = collectionName; + _entryData = entryData; + + _mapper = new ObjectMapper(); + _mapper.enable(SerializationFeature.INDENT_OUTPUT); + _mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + } + + /** + * + * @return The EntryData object of the entry + * + *+ * Note: This method is useful if you want to get the values of the entry. + *
+ * + * @see EntryData + * + */ + public EntryData getValues() { + return _entryData; + } + + /** + * + * @param key The key of the value to get + * @return The value of the specified key + * + *+ * Note: This method is useful if you want to get the value of a specific key without specifying the type. + *
+ * + * @see EntryData + * + */ + public Object getValue(String key) { + return _entryData.get(key); + } + + /** + * + * @return The name of the collection of the entry + * + */ + public String getCollectionName() { + return _collectionName; + } + + /** + * + * @param key he key of the value to update + * @param value The value to update + * @return The values of the entry after update + * + * + *+ * Note: This method is useful if you want to update the value of a specific key. + *
+ * + */ + public EntryData updateValue(String key, Object value) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("PUT"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryUpdatePayload(new EntryData() {{ + put("_id", _entryData.get("_id")); + }}, new EntryData() {{ + put(key, value); + }})).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to update entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return _entryData; + } + + /** + * + * @param entryData The values to update + * @return The values of the entry after update + * + *+ * Note: This method is useful if you want to update multiple values of the entry. + *
+ * + * + * @see EntryData + * + */ + public EntryData updateValues(EntryData entryData) throws URISyntaxException, IOException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("PUT"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryUpdatePayload(new EntryData() {{ + put("_id", _entryData.get("_id")); + }}, entryData)).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to update entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + + return _entryData; + } + + /** + * + * Deletes the entry + *+ * Note: Will delete the entry from the collection. This action cannot be undone. + *
+ * + */ + public void delete() throws IOException, URISyntaxException { + URL url = new URI("https://api.marcsync.dev/v1/entries/" + _collectionName).toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("DELETE"); + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("authorization", _accessToken); + connection.setRequestProperty("content-type", "application/json"); + connection.setDoOutput(true); + + try (OutputStream outputStream = connection.getOutputStream()) { + outputStream.write(_mapper.writeValueAsString(new EntryFilterPayload(new EntryData() {{ + put("_id", _entryData.get("_id")); + }})).getBytes(StandardCharsets.UTF_8)); + } + + if (connection.getResponseCode() != 200) { + throw new IOException("Failed to delete entry: " + connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/MarcSync/classes/CollectionUpdatePayload.java b/src/main/java/MarcSync/classes/CollectionUpdatePayload.java new file mode 100644 index 0000000..e7282a4 --- /dev/null +++ b/src/main/java/MarcSync/classes/CollectionUpdatePayload.java @@ -0,0 +1,9 @@ +package MarcSync.classes; + +public class CollectionUpdatePayload { + public String collectionName; + + public CollectionUpdatePayload(String collectionName) { + this.collectionName = collectionName; + } +} diff --git a/src/main/java/MarcSync/classes/EntryData.java b/src/main/java/MarcSync/classes/EntryData.java new file mode 100644 index 0000000..0452992 --- /dev/null +++ b/src/main/java/MarcSync/classes/EntryData.java @@ -0,0 +1,11 @@ +package MarcSync.classes; + +import com.google.gson.Gson; + +import java.util.HashMap; + +public class EntryData extends HashMap