diff --git a/build.gradle b/build.gradle
index d0fdd12..d6c241c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -82,8 +82,6 @@ buildscript {
repositories {
jcenter()
- maven { url "https://kamax.io/maven/releases/" }
- maven { url "https://kamax.io/maven/snapshots/" }
}
dependencies {
@@ -96,14 +94,16 @@ dependencies {
// Config management
compile 'org.yaml:snakeyaml:1.23'
- // Matrix Java SDK
- compile 'io.kamax:matrix-java-sdk:0.0.14-8-g0e57ec6'
+ // Dependencies from old Matrix-java-sdk
+ compile 'org.apache.commons:commons-lang3:3.8.1'
+ compile 'com.squareup.okhttp3:okhttp:3.12.0'
+ compile 'commons-codec:commons-codec:1.11'
// ORMLite
compile 'com.j256.ormlite:ormlite-jdbc:5.0'
// ed25519 handling
- compile 'net.i2p.crypto:eddsa:0.1.0'
+ compile 'net.i2p.crypto:eddsa:0.3.0'
// LDAP connector
compile 'org.apache.directory.api:api-all:1.0.0'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ea13fdf..0a20753 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Thu Jul 04 22:47:59 MSK 2019
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/src/main/java/io/kamax/matrix/MalformedEventException.java b/src/main/java/io/kamax/matrix/MalformedEventException.java
new file mode 100644
index 0000000..cb13171
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MalformedEventException.java
@@ -0,0 +1,33 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public class MalformedEventException extends MatrixException {
+
+ public MalformedEventException(String s) {
+ super("M_NOT_JSON", s);
+ }
+
+ public static MalformedEventException forId(String id) {
+ return new MalformedEventException("Event " + id + " is malformed");
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/MatrixErrorInfo.java b/src/main/java/io/kamax/matrix/MatrixErrorInfo.java
new file mode 100644
index 0000000..3bcb857
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MatrixErrorInfo.java
@@ -0,0 +1,44 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public class MatrixErrorInfo {
+
+ private String errcode;
+ private String error;
+
+ public MatrixErrorInfo(String errcode) {
+ this.errcode = errcode;
+ }
+
+ public MatrixErrorInfo(Throwable t) {
+ this.errcode = "AS_INTERNAL_SERVER_ERROR";
+ }
+
+ public String getErrcode() {
+ return errcode;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/MatrixException.java b/src/main/java/io/kamax/matrix/MatrixException.java
new file mode 100644
index 0000000..a46cd67
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MatrixException.java
@@ -0,0 +1,48 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public class MatrixException extends RuntimeException {
+
+ private String errorCode;
+ private String error;
+
+ public MatrixException(String errorCode, String error) {
+ super(errorCode + ": " + error);
+ this.errorCode = errorCode;
+ this.error = error;
+ }
+
+ public MatrixException(String errorCode, String error, Throwable t) {
+ super(errorCode + ": " + error, t);
+ this.errorCode = errorCode;
+ this.error = error;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/MatrixID.java b/src/main/java/io/kamax/matrix/MatrixID.java
new file mode 100644
index 0000000..612e643
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MatrixID.java
@@ -0,0 +1,170 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class MatrixID implements _MatrixID {
+
+ public static class Builder {
+
+ private MatrixID mxId;
+
+ public Builder(String id) {
+ mxId = MatrixID.parse(id);
+ }
+
+ public MatrixID valid() {
+ if (!mxId.isValid()) {
+ throw new IllegalArgumentException(mxId + " is not a valid Matrix ID");
+ }
+ return mxId;
+ }
+
+ public MatrixID acceptable() {
+ if (!mxId.isAcceptable()) {
+ throw new IllegalArgumentException(mxId + " is not an acceptable Matrix ID");
+ }
+ return mxId;
+ }
+
+ }
+
+ public static final String ALLOWED_CHARS = "0-9a-z-.=_/";
+ public static final Pattern LAX_PATTERN = Pattern.compile("@(.*?):(.+)");
+ public static final Pattern STRICT_PATTERN = Pattern.compile("@([" + ALLOWED_CHARS + "]+):(.+)");
+
+ private String id;
+
+ private String localpart;
+ private String domain;
+
+ private static String buildRaw(String localpart, String domain) {
+ return "@" + localpart + ":" + domain;
+ }
+
+ private static MatrixID parse(String id) {
+ Matcher m = LAX_PATTERN.matcher(id);
+ if (!m.matches()) {
+ throw new IllegalArgumentException(id + " is not a Matrix ID");
+ }
+
+ MatrixID mxId = new MatrixID();
+ mxId.id = id;
+ mxId.localpart = m.group(1);
+ mxId.domain = m.group(2);
+ return mxId;
+ }
+
+ public static Builder from(String id) {
+ return new Builder(id);
+ }
+
+ public static Builder from(String local, String domain) {
+ return from(buildRaw(local, domain));
+ }
+
+ public static MatrixID asValid(String id) {
+ return new Builder(id).valid();
+ }
+
+ public static MatrixID asAcceptable(String local, String domain) {
+ return from(local, domain).acceptable();
+ }
+
+ public static MatrixID asAcceptable(String id) {
+ return from(id).acceptable();
+ }
+
+ private MatrixID() {
+ // not for public consumption
+ }
+
+ private MatrixID(MatrixID mxId) {
+ this.id = mxId.id;
+ this.localpart = mxId.localpart;
+ this.domain = mxId.domain;
+ }
+
+ @Deprecated
+ public MatrixID(String mxId) {
+ this(parse(mxId));
+ }
+
+ @Deprecated
+ public MatrixID(String localpart, String domain) {
+ this(parse(buildRaw(localpart, domain)));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getLocalPart() {
+ return localpart;
+ }
+
+ @Override
+ public String getDomain() {
+ return domain;
+ }
+
+ @Override
+ public MatrixID canonicalize() {
+ return parse(getId().toLowerCase());
+ }
+
+ @Override
+ public boolean isValid() {
+ return isAcceptable() && STRICT_PATTERN.matcher(id).matches();
+ }
+
+ @Override
+ public boolean isAcceptable() {
+ // TODO properly implement
+
+ return id.length() <= 255;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MatrixID)) return false;
+
+ MatrixID matrixID = (MatrixID) o;
+
+ return id.equals(matrixID.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return getId();
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/MatrixIdCodec.java b/src/main/java/io/kamax/matrix/MatrixIdCodec.java
new file mode 100644
index 0000000..82f2c2d
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MatrixIdCodec.java
@@ -0,0 +1,93 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static io.kamax.matrix.MatrixID.ALLOWED_CHARS;
+
+public class MatrixIdCodec {
+
+ public static final String DELIMITER = "=";
+ public static final String ENCODE_REGEX = "[^" + ALLOWED_CHARS + "]+";
+ public static final Pattern ENCODE_PATTERN = Pattern.compile(ENCODE_REGEX);
+ public static final Pattern DECODE_PATTERN = Pattern.compile("(=[0-9a-f]{2})+");
+
+ private MatrixIdCodec() {
+ // not for public consumption
+ }
+
+ public static String encode(String decoded) {
+ decoded = decoded.toLowerCase();
+
+ StringBuilder builder = new StringBuilder();
+ for (Character c : decoded.toCharArray()) {
+ String s = c.toString();
+ Matcher lp = ENCODE_PATTERN.matcher(s);
+ if (!lp.find()) {
+ builder.append(s);
+ } else {
+ for (byte b : c.toString().getBytes(StandardCharsets.UTF_8)) {
+ builder.append(DELIMITER);
+ builder.append(Hex.encodeHexString(new byte[] { b }));
+ }
+ }
+ }
+
+ return builder.toString();
+ }
+
+ public static String decode(String encoded) {
+ StringBuilder builder = new StringBuilder();
+
+ Matcher m = DECODE_PATTERN.matcher(encoded);
+ int prevEnd = 0;
+ while (m.find()) {
+ try {
+ int start = m.start();
+ int end = m.end();
+ String sub = encoded.substring(start, end).replaceAll(DELIMITER, "");
+ String decoded = new String(Hex.decodeHex(sub.toCharArray()), StandardCharsets.UTF_8);
+ builder.append(encoded, prevEnd, start);
+ builder.append(decoded);
+ prevEnd = end - 1;
+ } catch (DecoderException e) {
+ e.printStackTrace();
+ }
+ }
+ prevEnd++;
+ if (prevEnd < encoded.length()) {
+ builder.append(encoded, prevEnd, encoded.length());
+ }
+
+ if (builder.length() == 0) {
+ return encoded;
+ } else {
+ return builder.toString();
+ }
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/MatrixPath.java b/src/main/java/io/kamax/matrix/MatrixPath.java
new file mode 100644
index 0000000..89e799b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/MatrixPath.java
@@ -0,0 +1,104 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+public class MatrixPath {
+
+ public static String encode(String element) {
+ try {
+ return URLEncoder.encode(element, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ // This would be madness if it happened, but we need to handle it still
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static MatrixPath with(String base) {
+ return new MatrixPath().add(base);
+ }
+
+ public static MatrixPath root() {
+ return with("");
+ }
+
+ public static MatrixPath base() {
+ return root().add("_matrix");
+ }
+
+ public static MatrixPath client() {
+ return base().add("client");
+ }
+
+ public static MatrixPath clientR0() {
+ return client().add("r0");
+ }
+
+ private StringBuilder path = new StringBuilder();
+
+ /**
+ * Add the raw element to this path
+ *
+ * @param element
+ * The raw element to be added as is to the path, without encoding or path separator
+ * @return The MatrixPath
+ */
+ public MatrixPath put(String element) {
+ path.append(element);
+ return this;
+ }
+
+ /**
+ * URL encode and add a new path element
+ *
+ * This method handle path separators
+ *
+ * @param element
+ * The element to be encoded and added.
+ * @return The MatrixPath
+ */
+ public MatrixPath add(String element) {
+ // We add a path separator if this is the first character or if the last character is not a path separator
+ // already
+ if (path.length() == 0 || path.lastIndexOf("/", 0) < path.length() - 1) {
+ put("/");
+ }
+ put(encode(element));
+ return this;
+ }
+
+ public String get() {
+ return path.toString();
+ }
+
+ public String toString() {
+ return get();
+ }
+
+ public URI toURI() {
+ return URI.create(toString());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/ThreePid.java b/src/main/java/io/kamax/matrix/ThreePid.java
new file mode 100644
index 0000000..c93baa6
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/ThreePid.java
@@ -0,0 +1,61 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public class ThreePid implements _ThreePid {
+
+ private String medium;
+ private String address;
+
+ public ThreePid(String medium, String address) {
+ this.medium = medium;
+ this.address = address;
+ }
+
+ @Override
+ public String getMedium() {
+ return medium;
+ }
+
+ @Override
+ public String getAddress() {
+ return address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ThreePid threePid = (ThreePid) o;
+
+ if (!medium.equals(threePid.medium)) return false;
+ return address.equals(threePid.address);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = medium.hashCode();
+ result = 31 * result + address.hashCode();
+ return result;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/ThreePidMapping.java b/src/main/java/io/kamax/matrix/ThreePidMapping.java
new file mode 100644
index 0000000..8650438
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/ThreePidMapping.java
@@ -0,0 +1,61 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public class ThreePidMapping implements _ThreePidMapping {
+
+ private _ThreePid threePid;
+ private _MatrixID mxId;
+
+ public ThreePidMapping(_ThreePid threePid, _MatrixID mxId) {
+ this.threePid = threePid;
+ this.mxId = mxId;
+ }
+
+ @Override
+ public _ThreePid getThreePid() {
+ return threePid;
+ }
+
+ @Override
+ public _MatrixID getMatrixId() {
+ return mxId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ThreePidMapping that = (ThreePidMapping) o;
+
+ if (!threePid.equals(that.threePid)) return false;
+ return mxId.equals(that.mxId);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = threePid.hashCode();
+ result = 31 * result + mxId.hashCode();
+ return result;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/ThreePidMedium.java b/src/main/java/io/kamax/matrix/ThreePidMedium.java
new file mode 100644
index 0000000..c6e6020
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/ThreePidMedium.java
@@ -0,0 +1,46 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public enum ThreePidMedium {
+
+ Email("email"),
+ PhoneNumber("msisdn");
+
+ private String id;
+
+ ThreePidMedium(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String toString() {
+ return getId();
+ }
+
+ public boolean is(String s) {
+ return getId().contentEquals(s);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/_MatrixContent.java b/src/main/java/io/kamax/matrix/_MatrixContent.java
new file mode 100644
index 0000000..e9af68d
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_MatrixContent.java
@@ -0,0 +1,41 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Optional;
+
+public interface _MatrixContent {
+
+ URI getAddress();
+
+ URL getPermaLink();
+
+ boolean isValid();
+
+ Optional getType();
+
+ byte[] getData();
+
+ Optional getFilename();
+
+}
diff --git a/src/main/java/io/kamax/matrix/_MatrixID.java b/src/main/java/io/kamax/matrix/_MatrixID.java
new file mode 100644
index 0000000..42099ab
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_MatrixID.java
@@ -0,0 +1,55 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public interface _MatrixID {
+
+ String getId();
+
+ String getLocalPart();
+
+ String getDomain();
+
+ /**
+ * Render this Matrix ID strictly valid. In technical term, transform this ID so
+ * isValid()
returns true.
+ *
+ * @return A canonical Matrix ID
+ */
+ _MatrixID canonicalize();
+
+ /**
+ * If the Matrix ID is strictly valid in the protocol as per
+ * http://matrix.org/docs/spec/intro.html#user-identifiers
+ *
+ * @return true if strictly valid, false if not
+ */
+ boolean isValid();
+
+ /**
+ * If the Matrix ID is acceptable in the protocol as per
+ * http://matrix.org/docs/spec/intro.html#historical-user-ids
+ *
+ * @return
+ */
+ boolean isAcceptable();
+
+}
diff --git a/src/main/java/io/kamax/matrix/_MatrixUser.java b/src/main/java/io/kamax/matrix/_MatrixUser.java
new file mode 100644
index 0000000..ca90958
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_MatrixUser.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import io.kamax.matrix.client._Presence;
+
+import java.util.Optional;
+
+public interface _MatrixUser extends _MatrixUserProfile {
+
+ Optional<_Presence> getPresence();
+
+}
diff --git a/src/main/java/io/kamax/matrix/_MatrixUserProfile.java b/src/main/java/io/kamax/matrix/_MatrixUserProfile.java
new file mode 100644
index 0000000..4fa73b0
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_MatrixUserProfile.java
@@ -0,0 +1,42 @@
+/*
+ * matrix-java-sdk - Matrix SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+import java.net.URI;
+import java.util.Optional;
+
+public interface _MatrixUserProfile {
+
+ _MatrixID getId();
+
+ Optional getName();
+
+ void setName(String name);
+
+ Optional getAvatarUrl();
+
+ void setAvatar(String avatarRef);
+
+ void setAvatar(URI avatarUri);
+
+ Optional<_MatrixContent> getAvatar();
+
+}
diff --git a/src/main/java/io/kamax/matrix/_ThreePid.java b/src/main/java/io/kamax/matrix/_ThreePid.java
new file mode 100644
index 0000000..b5e9bc4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_ThreePid.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public interface _ThreePid {
+
+ String getMedium();
+
+ String getAddress();
+
+}
diff --git a/src/main/java/io/kamax/matrix/_ThreePidMapping.java b/src/main/java/io/kamax/matrix/_ThreePidMapping.java
new file mode 100644
index 0000000..55ee6fd
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/_ThreePidMapping.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix;
+
+public interface _ThreePidMapping {
+
+ _ThreePid getThreePid();
+
+ _MatrixID getMatrixId();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java b/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java
new file mode 100644
index 0000000..72bad39
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/AMatrixHttpClient.java
@@ -0,0 +1,409 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+import io.kamax.matrix.MatrixErrorInfo;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.hs._MatrixHomeserver;
+import io.kamax.matrix.json.GsonUtil;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.Objects;
+import java.util.Optional;
+
+
+import okhttp3.*;
+
+public abstract class AMatrixHttpClient implements _MatrixClientRaw {
+
+ private Logger log = LoggerFactory.getLogger(AMatrixHttpClient.class);
+
+ protected MatrixClientContext context;
+
+ protected Gson gson = GsonUtil.get();
+ protected JsonParser jsonParser = new JsonParser();
+ private OkHttpClient client;
+
+ public AMatrixHttpClient(String domain) {
+ this(new MatrixClientContext().setDomain(domain));
+ }
+
+ public AMatrixHttpClient(URL hsBaseUrl) {
+ this(new MatrixClientContext().setHsBaseUrl(hsBaseUrl));
+ }
+
+ protected AMatrixHttpClient(MatrixClientContext context) {
+ this(context, new OkHttpClient.Builder(), new MatrixClientDefaults());
+ }
+
+ protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
+ this(context, client, new MatrixClientDefaults());
+ }
+
+ protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client,
+ MatrixClientDefaults defaults) {
+ this(context, client.connectTimeout(defaults.getConnectTimeout(), TimeUnit.MILLISECONDS)
+ .readTimeout(5, TimeUnit.MINUTES).followRedirects(false).build());
+ }
+
+ protected AMatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
+ this.context = context;
+ this.client = client;
+ }
+
+ @Override
+ public Optional<_AutoDiscoverySettings> discoverSettings() {
+ if (StringUtils.isBlank(context.getDomain())) {
+ throw new IllegalStateException("A non-empty Matrix domain must be set to discover the client settings");
+ }
+
+ String hostname = context.getDomain().split(":")[0];
+ log.info("Performing .well-known auto-discovery for {}", hostname);
+
+ URL url = new HttpUrl.Builder().scheme("https").host(hostname).addPathSegments(".well-known/matrix/client")
+ .build().url();
+ String body = execute(new MatrixHttpRequest(new Request.Builder().get().url(url)).addIgnoredErrorCode(404));
+ if (StringUtils.isBlank(body)) {
+ if (Objects.isNull(context.getHsBaseUrl())) {
+ throw new IllegalStateException("No valid Homeserver base URL was found");
+ }
+
+ // No .well-known data found
+ // FIXME improve SDK so we can differentiate between not found and empty.
+ // not found = skip
+ // empty = failure
+ return Optional.empty();
+ }
+
+ log.info("Found body: {}", body);
+
+ WellKnownAutoDiscoverySettings settings = new WellKnownAutoDiscoverySettings(body);
+ log.info("Found .well-known data");
+
+ // TODO reconsider if and where we should check for an already present HS url in the context
+ if (settings.getHsBaseUrls().isEmpty()) {
+ throw new IllegalStateException("No valid Homeserver base URL was found");
+ }
+
+ for (URL baseUrlCandidate : settings.getHsBaseUrls()) {
+ context.setHsBaseUrl(baseUrlCandidate);
+ try {
+ if (!getHomeApiVersions().isEmpty()) {
+ log.info("Found a valid HS at {}", getContext().getHsBaseUrl().toString());
+ break;
+ }
+ } catch (MatrixClientRequestException e) {
+ log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
+ }
+ }
+
+ for (URL baseUrlCandidate : settings.getIsBaseUrls()) {
+ context.setIsBaseUrl(baseUrlCandidate);
+ try {
+ if (validateIsBaseUrl()) {
+ log.info("Found a valid IS at {}", getContext().getIsBaseUrl().toString());
+ break;
+ }
+ } catch (MatrixClientRequestException e) {
+ log.warn("Error when trying to fetch {}: {}", baseUrlCandidate, e.getMessage());
+ }
+ }
+
+ return Optional.of(settings);
+ }
+
+ @Override
+ public MatrixClientContext getContext() {
+ return context;
+ }
+
+ @Override
+ public _MatrixHomeserver getHomeserver() {
+ return context.getHomeserver();
+ }
+
+ @Override
+ public Optional getAccessToken() {
+ return Optional.ofNullable(context.getToken());
+ }
+
+ public String getAccessTokenOrThrow() {
+ return getAccessToken()
+ .orElseThrow(() -> new IllegalStateException("This method can only be used with a valid token."));
+ }
+
+ @Override
+ public List getHomeApiVersions() {
+ String body = execute(new Request.Builder().get().url(getPath("client", "", "versions")));
+ return GsonUtil.asList(GsonUtil.parseObj(body), "versions", String.class);
+ }
+
+ @Override
+ public boolean validateIsBaseUrl() {
+ String body = execute(new Request.Builder().get().url(getIdentityPath("identity", "api", "v1")));
+ return "{}".equals(body);
+ }
+
+ protected String getUserId() {
+ return getUser().orElseThrow(IllegalStateException::new).getId();
+ }
+
+ @Override
+ public Optional<_MatrixID> getUser() {
+ return context.getUser();
+ }
+
+ protected Request.Builder addAuthHeader(Request.Builder builder, String token) {
+ builder.addHeader("Authorization", "Bearer " + token);
+ return builder;
+ }
+
+ protected Request.Builder addAuthHeader(Request.Builder builder) {
+ return addAuthHeader(builder, getAccessTokenOrThrow());
+ }
+
+ protected String executeAuthenticated(Request.Builder builder, String token) {
+ return execute(addAuthHeader(builder, token));
+ }
+
+ protected String executeAuthenticated(Request.Builder builder) {
+ return execute(addAuthHeader(builder));
+ }
+
+ protected String executeAuthenticated(MatrixHttpRequest matrixRequest) {
+ addAuthHeader(matrixRequest.getHttpRequest());
+ return execute(matrixRequest);
+ }
+
+ protected String execute(Request.Builder builder) {
+ return execute(new MatrixHttpRequest(builder));
+ }
+
+ protected String execute(MatrixHttpRequest matrixRequest) {
+ log(matrixRequest.getHttpRequest());
+ try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
+ String body = response.body().string();
+ int responseStatus = response.code();
+
+ if (responseStatus == 200) {
+ log.debug("Request successfully executed.");
+ } else if (matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
+ log.debug("Error code ignored: " + responseStatus);
+ return "";
+ } else {
+ MatrixErrorInfo info = createErrorInfo(body, responseStatus);
+
+ body = handleError(matrixRequest, responseStatus, info);
+ }
+ return body;
+ } catch (IOException e) {
+ throw new MatrixClientRequestException(e);
+ }
+ }
+
+ protected MatrixHttpContentResult executeContentRequest(MatrixHttpRequest matrixRequest) {
+ log(matrixRequest.getHttpRequest());
+ try (Response response = client.newCall(matrixRequest.getHttpRequest().build()).execute()) {
+ int responseStatus = response.code();
+
+ MatrixHttpContentResult result;
+
+ if (responseStatus == 200 || matrixRequest.getIgnoredErrorCodes().contains(responseStatus)) {
+ log.debug("Request successfully executed.");
+ result = new MatrixHttpContentResult(response);
+ } else {
+ String body = response.body().string();
+ MatrixErrorInfo info = createErrorInfo(body, responseStatus);
+
+ result = handleErrorContentRequest(matrixRequest, responseStatus, info);
+ }
+ return result;
+ } catch (IOException e) {
+ throw new MatrixClientRequestException(e);
+ }
+ }
+
+ /**
+ * Default handling of errors. Can be overwritten by a custom implementation in inherited classes.
+ *
+ * @param matrixRequest
+ * @param responseStatus
+ * @param info
+ * @return body of the response of a repeated call of the request, else this methods throws a
+ * MatrixClientRequestException
+ */
+ protected String handleError(MatrixHttpRequest matrixRequest, int responseStatus, MatrixErrorInfo info) {
+ String message = String.format("Request failed: %s", responseStatus);
+
+ if (Objects.nonNull(info)) {
+ message = String.format("%s - %s - %s", message, info.getErrcode(), info.getError());
+ }
+
+ if (responseStatus == 429) {
+ return handleRateLimited(matrixRequest, info);
+ }
+
+ throw new MatrixClientRequestException(info, message);
+ }
+
+ /**
+ * Default handling of rate limited calls. Can be overwritten by a custom implementation in inherited classes.
+ *
+ * @param matrixRequest
+ * @param info
+ * @return body of the response of a repeated call of the request, else this methods throws a
+ * MatrixClientRequestException
+ */
+ protected String handleRateLimited(MatrixHttpRequest matrixRequest, MatrixErrorInfo info) {
+ throw new MatrixClientRequestException(info, "Request was rate limited.");
+ // TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
+ // 1. Wait for timeout
+ // 2. return execute(request)
+ }
+
+ protected MatrixHttpContentResult handleErrorContentRequest(MatrixHttpRequest matrixRequest, int responseStatus,
+ MatrixErrorInfo info) {
+ String message = String.format("Request failed with status code: %s", responseStatus);
+
+ if (responseStatus == 429) {
+ return handleRateLimitedContentRequest(matrixRequest, info);
+ }
+
+ throw new MatrixClientRequestException(info, message);
+ }
+
+ protected MatrixHttpContentResult handleRateLimitedContentRequest(MatrixHttpRequest matrixRequest,
+ MatrixErrorInfo info) {
+ throw new MatrixClientRequestRateLimitedException(info, "Request was rate limited.");
+ // TODO Add default handling of rate limited call, i.e. repeated call after given time interval.
+ // 1. Wait for timeout
+ // 2. return execute(request)
+ }
+
+ protected Optional extractAsStringFromBody(String body, String jsonObjectName) {
+ if (StringUtils.isEmpty(body)) {
+ return Optional.empty();
+ }
+
+ return GsonUtil.findString(jsonParser.parse(body).getAsJsonObject(), jsonObjectName);
+ }
+
+ private MatrixErrorInfo createErrorInfo(String body, int responseStatus) {
+ MatrixErrorInfo info = null;
+
+ try {
+ info = gson.fromJson(body, MatrixErrorInfo.class);
+ if (Objects.nonNull(info)) {
+ log.debug("Request returned with an error. Status code: {}, errcode: {}, error: {}", responseStatus,
+ info.getErrcode(), info.getError());
+ }
+ } catch (JsonSyntaxException e) {
+ log.debug("Unable to parse Matrix error info. Content was:\n{}", body);
+ }
+
+ return info;
+ }
+
+ private void log(Request.Builder req) {
+ log.debug("Doing {} {}", req, req.toString());
+ }
+
+ protected HttpUrl.Builder getHsBaseUrl() {
+ return HttpUrl.get(context.getHsBaseUrl()).newBuilder();
+ }
+
+ protected HttpUrl.Builder getIsBaseUrl() {
+ return HttpUrl.get(context.getIsBaseUrl()).newBuilder();
+ }
+
+ protected HttpUrl.Builder getPathBuilder(HttpUrl.Builder base, String... segments) {
+ base.addPathSegment("_matrix");
+ for (String segment : segments) {
+ base.addPathSegment(segment);
+ }
+
+ if (context.isVirtual()) {
+ context.getUser().ifPresent(user -> base.addQueryParameter("user_id", user.getId()));
+ }
+ return base;
+ }
+
+ protected HttpUrl.Builder getPathBuilder(String... segments) {
+ return getPathBuilder(getHsBaseUrl(), segments);
+ }
+
+ protected HttpUrl.Builder getIdentityPathBuilder(String... segments) {
+ return getPathBuilder(getIsBaseUrl(), segments);
+ }
+
+ protected URL getPath(String... segments) {
+ return getPathBuilder(segments).build().url();
+ }
+
+ protected URL getIdentityPath(String... segments) {
+ return getIdentityPathBuilder(segments).build().url();
+ }
+
+ protected HttpUrl.Builder getClientPathBuilder(String... segments) {
+ String[] base = { "client", "r0" };
+ segments = ArrayUtils.addAll(base, segments);
+ return getPathBuilder(segments);
+ }
+
+ protected HttpUrl.Builder getMediaPathBuilder(String... segments) {
+ String[] base = { "media", "r0" };
+ segments = ArrayUtils.addAll(base, segments);
+ return getPathBuilder(segments);
+ }
+
+ protected URL getClientPath(String... segments) {
+ return getClientPathBuilder(segments).build().url();
+ }
+
+ protected URL getMediaPath(String... segments) {
+ return getMediaPathBuilder(segments).build().url();
+ }
+
+ protected RequestBody getJsonBody(Object o) {
+ return RequestBody.create(MediaType.parse("application/json"), GsonUtil.get().toJson(o));
+ }
+
+ protected Request.Builder request(URL url) {
+ return new Request.Builder().url(url);
+ }
+
+ protected Request.Builder getRequest(URL url) {
+ return request(url).get();
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientContext.java b/src/main/java/io/kamax/matrix/client/MatrixClientContext.java
new file mode 100644
index 0000000..4d8454b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixClientContext.java
@@ -0,0 +1,154 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.hs.MatrixHomeserver;
+import io.kamax.matrix.hs._MatrixHomeserver;
+
+import java.net.URL;
+import java.util.Objects;
+import java.util.Optional;
+
+public class MatrixClientContext {
+
+ private String domain;
+ private URL hsBaseUrl;
+ private URL isBaseUrl;
+ private _MatrixID user;
+ private String token;
+ private boolean isVirtual;
+ private String deviceId;
+ private String initialDeviceName;
+
+ public MatrixClientContext() {
+ // stub
+ }
+
+ public MatrixClientContext(MatrixClientContext other) {
+ this.domain = other.domain;
+ this.hsBaseUrl = other.hsBaseUrl;
+ this.isBaseUrl = other.isBaseUrl;
+ this.user = other.user;
+ this.token = other.token;
+ this.isVirtual = other.isVirtual;
+ this.deviceId = other.deviceId;
+ this.initialDeviceName = other.initialDeviceName;
+ }
+
+ public MatrixClientContext(_MatrixHomeserver hs) {
+ setDomain(hs.getDomain());
+ setHsBaseUrl(hs.getBaseEndpoint());
+ }
+
+ public MatrixClientContext(_MatrixHomeserver hs, _MatrixID user, String token) {
+ this(hs);
+ setUser(user);
+ setToken(token);
+ }
+
+ public _MatrixHomeserver getHomeserver() {
+ if (Objects.isNull(hsBaseUrl)) {
+ throw new IllegalStateException("Homeserver Base URL is not set");
+ }
+
+ return new MatrixHomeserver(domain, hsBaseUrl.toString());
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public MatrixClientContext setDomain(String domain) {
+ this.domain = domain;
+ return this;
+ }
+
+ public URL getHsBaseUrl() {
+ return hsBaseUrl;
+ }
+
+ public MatrixClientContext setHsBaseUrl(URL hsBaseUrl) {
+ this.hsBaseUrl = hsBaseUrl;
+ return this;
+ }
+
+ public URL getIsBaseUrl() {
+ return isBaseUrl;
+ }
+
+ public MatrixClientContext setIsBaseUrl(URL isBaseUrl) {
+ this.isBaseUrl = isBaseUrl;
+ return this;
+ }
+
+ public Optional<_MatrixID> getUser() {
+ return Optional.ofNullable(user);
+ }
+
+ public MatrixClientContext setUser(_MatrixID user) {
+ this.user = user;
+ return this;
+ }
+
+ public MatrixClientContext setUserWithLocalpart(String localpart) {
+ setUser(MatrixID.asAcceptable(localpart, getDomain()));
+ return this;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public MatrixClientContext setToken(String token) {
+ this.token = token;
+ return this;
+ }
+
+ public boolean isVirtual() {
+ return isVirtual;
+ }
+
+ public MatrixClientContext setVirtual(boolean virtual) {
+ isVirtual = virtual;
+ return this;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public MatrixClientContext setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ public String getInitialDeviceName() {
+ return initialDeviceName;
+ }
+
+ public MatrixClientContext setInitialDeviceName(String initialDeviceName) {
+ this.initialDeviceName = initialDeviceName;
+ return this;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientDefaults.java b/src/main/java/io/kamax/matrix/client/MatrixClientDefaults.java
new file mode 100644
index 0000000..d245c65
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixClientDefaults.java
@@ -0,0 +1,59 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+public class MatrixClientDefaults {
+
+ private int connectTimeout = 30 * 1000; // 30 sec
+ private int requestTimeout = 5 * 60 * 1000; // 5 min
+ private int socketTimeout = requestTimeout;
+
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public MatrixClientDefaults setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+
+ return this;
+ }
+
+ public int getRequestTimeout() {
+ return requestTimeout;
+ }
+
+ public MatrixClientDefaults setRequestTimeout(int requestTimeout) {
+ this.requestTimeout = requestTimeout;
+
+ return this;
+ }
+
+ public int getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ public MatrixClientDefaults setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+
+ return this;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java b/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java
new file mode 100644
index 0000000..809ed72
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixClientRequestException.java
@@ -0,0 +1,46 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import io.kamax.matrix.MatrixErrorInfo;
+
+import java.io.IOException;
+import java.util.Optional;
+
+public class MatrixClientRequestException extends RuntimeException {
+
+ private MatrixErrorInfo errorInfo;
+
+ public MatrixClientRequestException(IOException e) {
+ super(e);
+ }
+
+ public MatrixClientRequestException(MatrixErrorInfo errorInfo, String message) {
+ super(message);
+
+ this.errorInfo = errorInfo;
+ }
+
+ public Optional getError() {
+ return Optional.ofNullable(errorInfo);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixClientRequestRateLimitedException.java b/src/main/java/io/kamax/matrix/client/MatrixClientRequestRateLimitedException.java
new file mode 100644
index 0000000..3383d7b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixClientRequestRateLimitedException.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import io.kamax.matrix.MatrixErrorInfo;
+
+public class MatrixClientRequestRateLimitedException extends MatrixClientRequestException {
+
+ public MatrixClientRequestRateLimitedException(MatrixErrorInfo errorInfo, String message) {
+ super(errorInfo, message);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java b/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java
new file mode 100644
index 0000000..f1e0321
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpContent.java
@@ -0,0 +1,133 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import io.kamax.matrix._MatrixContent;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Optional;
+
+
+import okhttp3.Request;
+
+public class MatrixHttpContent extends AMatrixHttpClient implements _MatrixContent {
+
+ private Logger log = LoggerFactory.getLogger(MatrixHttpContent.class);
+ private final Pattern filenamePattern = Pattern.compile("filename=\"?([^\";]+)");
+ private URI address;
+
+ private MatrixHttpContentResult result;
+
+ private boolean loaded = false;
+ private boolean valid = false;
+
+ public MatrixHttpContent(MatrixClientContext context, URI address) {
+ super(context);
+ this.address = address;
+ }
+
+ // TODO switch a HTTP HEAD to fetch initial data, instead of loading in memory directly
+ private synchronized void load() {
+ if (loaded) {
+ return;
+ }
+
+ try {
+ if (!StringUtils.equalsIgnoreCase("mxc", address.getScheme())) {
+ log.debug("{} is not a supported protocol for avatars, ignoring", address.getScheme());
+ } else {
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().url(getPermaLink()));
+ result = executeContentRequest(request);
+ valid = result.isValid();
+ }
+
+ } catch (MatrixClientRequestException e) {
+ valid = false;
+ }
+ loaded = true;
+ }
+
+ @Override
+ public URI getAddress() {
+ return address;
+ }
+
+ @Override
+ public URL getPermaLink() {
+ return getMediaPathBuilder("download", address.getHost()).addEncodedPathSegments(address.getPath().substring(1))
+ .build().url();
+ }
+
+ @Override
+ public boolean isValid() {
+ load();
+
+ return valid;
+ }
+
+ @Override
+ public Optional getType() {
+ load();
+
+ if (!isValid()) {
+ throw new IllegalStateException("This method should only be called, if valid is true.");
+ }
+ return result.getContentType();
+ }
+
+ @Override
+ public byte[] getData() {
+ load();
+
+ if (!isValid()) {
+ throw new IllegalStateException("This method should only be called, if valid is true.");
+ }
+ return result.getData();
+ }
+
+ @Override
+ public Optional getFilename() {
+ load();
+
+ if (!isValid()) {
+ throw new IllegalStateException("This method should only be called, if valid is true.");
+ }
+
+ return result.getHeader("Content-Disposition").filter(l -> !l.isEmpty()).flatMap(l -> {
+ for (String v : l) {
+ Matcher m = filenamePattern.matcher(v);
+ if (m.find()) {
+ return Optional.of(m.group(1));
+ }
+ }
+
+ return Optional.empty();
+ });
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java b/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java
new file mode 100644
index 0000000..70b831f
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpContentResult.java
@@ -0,0 +1,71 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.Optional;
+
+
+import okhttp3.MediaType;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+public class MatrixHttpContentResult {
+
+ private final boolean valid;
+ private final Map> headers;
+ private final Optional contentType;
+ private final byte[] data;
+
+ public MatrixHttpContentResult(Response response) throws IOException {
+ try (ResponseBody body = response.body()) {
+ boolean hasBody = Objects.nonNull(body);
+ valid = hasBody && response.code() == 200;
+ headers = response.headers().toMultimap();
+
+ if (hasBody) {
+ contentType = Optional.ofNullable(body.contentType()).map(MediaType::toString);
+ data = body.bytes();
+ } else {
+ contentType = Optional.empty();
+ data = new byte[0];
+ }
+ }
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public Optional> getHeader(String name) {
+ return Optional.ofNullable(headers.get(name));
+ }
+
+ public Optional getContentType() {
+ return contentType;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpPushRule.java b/src/main/java/io/kamax/matrix/client/MatrixHttpPushRule.java
new file mode 100644
index 0000000..a582edc
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpPushRule.java
@@ -0,0 +1,93 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.json.GsonUtil;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.net.URL;
+import java.util.List;
+
+import javax.swing.*;
+
+public class MatrixHttpPushRule extends AMatrixHttpClient implements _PushRule {
+
+ private static final String ActionKey = "actions";
+ private static final String EnabledKey = "enabled";
+
+ private final String[] baseSegments;
+
+ public MatrixHttpPushRule(MatrixClientContext context, String scope, String kind, String id) {
+ super(context);
+ baseSegments = new String[] { "pushrules", scope, kind, id };
+ }
+
+ private URL makeUrl() {
+ return getClientPath(baseSegments);
+ }
+
+ private URL makeUrl(String... segments) {
+ return getClientPath(ArrayUtils.addAll(baseSegments, segments));
+ }
+
+ @Override
+ public JsonObject getJson() {
+ return GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl())));
+ }
+
+ @Override
+ public void set(JsonObject data) {
+ executeAuthenticated(request(makeUrl()).put(getJsonBody(data)));
+ }
+
+ @Override
+ public void delete() {
+ executeAuthenticated(request(makeUrl()).delete());
+ }
+
+ @Override
+ public boolean isEnabled() {
+ JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(EnabledKey))));
+ return GsonUtil.getPrimitive(response, EnabledKey).getAsBoolean();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ executeAuthenticated(request(makeUrl(EnabledKey)).put(getJsonBody(GsonUtil.makeObj(EnabledKey, enabled))));
+ }
+
+ @Override
+ public List getActions() {
+ JsonObject response = GsonUtil.parseObj(executeAuthenticated(getRequest(makeUrl(ActionKey))));
+ return GsonUtil.asList(GsonUtil.findArray(response, ActionKey).orElseGet(JsonArray::new), String.class);
+ }
+
+ @Override
+ public void setActions(List data) {
+ executeAuthenticated(
+ request(makeUrl(ActionKey)).put(getJsonBody(GsonUtil.makeObj(ActionKey, GsonUtil.asArray(data)))));
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java b/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java
new file mode 100644
index 0000000..0471c94
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpRequest.java
@@ -0,0 +1,50 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import okhttp3.Request;
+
+public class MatrixHttpRequest {
+ private final Request.Builder httpRequest;
+ private List ignoredErrorCodes = new ArrayList<>();
+
+ public MatrixHttpRequest(Request.Builder request) {
+ this.httpRequest = request;
+ }
+
+ public MatrixHttpRequest addIgnoredErrorCode(int errcode) {
+ ignoredErrorCodes.add(errcode);
+ return this;
+ }
+
+ public Request.Builder getHttpRequest() {
+ return httpRequest;
+ }
+
+ public List getIgnoredErrorCodes() {
+ return ignoredErrorCodes;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java b/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java
new file mode 100644
index 0000000..b6bc122
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpRoom.java
@@ -0,0 +1,440 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixErrorInfo;
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixContent;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix._MatrixUserProfile;
+import io.kamax.matrix.hs._MatrixRoom;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.RoomMessageChunkResponseJson;
+import io.kamax.matrix.json.RoomMessageFormattedTextPutBody;
+import io.kamax.matrix.json.RoomMessageTextPutBody;
+import io.kamax.matrix.json.RoomTagSetBody;
+import io.kamax.matrix.json.event.MatrixJsonPersistentEvent;
+import io.kamax.matrix.room.*;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+
+public class MatrixHttpRoom extends AMatrixHttpClient implements _MatrixRoom {
+
+ private Logger log = LoggerFactory.getLogger(MatrixHttpRoom.class);
+
+ private String roomId;
+
+ public MatrixHttpRoom(MatrixClientContext context, String roomId) {
+ super(context);
+ this.roomId = roomId;
+ }
+
+ @Override
+ public String getAddress() {
+ return roomId;
+ }
+
+ @Override
+ public Optional getName() {
+ return getState("m.room.name").flatMap(obj -> GsonUtil.findString(obj, "name"));
+ }
+
+ @Override
+ public Optional getTopic() {
+ return getState("m.room.topic").flatMap(obj -> GsonUtil.findString(obj, "topic"));
+ }
+
+ @Override
+ public Optional getAvatarUrl() {
+ return getState("m.room.avatar").flatMap(obj -> GsonUtil.findString(obj, "url"));
+ }
+
+ @Override
+ public Optional<_MatrixContent> getAvatar() {
+ return getAvatarUrl().flatMap(url -> {
+ try {
+ return Optional.of(new MatrixHttpContent(context, new URI(url)));
+ } catch (URISyntaxException e) {
+ log.debug("{} is not a valid URI for avatar, returning empty", url);
+ return Optional.empty();
+ }
+ });
+ }
+
+ @Override
+ public String getId() {
+ return roomId;
+ }
+
+ @Override
+ public Optional getState(String type) {
+ URL path = getClientPath("rooms", getAddress(), "state", type);
+
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
+ request.addIgnoredErrorCode(404);
+ String body = executeAuthenticated(request);
+ if (StringUtils.isBlank(body)) {
+ return Optional.empty();
+ }
+
+ return Optional.of(GsonUtil.parseObj(body));
+ }
+
+ @Override
+ public Optional getState(String type, String key) {
+ URL path = getClientPath("rooms", roomId, "state", type, key);
+
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
+ request.addIgnoredErrorCode(404);
+ String body = executeAuthenticated(request);
+ if (StringUtils.isBlank(body)) {
+ return Optional.empty();
+ }
+
+ return Optional.of(GsonUtil.parseObj(body));
+ }
+
+ @Override
+ public void join() {
+ join(Collections.emptyList());
+ }
+
+ @Override
+ public void join(List servers) {
+ HttpUrl.Builder b = getClientPathBuilder("rooms", roomId, "join");
+ servers.forEach(server -> b.addQueryParameter("server_name", server));
+ executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(b.build()));
+ }
+
+ @Override
+ public Optional tryJoin() {
+ return tryJoin(Collections.emptyList());
+ }
+
+ @Override
+ public Optional tryJoin(List servers) {
+ try {
+ join(servers);
+ return Optional.empty();
+ } catch (MatrixClientRequestException e) {
+ return e.getError();
+ }
+ }
+
+ @Override
+ public void leave() {
+ URL path = getClientPath("rooms", roomId, "leave");
+ MatrixHttpRequest request = new MatrixHttpRequest(
+ new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
+
+ // TODO Find a better way to handle room objects for unknown rooms
+ // Maybe throw exception?
+ // TODO implement method to check room existence - isValid() ?
+ // if (res.getStatusLine().getStatusCode() == 404) {
+ // log.warn("Room {} is not joined, ignoring call", roomId);
+ // return;
+ // }
+ request.addIgnoredErrorCode(404);
+ executeAuthenticated(request);
+ }
+
+ @Override
+ public Optional tryLeave() {
+ try {
+ leave();
+ return Optional.empty();
+ } catch (MatrixClientRequestException e) {
+ return e.getError();
+ }
+ }
+
+ @Override
+ public void kick(_MatrixID user) {
+ kick(user, null);
+ }
+
+ @Override
+ public void kick(_MatrixID user, String reason) {
+ JsonObject body = new JsonObject();
+ body.addProperty("user_id", user.getId());
+ body.addProperty("reason", reason);
+ URL path = getClientPath("rooms", roomId, "kick");
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().post(getJsonBody(body)).url(path));
+ executeAuthenticated(request);
+ }
+
+ @Override
+ public Optional tryKick(_MatrixID user) {
+ return tryKick(user, null);
+ }
+
+ @Override
+ public Optional tryKick(_MatrixID user, String reason) {
+ try {
+ kick(user, reason);
+ return Optional.empty();
+ } catch (MatrixClientRequestException e) {
+ return e.getError();
+ }
+ }
+
+ @Override
+ public String sendEvent(String type, JsonObject content) {
+ // FIXME URL encoding
+ URL path = getClientPath("rooms", roomId, "send", type, Long.toString(System.currentTimeMillis()));
+ String body = executeAuthenticated(new Request.Builder().put(getJsonBody(content)).url(path));
+ return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "event_id");
+ }
+
+ private String sendMessage(RoomMessageTextPutBody content) {
+ return sendEvent("m.room.message", GsonUtil.makeObj(content));
+ }
+
+ @Override
+ public String sendText(String message) {
+ return sendMessage(new RoomMessageTextPutBody(message));
+ }
+
+ @Override
+ public String sendFormattedText(String formatted, String rawFallback) {
+ // TODO sanitize input
+ return sendMessage(new RoomMessageFormattedTextPutBody(rawFallback, formatted));
+ }
+
+ @Override
+ public String sendNotice(String message) {
+ return sendMessage(new RoomMessageTextPutBody("m.notice", message));
+ }
+
+ @Override
+ public String sendNotice(String formatted, String plain) {
+ // TODO sanitize input
+ return sendMessage(new RoomMessageFormattedTextPutBody("m.notice", plain, formatted));
+ }
+
+ @Override
+ public void sendReceipt(String type, String eventId) {
+ URL path = getClientPath("rooms", roomId, "receipt", type, eventId);
+ executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
+ }
+
+ @Override
+ public void sendReceipt(ReceiptType type, String eventId) {
+ sendReceipt(type.getId(), eventId);
+ }
+
+ @Override
+ public void sendReadReceipt(String eventId) {
+ sendReceipt(ReceiptType.Read, eventId);
+ }
+
+ @Override
+ public void invite(_MatrixID mxId) {
+ URL path = getClientPath("rooms", roomId, "invite");
+ executeAuthenticated(
+ new Request.Builder().post(getJsonBody(GsonUtil.makeObj("user_id", mxId.getId()))).url(path));
+ }
+
+ @Override
+ public List<_MatrixUserProfile> getJoinedUsers() {
+ URL path = getClientPath("rooms", roomId, "joined_members");
+ String body = executeAuthenticated(new Request.Builder().get().url(path));
+
+ List<_MatrixUserProfile> ids = new ArrayList<>();
+ if (StringUtils.isNotEmpty(body)) {
+ JsonObject joinedUsers = jsonParser.parse(body).getAsJsonObject().get("joined").getAsJsonObject();
+ ids = joinedUsers.entrySet().stream().filter(e -> e.getValue().isJsonObject()).map(entry -> {
+ JsonObject obj = entry.getValue().getAsJsonObject();
+ return new MatrixHttpUser(getContext(), MatrixID.asAcceptable(entry.getKey())) {
+
+ @Override
+ public Optional getName() {
+ return GsonUtil.findString(obj, "display_name");
+ }
+
+ @Override
+ public Optional<_MatrixContent> getAvatar() {
+ return GsonUtil.findString(obj, "avatar_url").flatMap(s -> {
+ try {
+ return Optional.of(new URI(s));
+ } catch (URISyntaxException e) {
+ return Optional.empty();
+ }
+ }).map(uri -> new MatrixHttpContent(getContext(), uri));
+ }
+
+ };
+ }).collect(Collectors.toList());
+ }
+
+ return ids;
+ }
+
+ @Override
+ public _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options) {
+ HttpUrl.Builder builder = getClientPathBuilder("rooms", roomId, "messages");
+ builder.addQueryParameter("from", options.getFromToken());
+ builder.addQueryParameter("dir", options.getDirection());
+ options.getToToken().ifPresent(token -> builder.addQueryParameter("to", token));
+ options.getLimit().ifPresent(limit -> builder.addQueryParameter("limit", limit.toString()));
+
+ String bodyRaw = executeAuthenticated(new Request.Builder().get().url(builder.build().url()));
+ RoomMessageChunkResponseJson body = GsonUtil.get().fromJson(bodyRaw, RoomMessageChunkResponseJson.class);
+ return new MatrixRoomMessageChunk(body.getStart(), body.getEnd(),
+ body.getChunk().stream().map(MatrixJsonPersistentEvent::new).collect(Collectors.toList()));
+ }
+
+ @Override
+ public List getUserTags() {
+ return getAllTags().stream().filter(tag -> "u".equals(tag.getNamespace()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List getAllTags() {
+
+ URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags");
+
+ String body = executeAuthenticated(new Request.Builder().get().url(path));
+
+ JsonObject jsonTags = GsonUtil.parseObj(body).getAsJsonObject("tags").getAsJsonObject();
+ List tags = jsonTags.entrySet().stream().map(entry -> {
+ String completeName = entry.getKey();
+ String name = "";
+ String namespace = "";
+ if (completeName.startsWith("m.")) {
+ name = completeName.substring(2);
+ namespace = "m";
+ } else if (completeName.startsWith("u.")) {
+ name = completeName.substring(2);
+ namespace = "u";
+ } else {
+ name = completeName;
+ }
+ JsonElement jsonOrder = entry.getValue().getAsJsonObject().get("order");
+ Double order = null;
+ if (jsonOrder != null) {
+ order = jsonOrder.getAsDouble();
+ }
+
+ return new Tag(namespace, name, order);
+ }).collect(Collectors.toList());
+
+ return tags;
+ }
+
+ @Override
+ public void addUserTag(String tag) {
+ addTag("u." + tag, null);
+ }
+
+ @Override
+ public void addUserTag(String tag, double order) {
+ addTag("u." + tag, order);
+ }
+
+ @Override
+ public void deleteUserTag(String tag) {
+ deleteTag("u." + tag);
+ }
+
+ @Override
+ public void addFavouriteTag() {
+ addTag("m.favourite", null);
+ }
+
+ @Override
+ public void addFavouriteTag(double order) {
+ addTag("m.favourite", order);
+ }
+
+ @Override
+ public Optional getFavouriteTag() {
+ return getAllTags().stream()
+ .filter(tag -> "m".equals(tag.getNamespace()) && "favourite".equals(tag.getName())).findFirst();
+ }
+
+ @Override
+ public void deleteFavouriteTag() {
+ deleteTag("m.favourite");
+ }
+
+ @Override
+ public void addLowpriorityTag() {
+ addTag("m.lowpriority", null);
+ }
+
+ @Override
+ public void addLowpriorityTag(double order) {
+ addTag("m.lowpriority", order);
+ }
+
+ @Override
+ public Optional getLowpriorityTag() {
+ return getAllTags().stream()
+ .filter(tag -> "m".equals(tag.getNamespace()) && "lowpriority".equals(tag.getName())).findFirst();
+ }
+
+ @Override
+ public void deleteLowpriorityTag() {
+ deleteTag("m.lowpriority");
+ }
+
+ private void addTag(String tag, Double order) {
+ // TODO check name size
+
+ if (order != null && (order < 0 || order > 1)) {
+ throw new IllegalArgumentException("Order out of range!");
+ }
+
+ URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
+ Request.Builder request = new Request.Builder().url(path);
+ if (order != null) {
+ request.put(getJsonBody(new RoomTagSetBody(order)));
+ } else {
+ request.put(getJsonBody(new JsonObject()));
+ }
+ executeAuthenticated(request);
+ }
+
+ private void deleteTag(String tag) {
+ URL path = getClientPath("user", getUserId(), "rooms", getAddress(), "tags", tag);
+ executeAuthenticated(new Request.Builder().url(path).delete());
+ }
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java b/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java
new file mode 100644
index 0000000..4cab076
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixHttpUser.java
@@ -0,0 +1,125 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix._MatrixContent;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix._MatrixUser;
+import io.kamax.matrix.client.regular.Presence;
+import io.kamax.matrix.json.GsonUtil;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Optional;
+
+
+import okhttp3.Request;
+
+public class MatrixHttpUser extends AMatrixHttpClient implements _MatrixUser {
+
+ private Logger log = LoggerFactory.getLogger(MatrixHttpUser.class);
+
+ private _MatrixID mxId;
+
+ public MatrixHttpUser(MatrixClientContext context, _MatrixID mxId) {
+ super(context);
+
+ this.mxId = mxId;
+ }
+
+ @Override
+ public _MatrixID getId() {
+ return mxId;
+ }
+
+ @Override
+ public Optional getName() {
+ URL path = getClientPath("profile", mxId.getId(), "displayname");
+
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
+ request.addIgnoredErrorCode(404);
+ String body = executeAuthenticated(request);
+ return extractAsStringFromBody(body, "displayname");
+ }
+
+ @Override
+ public void setName(String name) {
+ URL path = getClientPath("profile", mxId.getId(), "displayname");
+ JsonObject body = GsonUtil.makeObj("displayname", name);
+ executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
+ }
+
+ @Override
+ public Optional getAvatarUrl() {
+ URL path = getClientPath("profile", mxId.getId(), "avatar_url");
+
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
+ request.addIgnoredErrorCode(404);
+ String body = executeAuthenticated(request);
+ return extractAsStringFromBody(body, "avatar_url");
+ }
+
+ @Override
+ public void setAvatar(String avatarRef) {
+ URL path = getClientPath("profile", mxId.getId(), "avatar_url");
+ JsonObject body = GsonUtil.makeObj("avatar_url", avatarRef);
+ executeAuthenticated(new Request.Builder().put(getJsonBody(body)).url(path));
+ }
+
+ @Override
+ public void setAvatar(URI avatarUri) {
+ setAvatar(avatarUri.toString());
+ }
+
+ @Override
+ public Optional<_MatrixContent> getAvatar() {
+ return getAvatarUrl().flatMap(uri -> {
+ try {
+ return Optional.of(new MatrixHttpContent(getContext(), new URI(uri)));
+ } catch (URISyntaxException e) {
+ log.debug("{} is not a valid URI for avatar, returning empty", uri);
+ return Optional.empty();
+ }
+ });
+ }
+
+ @Override
+ public Optional<_Presence> getPresence() {
+ URL path = getClientPath("presence", mxId.getId(), "status");
+
+ MatrixHttpRequest request = new MatrixHttpRequest(new Request.Builder().get().url(path));
+ request.addIgnoredErrorCode(404);
+ String body = execute(request);
+ if (StringUtils.isBlank(body)) {
+ return Optional.empty();
+ }
+
+ return Optional.of(new Presence(GsonUtil.parseObj(body)));
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/MatrixPasswordCredentials.java b/src/main/java/io/kamax/matrix/client/MatrixPasswordCredentials.java
new file mode 100644
index 0000000..51016c6
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/MatrixPasswordCredentials.java
@@ -0,0 +1,39 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+public class MatrixPasswordCredentials {
+ private final String localPart;
+ private final String password;
+
+ public MatrixPasswordCredentials(String localPart, String password) {
+ this.localPart = localPart;
+ this.password = password;
+ }
+
+ public String getLocalPart() {
+ return localPart;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/main/java/io/kamax/matrix/client/PresenceStatus.java b/src/main/java/io/kamax/matrix/client/PresenceStatus.java
new file mode 100644
index 0000000..472fe59
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/PresenceStatus.java
@@ -0,0 +1,45 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import org.apache.commons.lang3.StringUtils;
+
+public enum PresenceStatus {
+
+ Online("online"),
+ Offline("offline"),
+ Unavailable("unavailable");
+
+ private String id;
+
+ PresenceStatus(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public boolean is(String status) {
+ return StringUtils.equals(id, status);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java b/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java
new file mode 100644
index 0000000..b056cbd
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/WellKnownAutoDiscoverySettings.java
@@ -0,0 +1,138 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.InvalidJsonException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class WellKnownAutoDiscoverySettings implements _AutoDiscoverySettings {
+
+ private final Logger log = LoggerFactory.getLogger(WellKnownAutoDiscoverySettings.class);
+
+ private JsonObject raw;
+
+ private List hsBaseUrls = new ArrayList<>();
+ private List isBaseUrls = new ArrayList<>();
+
+ /**
+ * Build .well-known auto-discovery settings from a .well-known source.
+ *
+ * @param raw
+ * The raw JSON data
+ * @throws IllegalArgumentException
+ * if the data is invalid and couldn't be parsed.
+ */
+ public WellKnownAutoDiscoverySettings(String raw) {
+ try {
+ setRaw(GsonUtil.parseObj(raw));
+ } catch (JsonParseException | InvalidJsonException e) {
+ throw new IllegalArgumentException("Invalid JSON data for .well-known string");
+ }
+ }
+
+ private void setRaw(JsonObject raw) {
+ this.raw = raw;
+ process();
+ }
+
+ private Optional getUrl(String url) {
+ try {
+ return Optional.of(new URL(url));
+ } catch (MalformedURLException e) {
+ log.warn("Ignoring invalid Base URL entry in well-known: {} - {}", url, e.getMessage());
+ return Optional.empty();
+ }
+ }
+
+ private List getUrls(JsonArray array) {
+ List urls = new ArrayList<>();
+
+ array.forEach(el -> {
+ if (!el.isJsonPrimitive()) {
+ log.warn("Ignoring invalid Base URL entry in well-known: {} - Not a string", GsonUtil.get().toJson(el));
+ return;
+ }
+
+ getUrl(el.getAsString()).ifPresent(urls::add);
+ });
+
+ return urls;
+ }
+
+ private List processUrls(JsonObject base, String key) {
+ List urls = new ArrayList<>();
+
+ GsonUtil.findObj(base, key).ifPresent(cfg -> {
+ log.info("Found data");
+
+ GsonUtil.findArray(cfg, "base_urls").ifPresent(arr -> {
+ log.info("Found base URL(s)");
+ urls.addAll(getUrls(arr));
+ });
+
+ if (urls.isEmpty()) {
+ GsonUtil.findString(cfg, "base_url").flatMap(this::getUrl).ifPresent(urls::add);
+ }
+ });
+
+ return urls;
+ }
+
+ private void process() {
+ log.info("Processing Homeserver Base URLs");
+ hsBaseUrls = processUrls(raw, "m.homeserver");
+ log.info("Found {} valid URL(s)", hsBaseUrls.size());
+
+ log.info("Processing Identity server Base URLs");
+ isBaseUrls = processUrls(raw, "m.identity_server");
+ log.info("Found {} valid URL(s)", isBaseUrls.size());
+ }
+
+ @Override
+ public JsonObject getRaw() {
+ return raw;
+ }
+
+ @Override
+ public List getHsBaseUrls() {
+ return Collections.unmodifiableList(hsBaseUrls);
+ }
+
+ @Override
+ public List getIsBaseUrls() {
+ return Collections.unmodifiableList(isBaseUrls);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java b/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java
new file mode 100644
index 0000000..b7e16c4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_AutoDiscoverySettings.java
@@ -0,0 +1,36 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import java.net.URL;
+import java.util.List;
+
+public interface _AutoDiscoverySettings {
+
+ JsonObject getRaw();
+
+ List getHsBaseUrls();
+
+ List getIsBaseUrls();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_GlobalPushRulesSet.java b/src/main/java/io/kamax/matrix/client/_GlobalPushRulesSet.java
new file mode 100644
index 0000000..def5da8
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_GlobalPushRulesSet.java
@@ -0,0 +1,39 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import java.util.List;
+
+public interface _GlobalPushRulesSet {
+
+ List getContent();
+
+ List getOverride();
+
+ List getRoom();
+
+ List getSender();
+
+ List getUnderride();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_MatrixClient.java b/src/main/java/io/kamax/matrix/client/_MatrixClient.java
new file mode 100644
index 0000000..19d1554
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_MatrixClient.java
@@ -0,0 +1,158 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix._MatrixContent;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix._MatrixUser;
+import io.kamax.matrix.hs._MatrixRoom;
+import io.kamax.matrix.room.RoomAlias;
+import io.kamax.matrix.room._RoomAliasLookup;
+import io.kamax.matrix.room._RoomCreationOptions;
+
+import java.io.File;
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+
+public interface _MatrixClient extends _MatrixClientRaw {
+
+ _MatrixID getWhoAmI();
+
+ void setDisplayName(String name);
+
+ _RoomAliasLookup lookup(RoomAlias alias);
+
+ _MatrixRoom createRoom(_RoomCreationOptions options);
+
+ _MatrixRoom getRoom(String roomId);
+
+ List<_MatrixRoom> getJoinedRooms();
+
+ _MatrixRoom joinRoom(String roomIdOrAlias);
+
+ _MatrixUser getUser(_MatrixID mxId);
+
+ Optional getDeviceId();
+
+ /* Custom endpoint! */
+ // TODO refactor into custom synapse class?
+ void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin);
+
+ /***
+ * Set the access token to use for any authenticated API calls.
+ *
+ * @param accessToken
+ * The access token provided by the server which must be valid
+ * @throws MatrixClientRequestException
+ * If an error occurred while checking for the identity behind the access token
+ */
+ void setAccessToken(String accessToken) throws MatrixClientRequestException;
+
+ void login(MatrixPasswordCredentials credentials);
+
+ void logout();
+
+ _SyncData sync(_SyncOptions options);
+
+ /**
+ * Download content from the media repository
+ *
+ * @param mxUri
+ * The MXC URI for the content to download
+ * @return The content
+ * @throws IllegalArgumentException
+ * if the parameter is not a valid MXC URI
+ */
+ _MatrixContent getMedia(String mxUri) throws IllegalArgumentException;
+
+ /**
+ * Download content from the media repository
+ *
+ * @param mxUri
+ * The MXC URI for the content to download
+ * @return The content
+ * @throws IllegalArgumentException
+ * if the parameter is not a valid MXC URI
+ */
+ _MatrixContent getMedia(URI mxUri) throws IllegalArgumentException;
+
+ /**
+ * Upload content to the media repository
+ *
+ * @param data
+ * The data to send
+ * @param type
+ * The mime-type of the content upload
+ * @return The MXC URI for the uploaded content
+ */
+ String putMedia(byte[] data, String type);
+
+ /**
+ * Upload content to the media repository
+ *
+ * @param data
+ * The data to send
+ * @param type
+ * The mime-type of the content upload
+ * @param filename
+ * A suggested filename for the content
+ * @return The MXC URI for the uploaded content
+ */
+ String putMedia(byte[] data, String type, String filename);
+
+ /**
+ * Upload content to the media repository
+ *
+ * @param data
+ * The file to read the data from
+ * @param type
+ * The mime-type of the content upload
+ * @return The MXC URI for the uploaded content
+ */
+ String putMedia(File data, String type);
+
+ /**
+ * Upload content to the media repository
+ *
+ * @param data
+ * The data to send
+ * @param type
+ * The mime-type of the content upload
+ * @param filename
+ * A suggested filename for the content
+ * @return The MXC URI for the uploaded content
+ */
+ String putMedia(File data, String type, String filename);
+
+ List getPushers();
+
+ void setPusher(JsonObject pusher);
+
+ void deletePusher(String pushKey);
+
+ _GlobalPushRulesSet getPushRules();
+
+ _PushRule getPushRule(String scope, String kind, String id);
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java b/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java
new file mode 100644
index 0000000..145f052
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_MatrixClientRaw.java
@@ -0,0 +1,51 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.hs._MatrixHomeserver;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface _MatrixClientRaw {
+
+ MatrixClientContext getContext();
+
+ _MatrixHomeserver getHomeserver();
+
+ Optional getAccessToken();
+
+ Optional<_MatrixID> getUser();
+
+ Optional<_AutoDiscoverySettings> discoverSettings();
+
+ // FIXME
+ // we should maybe have a dedicated object for HS related items and be merged into getHomeserver() which is only
+ // holding state at this point and is not functional
+ List getHomeApiVersions();
+
+ // FIXME
+ // we should maybe have a dedicated object for IS related items. Will reconsider when implementing
+ // other part of the IS API
+ boolean validateIsBaseUrl();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_Presence.java b/src/main/java/io/kamax/matrix/client/_Presence.java
new file mode 100644
index 0000000..ce9e818
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_Presence.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+public interface _Presence {
+
+ String getStatus();
+
+ Long getLastActive();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_PushRule.java b/src/main/java/io/kamax/matrix/client/_PushRule.java
new file mode 100644
index 0000000..227fa58
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_PushRule.java
@@ -0,0 +1,43 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import java.util.List;
+
+public interface _PushRule {
+
+ JsonObject getJson();
+
+ void set(JsonObject data);
+
+ void delete();
+
+ boolean isEnabled();
+
+ void setEnabled(boolean enabled);
+
+ List getActions();
+
+ void setActions(List data);
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_SyncData.java b/src/main/java/io/kamax/matrix/client/_SyncData.java
new file mode 100644
index 0000000..0a59222
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_SyncData.java
@@ -0,0 +1,253 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._MatrixAccountDataEvent;
+import io.kamax.matrix.event._MatrixEphemeralEvent;
+import io.kamax.matrix.event._MatrixPersistentEvent;
+import io.kamax.matrix.event._MatrixStateEvent;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Representation of the data when performing a sync call on the Matrix Client API.
+ */
+public interface _SyncData {
+
+ interface State {
+
+ /**
+ * The state of the room.
+ *
+ * @return a list of state events.
+ */
+ List<_MatrixStateEvent> getEvents();
+
+ }
+
+ interface Timeline {
+
+ /**
+ * Events that happened in the sync window.
+ *
+ * @return List of events.
+ */
+ List<_MatrixPersistentEvent> getEvents();
+
+ /**
+ * If the number of events returned was limited by the sync filter.
+ *
+ * @return true if the number of events was limited, false if not.
+ */
+ boolean isLimited();
+
+ /**
+ * Token that can be supplied to fetch previous events for the associated room.
+ *
+ * @return the token.
+ */
+ String getPreviousBatchToken();
+ }
+
+ interface Ephemeral {
+
+ /**
+ * Events that happened in the sync window.
+ *
+ * @return List of events.
+ */
+ List<_MatrixEphemeralEvent> getEvents();
+ }
+
+ interface AccountData {
+
+ /**
+ * Events that happened in the sync window.
+ *
+ * @return List of events.
+ */
+ List<_MatrixAccountDataEvent> getEvents();
+ }
+
+ interface InvitedRoom {
+
+ /**
+ * The ID of the room the user was invited to.
+ *
+ * @return the room ID.
+ */
+ String getId();
+
+ /**
+ * The state of the room at the invite event.
+ *
+ * @return a list of state events.
+ */
+ State getState();
+
+ }
+
+ interface UnreadNotifications {
+
+ /**
+ * The number of unread notifications with the highlight flag set.
+ *
+ * @return the count.
+ */
+ long getHighlightCount();
+
+ /**
+ * The total number of unread notifications.
+ *
+ * @return the count.
+ */
+ long getNotificationCount();
+
+ }
+
+ interface JoinedRoom {
+
+ /**
+ * The ID of the room the user is joined to.
+ *
+ * @return the room id.
+ */
+ String getId();
+
+ /**
+ * State changes prior the start of the timeline.
+ *
+ * @return a list of state events.
+ */
+ State getState();
+
+ /**
+ * The room timeline for this sync batch.
+ *
+ * @return the timeline.
+ */
+ Timeline getTimeline();
+
+ /**
+ * Ephemeral events of the room.
+ *
+ * @return a list of ephemeral events.
+ */
+ Ephemeral getEphemeral();
+
+ /**
+ * Account events of the room.
+ *
+ * @return a list of account data events.
+ */
+ AccountData getAccountData();
+
+ /**
+ * The Counts of unread notifications.
+ *
+ * @return unread notifications.
+ */
+ UnreadNotifications getUnreadNotifications();
+
+ }
+
+ interface LeftRoom {
+
+ /**
+ * The ID of the room the user is joined to.
+ *
+ * @return the room id.
+ */
+ String getId();
+
+ /**
+ * State changes prior the start of the timeline.
+ *
+ * @return a list of state events.
+ */
+ State getState();
+
+ /**
+ * The room timeline up to the leave event.
+ *
+ * @return the timeline.
+ */
+ Timeline getTimeline();
+
+ }
+
+ interface Rooms {
+
+ /**
+ * Rooms the user was invited to within this sync window.
+ *
+ * @return Set of InvitedRoom objects.
+ */
+ Set getInvited();
+
+ /**
+ * Rooms the user was joined in within this sync window.
+ *
+ * @return Set of JoinedRoom objects.
+ */
+ Set getJoined();
+
+ /**
+ * Rooms the user left from within this sync window.
+ *
+ * @return Set of LeftRoom objects.
+ */
+ Set getLeft();
+
+ }
+
+ /**
+ * The batch token to supply in the next sync call.
+ *
+ * @return the batch token.
+ */
+ String nextBatchToken();
+
+ /**
+ * The global private data created by this user.
+ *
+ * @return the account data.
+ */
+ AccountData getAccountData();
+
+ /**
+ * Update to the rooms.
+ *
+ * @return rooms object.
+ */
+ Rooms getRooms();
+
+ /**
+ * The raw JSON data for this object.
+ *
+ * @return the JSON data.
+ */
+ JsonObject getJson();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/_SyncOptions.java b/src/main/java/io/kamax/matrix/client/_SyncOptions.java
new file mode 100644
index 0000000..7d63d92
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/_SyncOptions.java
@@ -0,0 +1,65 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client;
+
+import java.util.Optional;
+
+/**
+ * Possible options that can be passed to the sync call.
+ */
+public interface _SyncOptions {
+
+ /**
+ * The point of time to continue the sync from.
+ *
+ * @return A token that was provided in a previous sync call, if set.
+ */
+ Optional getSince();
+
+ /**
+ * The filter to use for the sync.
+ *
+ * @return The ID or raw JSON filter, if set.
+ */
+ Optional getFilter();
+
+ /**
+ * If the full state should be included in the sync.
+ *
+ * @return The full state option, if set.
+ */
+ Optional withFullState();
+
+ /**
+ * If the client should automatically be marked as online.
+ *
+ * @return The set presence option, if set.
+ */
+ Optional getSetPresence();
+
+ /**
+ * The maximum time to wait, in milliseconds, before ending the sync call.
+ *
+ * @return The timeout option, if set.
+ */
+ Optional getTimeout();
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java b/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java
new file mode 100644
index 0000000..75765cf
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/as/MatrixApplicationServiceClient.java
@@ -0,0 +1,87 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.as;
+
+import io.kamax.matrix.client.MatrixClientContext;
+import io.kamax.matrix.client.MatrixClientDefaults;
+import io.kamax.matrix.client._MatrixClient;
+import io.kamax.matrix.client.regular.MatrixHttpClient;
+import io.kamax.matrix.json.VirtualUserRegistrationBody;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+public class MatrixApplicationServiceClient extends MatrixHttpClient implements _MatrixApplicationServiceClient {
+
+ private Logger log = LoggerFactory.getLogger(MatrixApplicationServiceClient.class);
+
+ public MatrixApplicationServiceClient(String domain) {
+ super(domain);
+ }
+
+ public MatrixApplicationServiceClient(URL hsBaseUrl) {
+ super(hsBaseUrl);
+ }
+
+ public MatrixApplicationServiceClient(MatrixClientContext context) {
+ super(context);
+ }
+
+ public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client) {
+ super(context, client);
+ }
+
+ public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient.Builder client,
+ MatrixClientDefaults defaults) {
+ super(context, client, defaults);
+ }
+
+ public MatrixApplicationServiceClient(MatrixClientContext context, OkHttpClient client) {
+ super(context, client);
+ }
+
+ private MatrixHttpClient createClient(String localpart) {
+ MatrixClientContext context = new MatrixClientContext(getContext()).setUserWithLocalpart(localpart)
+ .setVirtual(true);
+ return new MatrixHttpClient(context);
+ }
+
+ @Override
+ public _MatrixClient createUser(String localpart) {
+ log.debug("Creating new user {}", localpart);
+ URL path = getClientPath("register");
+ executeAuthenticated(
+ new Request.Builder().post(getJsonBody(new VirtualUserRegistrationBody(localpart))).url(path));
+ return createClient(localpart);
+ }
+
+ @Override
+ public _MatrixClient getUser(String localpart) {
+ return createClient(localpart);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java b/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java
new file mode 100644
index 0000000..6a770d2
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/as/_MatrixApplicationServiceClient.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.as;
+
+import io.kamax.matrix.client._MatrixClient;
+
+public interface _MatrixApplicationServiceClient extends _MatrixClient {
+
+ _MatrixClient createUser(String localpart);
+
+ _MatrixClient getUser(String localpart);
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/regular/GlobalPushRulesSet.java b/src/main/java/io/kamax/matrix/client/regular/GlobalPushRulesSet.java
new file mode 100644
index 0000000..c18b917
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/regular/GlobalPushRulesSet.java
@@ -0,0 +1,68 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.regular;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.client._GlobalPushRulesSet;
+import io.kamax.matrix.json.GsonUtil;
+
+import java.util.List;
+
+public class GlobalPushRulesSet implements _GlobalPushRulesSet {
+
+ private JsonObject data;
+
+ public GlobalPushRulesSet(JsonObject data) {
+ this.data = data;
+ }
+
+ private List getForKey(String key) {
+ return GsonUtil.asList(GsonUtil.findArray(data, key).orElseGet(JsonArray::new), JsonObject.class);
+ }
+
+ @Override
+ public List getContent() {
+ return getForKey("content");
+ }
+
+ @Override
+ public List getOverride() {
+ return getForKey("override");
+ }
+
+ @Override
+ public List getRoom() {
+ return getForKey("room");
+ }
+
+ @Override
+ public List getSender() {
+ return getForKey("sender");
+ }
+
+ @Override
+ public List getUnderride() {
+ return getForKey("underride");
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java b/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java
new file mode 100644
index 0000000..4cf19c3
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/regular/MatrixHttpClient.java
@@ -0,0 +1,292 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.regular;
+
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixContent;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix._MatrixUser;
+import io.kamax.matrix.client.*;
+import io.kamax.matrix.hs._MatrixRoom;
+import io.kamax.matrix.json.*;
+import io.kamax.matrix.room.RoomAlias;
+import io.kamax.matrix.room.RoomAliasLookup;
+import io.kamax.matrix.room._RoomAliasLookup;
+import io.kamax.matrix.room._RoomCreationOptions;
+
+import org.apache.commons.codec.digest.HmacAlgorithms;
+import org.apache.commons.codec.digest.HmacUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+
+import okhttp3.*;
+
+public class MatrixHttpClient extends AMatrixHttpClient implements _MatrixClient {
+
+ private Logger log = LoggerFactory.getLogger(MatrixHttpClient.class);
+
+ public MatrixHttpClient(String domain) {
+ super(domain);
+ }
+
+ public MatrixHttpClient(URL hsBaseUrl) {
+ super(hsBaseUrl);
+ }
+
+ public MatrixHttpClient(MatrixClientContext context) {
+ super(context);
+ }
+
+ public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client) {
+ super(context, client);
+ }
+
+ public MatrixHttpClient(MatrixClientContext context, OkHttpClient.Builder client, MatrixClientDefaults defaults) {
+ super(context, client, defaults);
+ }
+
+ public MatrixHttpClient(MatrixClientContext context, OkHttpClient client) {
+ super(context, client);
+ }
+
+ protected _MatrixID getIdentity(String token) {
+ URL path = getClientPath("account", "whoami");
+ String body = executeAuthenticated(new Request.Builder().get().url(path), token);
+ return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
+ }
+
+ @Override
+ public _MatrixID getWhoAmI() {
+ URL path = getClientPath("account", "whoami");
+ String body = executeAuthenticated(new Request.Builder().get().url(path));
+ return MatrixID.from(GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "user_id")).acceptable();
+ }
+
+ @Override
+ public void setDisplayName(String name) {
+ URL path = getClientPath("profile", getUserId(), "displayname");
+ execute(new Request.Builder().put(getJsonBody(new UserDisplaynameSetBody(name))).url(path));
+ }
+
+ @Override
+ public _RoomAliasLookup lookup(RoomAlias alias) {
+ URL path = getClientPath("directory", "room", alias.getId());
+ String resBody = execute(new Request.Builder().get().url(path));
+ RoomAliasLookupJson lookup = GsonUtil.get().fromJson(resBody, RoomAliasLookupJson.class);
+ return new RoomAliasLookup(lookup.getRoomId(), alias.getId(), lookup.getServers());
+ }
+
+ @Override
+ public _MatrixRoom createRoom(_RoomCreationOptions options) {
+ URL path = getClientPath("createRoom");
+ String resBody = executeAuthenticated(
+ new Request.Builder().post(getJsonBody(new RoomCreationRequestJson(options))).url(path));
+ String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
+ return getRoom(roomId);
+ }
+
+ @Override
+ public _MatrixRoom getRoom(String roomId) {
+ return new MatrixHttpRoom(getContext(), roomId);
+ }
+
+ @Override
+ public List<_MatrixRoom> getJoinedRooms() {
+ URL path = getClientPath("joined_rooms");
+ JsonObject resBody = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(path)));
+ return GsonUtil.asList(resBody, "joined_rooms", String.class).stream().map(this::getRoom)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public _MatrixRoom joinRoom(String roomIdOrAlias) {
+ URL path = getClientPath("join", roomIdOrAlias);
+ String resBody = executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
+ String roomId = GsonUtil.get().fromJson(resBody, RoomCreationResponseJson.class).getRoomId();
+ return getRoom(roomId);
+ }
+
+ @Override
+ public _MatrixUser getUser(_MatrixID mxId) {
+ return new MatrixHttpUser(getContext(), mxId);
+ }
+
+ @Override
+ public Optional getDeviceId() {
+ return Optional.ofNullable(context.getDeviceId());
+ }
+
+ protected void updateContext(String resBody) {
+ LoginResponse response = gson.fromJson(resBody, LoginResponse.class);
+ context.setToken(response.getAccessToken());
+ context.setDeviceId(response.getDeviceId());
+ context.setUser(MatrixID.asAcceptable(response.getUserId()));
+ }
+
+ @Override
+ public void register(MatrixPasswordCredentials credentials, String sharedSecret, boolean admin) {
+ // As per synapse registration script:
+ // https://github.com/matrix-org/synapse/blob/master/scripts/register_new_matrix_user#L28
+
+ String value = credentials.getLocalPart() + "\0" + credentials.getPassword() + "\0"
+ + (admin ? "admin" : "notadmin");
+ String mac = new HmacUtils(HmacAlgorithms.HMAC_SHA_1, sharedSecret).hmacHex(value);
+ JsonObject body = new JsonObject();
+ body.addProperty("user", credentials.getLocalPart());
+ body.addProperty("password", credentials.getPassword());
+ body.addProperty("mac", mac);
+ body.addProperty("type", "org.matrix.login.shared_secret");
+ body.addProperty("admin", false);
+ URL url = getPath("client", "api", "v1", "register");
+ updateContext(execute(new Request.Builder().post(getJsonBody(body)).url(url)));
+ }
+
+ @Override
+ public void setAccessToken(String accessToken) {
+ context.setUser(getIdentity(accessToken));
+ context.setToken(accessToken);
+ }
+
+ @Override
+ public void login(MatrixPasswordCredentials credentials) {
+ URL url = getClientPath("login");
+
+ LoginPostBody data = new LoginPostBody(credentials.getLocalPart(), credentials.getPassword());
+ getDeviceId().ifPresent(data::setDeviceId);
+ Optional.ofNullable(context.getInitialDeviceName()).ifPresent(data::setInitialDeviceDisplayName);
+
+ updateContext(execute(new Request.Builder().post(getJsonBody(data)).url(url)));
+ }
+
+ @Override
+ public void logout() {
+ URL path = getClientPath("logout");
+ executeAuthenticated(new Request.Builder().post(getJsonBody(new JsonObject())).url(path));
+ context.setToken(null);
+ context.setUser(null);
+ context.setDeviceId(null);
+ }
+
+ @Override
+ public _SyncData sync(_SyncOptions options) {
+ long start = System.currentTimeMillis();
+ HttpUrl.Builder path = getClientPathBuilder("sync");
+ path.addQueryParameter("timeout", options.getTimeout().map(Long::intValue).orElse(30000).toString());
+ options.getSince().ifPresent(since -> path.addQueryParameter("since", since));
+ options.getFilter().ifPresent(filter -> path.addQueryParameter("filter", filter));
+ options.withFullState().ifPresent(state -> path.addQueryParameter("full_state", state ? "true" : "false"));
+ options.getSetPresence().ifPresent(presence -> path.addQueryParameter("presence", presence));
+
+ String body = executeAuthenticated(new Request.Builder().get().url(path.build().url()));
+ long request = System.currentTimeMillis();
+ log.info("Sync: network request took {} ms", (request - start));
+ SyncDataJson data = new SyncDataJson(GsonUtil.parseObj(body));
+ long parsing = System.currentTimeMillis();
+ log.info("Sync: parsing took {} ms", (parsing - request));
+ return data;
+ }
+
+ @Override
+ public _MatrixContent getMedia(String mxUri) throws IllegalArgumentException {
+ return getMedia(URI.create(mxUri));
+ }
+
+ @Override
+ public _MatrixContent getMedia(URI mxUri) throws IllegalArgumentException {
+ return new MatrixHttpContent(context, mxUri);
+ }
+
+ private String putMedia(Request.Builder builder, String filename) {
+ HttpUrl.Builder b = getMediaPathBuilder("upload");
+ if (StringUtils.isNotEmpty(filename)) b.addQueryParameter("filename", filename);
+
+ String body = executeAuthenticated(builder.url(b.build()));
+ return GsonUtil.getStringOrThrow(GsonUtil.parseObj(body), "content_uri");
+ }
+
+ @Override
+ public String putMedia(byte[] data, String type) {
+ return putMedia(data, type, null);
+ }
+
+ @Override
+ public String putMedia(byte[] data, String type, String filename) {
+ return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
+ }
+
+ @Override
+ public String putMedia(File data, String type) {
+ return putMedia(data, type, null);
+ }
+
+ @Override
+ public String putMedia(File data, String type, String filename) {
+ return putMedia(new Request.Builder().post(RequestBody.create(MediaType.parse(type), data)), filename);
+ }
+
+ @Override
+ public List getPushers() {
+ URL url = getClientPath("pushers");
+ JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().get().url(url)));
+ return GsonUtil.findArray(response, "pushers").map(array -> GsonUtil.asList(array, JsonObject.class))
+ .orElse(Collections.emptyList());
+ }
+
+ @Override
+ public void setPusher(JsonObject pusher) {
+ URL url = getClientPath("pushers", "set");
+ executeAuthenticated(new Request.Builder().url(url).post(getJsonBody(pusher)));
+ }
+
+ @Override
+ public void deletePusher(String pushKey) {
+ JsonObject pusher = new JsonObject();
+ pusher.add("kind", JsonNull.INSTANCE);
+ pusher.addProperty("pushkey", pushKey);
+ setPusher(pusher);
+ }
+
+ @Override
+ public _GlobalPushRulesSet getPushRules() {
+ URL url = getClientPath("pushrules", "global", "");
+ JsonObject response = GsonUtil.parseObj(executeAuthenticated(new Request.Builder().url(url).get()));
+ return new GlobalPushRulesSet(response);
+ }
+
+ @Override
+ public _PushRule getPushRule(String scope, String kind, String id) {
+ return new MatrixHttpPushRule(context, scope, kind, id);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/regular/Presence.java b/src/main/java/io/kamax/matrix/client/regular/Presence.java
new file mode 100644
index 0000000..5fef2c4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/regular/Presence.java
@@ -0,0 +1,48 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.regular;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.client._Presence;
+import io.kamax.matrix.json.GsonUtil;
+
+public class Presence implements _Presence {
+
+ private String status;
+ private Long lastActive;
+
+ public Presence(JsonObject json) {
+ this.status = GsonUtil.getStringOrThrow(json, "presence");
+ this.lastActive = GsonUtil.getLong(json, "last_active_ago");
+ }
+
+ @Override
+ public String getStatus() {
+ return status;
+ }
+
+ @Override
+ public Long getLastActive() {
+ return lastActive;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java b/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java
new file mode 100644
index 0000000..3685064
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/regular/SyncDataJson.java
@@ -0,0 +1,390 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.regular;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.client._SyncData;
+import io.kamax.matrix.event.EventKey;
+import io.kamax.matrix.event._MatrixAccountDataEvent;
+import io.kamax.matrix.event._MatrixEphemeralEvent;
+import io.kamax.matrix.event._MatrixPersistentEvent;
+import io.kamax.matrix.event._MatrixStateEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.*;
+
+public class SyncDataJson extends MatrixJsonObject implements _SyncData {
+
+ public class MatrixPersistentEventJson extends MatrixJsonObject implements _MatrixPersistentEvent {
+
+ public MatrixPersistentEventJson(JsonObject obj) {
+ super(obj);
+ }
+
+ @Override
+ public String getId() {
+ return findString(EventKey.Id.get()).orElse(""); // FIXME refactor event structure
+ }
+
+ @Override
+ public String getType() {
+ return getString(EventKey.Type.get());
+ }
+
+ @Override
+ public Long getTime() {
+ return getLong(EventKey.Timestamp.get());
+ }
+
+ @Override
+ public _MatrixID getSender() {
+ return MatrixID.from(getString(EventKey.Sender.get())).acceptable();
+ }
+ }
+
+ public class MatrixEphemeralEventJson extends MatrixJsonObject implements _MatrixEphemeralEvent {
+
+ public MatrixEphemeralEventJson(JsonObject obj) {
+ super(obj);
+ }
+
+ @Override
+ public String getType() {
+ return getString(EventKey.Type.get());
+ }
+
+ }
+
+ public class MatrixAccountDataEventJson extends MatrixJsonObject implements _MatrixAccountDataEvent {
+
+ public MatrixAccountDataEventJson(JsonObject obj) {
+ super(obj);
+ }
+
+ @Override
+ public String getType() {
+ return getString(EventKey.Type.get());
+ }
+
+ }
+
+ public class MatrixStateEventJson extends MatrixPersistentEventJson implements _MatrixStateEvent {
+
+ public MatrixStateEventJson(JsonObject obj) {
+ super(obj);
+ }
+
+ @Override
+ public String getStateKey() {
+ return getString(EventKey.StateKey.get());
+ }
+
+ }
+
+ public class StateJson extends MatrixJsonObject implements _SyncData.State {
+
+ private List<_MatrixStateEvent> events = new ArrayList<>();
+
+ public StateJson(JsonObject obj) {
+ super(obj);
+
+ findArray("events").ifPresent(array -> {
+ for (JsonElement el : array) {
+ events.add(new MatrixStateEventJson(asObj(el)));
+ }
+ });
+ }
+
+ @Override
+ public List<_MatrixStateEvent> getEvents() {
+ return events;
+ }
+ }
+
+ public class TimelineJson extends MatrixJsonObject implements _SyncData.Timeline {
+
+ private List<_MatrixPersistentEvent> events = new ArrayList<>();
+
+ public TimelineJson(JsonObject obj) {
+ super(obj);
+
+ findArray("events").ifPresent(array -> {
+ for (JsonElement el : array) {
+ events.add(new MatrixPersistentEventJson(asObj(el)));
+ }
+ });
+ }
+
+ @Override
+ public List<_MatrixPersistentEvent> getEvents() {
+ return events;
+ }
+
+ @Override
+ public boolean isLimited() {
+ return findString("limited").map("true"::equals).orElse(false);
+ }
+
+ @Override
+ public String getPreviousBatchToken() {
+ return getString("prev_batch");
+ }
+ }
+
+ public class EphemeralJson extends MatrixJsonObject implements _SyncData.Ephemeral {
+
+ private List<_MatrixEphemeralEvent> events = new ArrayList<>();
+
+ public EphemeralJson(JsonObject obj) {
+ super(obj);
+
+ findArray("events").ifPresent(array -> {
+ for (JsonElement el : array) {
+ events.add(new MatrixEphemeralEventJson(asObj(el)));
+ }
+ });
+ }
+
+ @Override
+ public List<_MatrixEphemeralEvent> getEvents() {
+ return events;
+ }
+ }
+
+ public class AccountDataJson extends MatrixJsonObject implements _SyncData.AccountData {
+
+ private List<_MatrixAccountDataEvent> events = new ArrayList<>();
+
+ public AccountDataJson(JsonObject obj) {
+ super(obj);
+
+ findArray("events").ifPresent(array -> {
+ for (JsonElement el : array) {
+ events.add(new MatrixAccountDataEventJson(asObj(el)));
+ }
+ });
+ }
+
+ @Override
+ public List<_MatrixAccountDataEvent> getEvents() {
+ return events;
+ }
+ }
+
+ public class InvitedRoomJson extends MatrixJsonObject implements _SyncData.InvitedRoom {
+
+ private String id;
+ private State state;
+
+ public InvitedRoomJson(String id, JsonObject data) {
+ super(data);
+ this.id = id;
+ this.state = new StateJson(findObj("invite_state").orElseGet(JsonObject::new));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+ }
+
+ public class UnreadNotificationsJson extends MatrixJsonObject implements _SyncData.UnreadNotifications {
+
+ private long highlights;
+ private long global;
+
+ public UnreadNotificationsJson(JsonObject data) {
+ super(data);
+ this.highlights = findLong("highlight_count").orElse(0L);
+ this.global = findLong("notification_count").orElse(0L);
+ }
+
+ @Override
+ public long getHighlightCount() {
+ return highlights;
+ }
+
+ @Override
+ public long getNotificationCount() {
+ return global;
+ }
+
+ }
+
+ public class JoinedRoomJson extends MatrixJsonObject implements _SyncData.JoinedRoom {
+
+ private String id;
+ private State state;
+ private Timeline timeline;
+ private UnreadNotifications unreadNotifications;
+ private Ephemeral ephemeral;
+ private AccountData accountData;
+
+ public JoinedRoomJson(String id, JsonObject data) {
+ super(data);
+ this.id = id;
+ this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
+ this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
+ this.unreadNotifications = new UnreadNotificationsJson(computeObj("unread_notifications"));
+ this.ephemeral = new EphemeralJson(findObj("ephemeral").orElseGet(JsonObject::new));
+ this.accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+
+ @Override
+ public Timeline getTimeline() {
+ return timeline;
+ }
+
+ @Override
+ public Ephemeral getEphemeral() {
+ return ephemeral;
+ }
+
+ @Override
+ public AccountData getAccountData() {
+ return accountData;
+ }
+
+ @Override
+ public UnreadNotifications getUnreadNotifications() {
+ return unreadNotifications;
+ }
+ }
+
+ public class LeftRoomJson extends MatrixPersistentEventJson implements _SyncData.LeftRoom {
+
+ private String id;
+ private State state;
+ private Timeline timeline;
+
+ public LeftRoomJson(String id, JsonObject data) {
+ super(data);
+ this.id = id;
+ this.state = new StateJson(findObj("state").orElseGet(JsonObject::new));
+ this.timeline = new TimelineJson(findObj("timeline").orElseGet(JsonObject::new));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+
+ @Override
+ public Timeline getTimeline() {
+ return timeline;
+ }
+ }
+
+ public class RoomsJson extends MatrixJsonObject implements _SyncData.Rooms {
+
+ private Set invited = new HashSet<>();
+ private Set joined = new HashSet<>();
+ private Set left = new HashSet<>();
+
+ public RoomsJson(JsonObject obj) {
+ super(obj);
+ findObj("invite").ifPresent(o -> {
+ for (Map.Entry entry : o.entrySet()) {
+ invited.add(new InvitedRoomJson(entry.getKey(), asObj(entry.getValue())));
+ }
+ });
+
+ findObj("join").ifPresent(o -> {
+ for (Map.Entry entry : o.entrySet()) {
+ joined.add(new JoinedRoomJson(entry.getKey(), asObj(entry.getValue())));
+ }
+ });
+
+ findObj("leave").ifPresent(o -> {
+ for (Map.Entry entry : o.entrySet()) {
+ left.add(new LeftRoomJson(entry.getKey(), asObj(entry.getValue())));
+ }
+ });
+ }
+
+ @Override
+ public Set getInvited() {
+ return invited;
+ }
+
+ @Override
+ public Set getJoined() {
+ return joined;
+ }
+
+ @Override
+ public Set getLeft() {
+ return left;
+ }
+
+ }
+
+ private String nextBatch;
+ private AccountDataJson accountData;
+ private RoomsJson rooms;
+
+ public SyncDataJson(JsonObject data) {
+ super(data);
+ nextBatch = getString("next_batch");
+ accountData = new AccountDataJson(findObj("account_data").orElseGet(JsonObject::new));
+ rooms = new RoomsJson(findObj("rooms").orElseGet(JsonObject::new));
+ }
+
+ @Override
+ public String nextBatchToken() {
+ return nextBatch;
+ }
+
+ @Override
+ public AccountData getAccountData() {
+ return accountData;
+ }
+
+ @Override
+ public Rooms getRooms() {
+ return rooms;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java b/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java
new file mode 100644
index 0000000..e1ed9ed
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/client/regular/SyncOptions.java
@@ -0,0 +1,103 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.client.regular;
+
+import io.kamax.matrix.client._SyncOptions;
+
+import java.util.Optional;
+
+public class SyncOptions implements _SyncOptions {
+
+ public static class Builder {
+
+ private final SyncOptions obj;
+
+ public Builder() {
+ this.obj = new SyncOptions();
+ }
+
+ public SyncOptions get() {
+ return obj;
+ }
+
+ public Builder setSince(String since) {
+ obj.since = since;
+ return this;
+ }
+
+ public Builder setFilter(String filter) {
+ obj.filter = filter;
+ return this;
+ }
+
+ public Builder setWithFullState(boolean withFullState) {
+ obj.fullState = withFullState;
+ return this;
+ }
+
+ public Builder setPresence(boolean setPresence) {
+ obj.setPresence = setPresence ? null : "offline";
+ return this;
+ }
+
+ public Builder setTimeout(long timeout) {
+ obj.timeout = timeout;
+ return this;
+ }
+
+ }
+
+ public static Builder build() {
+ return new Builder();
+ }
+
+ private String since;
+ private String filter;
+ private Boolean fullState;
+ private String setPresence;
+ private Long timeout;
+
+ @Override
+ public Optional getSince() {
+ return Optional.ofNullable(since);
+ }
+
+ @Override
+ public Optional getFilter() {
+ return Optional.ofNullable(filter);
+ }
+
+ @Override
+ public Optional withFullState() {
+ return Optional.ofNullable(fullState);
+ }
+
+ @Override
+ public Optional getSetPresence() {
+ return Optional.ofNullable(setPresence);
+ }
+
+ @Override
+ public Optional getTimeout() {
+ return Optional.ofNullable(timeout);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/codec/MxBase64.java b/src/main/java/io/kamax/matrix/codec/MxBase64.java
new file mode 100644
index 0000000..9c849c7
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/codec/MxBase64.java
@@ -0,0 +1,36 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.codec;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+public class MxBase64 {
+
+ public static String encode(byte[] data) {
+ return Base64.getEncoder().withoutPadding().encodeToString(data);
+ }
+
+ public static String encode(String data) {
+ return encode(data.getBytes(StandardCharsets.UTF_8));
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/codec/MxSha256.java b/src/main/java/io/kamax/matrix/codec/MxSha256.java
new file mode 100644
index 0000000..2bb4aa4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/codec/MxSha256.java
@@ -0,0 +1,47 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.codec;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MxSha256 {
+
+ private MessageDigest md;
+
+ public MxSha256() {
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String hash(byte[] data) {
+ return MxBase64.encode(md.digest(data));
+ }
+
+ public String hash(String data) {
+ return hash(data.getBytes(StandardCharsets.UTF_8));
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/crypto/KeyFileStore.java b/src/main/java/io/kamax/matrix/crypto/KeyFileStore.java
new file mode 100644
index 0000000..b8f68a7
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/crypto/KeyFileStore.java
@@ -0,0 +1,80 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.crypto;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class KeyFileStore implements _KeyStore {
+
+ private final Charset charset = StandardCharsets.UTF_8;
+
+ private File file;
+
+ public KeyFileStore(String path) {
+ File file = new File(path);
+ if (!file.exists()) {
+ throw new IllegalArgumentException("Signing key file storage " + path + " does not exist");
+ }
+
+ if (file.isDirectory()) {
+ throw new IllegalArgumentException("Signing key file storage " + path + " is a directory");
+ }
+
+ if (!file.isFile()) {
+ throw new IllegalArgumentException("Signing key file storage " + path + " is not a regular file");
+ }
+
+ if (!file.canRead()) {
+ throw new IllegalArgumentException("Signing key file storage " + path + " is not readable");
+ }
+
+ this.file = file;
+ }
+
+ @Override
+ public Optional load() {
+ try {
+ List keys = FileUtils.readLines(file, charset);
+ return keys.stream().filter(StringUtils::isNotBlank).findFirst();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void store(String key) {
+ try {
+ FileUtils.writeLines(file, charset.name(), Collections.singletonList(key), false);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/crypto/KeyManager.java b/src/main/java/io/kamax/matrix/crypto/KeyManager.java
new file mode 100644
index 0000000..27a4f60
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/crypto/KeyManager.java
@@ -0,0 +1,100 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.crypto;
+
+import io.kamax.matrix.codec.MxBase64;
+
+import java.security.KeyPair;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+
+import net.i2p.crypto.eddsa.EdDSAPrivateKey;
+import net.i2p.crypto.eddsa.EdDSAPublicKey;
+import net.i2p.crypto.eddsa.KeyPairGenerator;
+import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
+import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
+import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
+import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
+
+public class KeyManager {
+
+ public static KeyManager fromFile(String path) {
+ return new KeyManager(new KeyFileStore(path));
+ }
+
+ public static KeyManager fromMemory() {
+ return new KeyManager(new KeyMemoryStore());
+ }
+
+ private EdDSAParameterSpec keySpecs;
+ private List keys;
+
+ public KeyManager(_KeyStore store) {
+ keySpecs = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
+ keys = new ArrayList<>();
+
+ String seedBase64 = store.load().orElseGet(() -> {
+ KeyPair pair = (new KeyPairGenerator()).generateKeyPair();
+ String keyEncoded = getPrivateKeyBase64((EdDSAPrivateKey) pair.getPrivate());
+ store.store(keyEncoded);
+ return keyEncoded;
+ });
+ byte[] seed = Base64.getDecoder().decode(seedBase64);
+ EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(seed, keySpecs);
+ EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKeySpec.getA(), keySpecs);
+ keys.add(new KeyPair(new EdDSAPublicKey(pubKeySpec), new EdDSAPrivateKey(privKeySpec)));
+ }
+
+ public int getCurrentIndex() {
+ return 0;
+ }
+
+ public KeyPair getKeys(int index) {
+ return keys.get(index);
+ }
+
+ public EdDSAPrivateKey getPrivateKey(int index) {
+ return (EdDSAPrivateKey) getKeys(index).getPrivate();
+ }
+
+ protected String getPrivateKeyBase64(EdDSAPrivateKey key) {
+ return MxBase64.encode(key.getSeed());
+ }
+
+ public String getPrivateKeyBase64(int index) {
+ return getPrivateKeyBase64(getPrivateKey(index));
+ }
+
+ public EdDSAPublicKey getPublicKey(int index) {
+ return (EdDSAPublicKey) getKeys(index).getPublic();
+ }
+
+ public EdDSAParameterSpec getSpecs() {
+ return keySpecs;
+ }
+
+ public String getPublicKeyBase64(int index) {
+ return MxBase64.encode(getPublicKey(index).getAbyte());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/crypto/KeyMemoryStore.java b/src/main/java/io/kamax/matrix/crypto/KeyMemoryStore.java
new file mode 100644
index 0000000..79af627
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/crypto/KeyMemoryStore.java
@@ -0,0 +1,46 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.crypto;
+
+import java.util.Optional;
+
+public class KeyMemoryStore implements _KeyStore {
+
+ private String data;
+
+ public KeyMemoryStore() {
+ }
+
+ public KeyMemoryStore(String data) {
+ this.data = data;
+ }
+
+ @Override
+ public Optional load() {
+ return Optional.ofNullable(data);
+ }
+
+ @Override
+ public void store(String key) {
+ data = key;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/crypto/SignatureManager.java b/src/main/java/io/kamax/matrix/crypto/SignatureManager.java
new file mode 100644
index 0000000..950c543
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/crypto/SignatureManager.java
@@ -0,0 +1,80 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.crypto;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.codec.MxBase64;
+import io.kamax.matrix.json.MatrixJson;
+
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+
+import net.i2p.crypto.eddsa.EdDSAEngine;
+
+public class SignatureManager {
+
+ private KeyManager keyMgr;
+ private String domain;
+
+ private EdDSAEngine signEngine;
+
+ public SignatureManager(KeyManager keyMgr, String domain) {
+ this.keyMgr = keyMgr;
+ this.domain = domain;
+
+ try {
+ signEngine = new EdDSAEngine(MessageDigest.getInstance(keyMgr.getSpecs().getHashAlgorithm()));
+ signEngine.initSign(keyMgr.getPrivateKey(keyMgr.getCurrentIndex()));
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String sign(JsonObject obj) {
+ return sign(MatrixJson.encodeCanonical(obj));
+ }
+
+ public String sign(String message) {
+ try {
+ byte[] signRaw = signEngine.signOneShot(message.getBytes());
+ return MxBase64.encode(signRaw);
+ } catch (SignatureException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public JsonObject signMessageGson(String message) {
+ String sign = sign(message);
+
+ JsonObject keySignature = new JsonObject();
+ // FIXME should create a signing key object what would give this ed and index values
+ keySignature.addProperty("ed25519:" + keyMgr.getCurrentIndex(), sign);
+ JsonObject signature = new JsonObject();
+ signature.add(domain, keySignature);
+
+ return signature;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/crypto/_KeyStore.java b/src/main/java/io/kamax/matrix/crypto/_KeyStore.java
new file mode 100644
index 0000000..4d1254d
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/crypto/_KeyStore.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.crypto;
+
+import java.util.Optional;
+
+public interface _KeyStore {
+
+ Optional load();
+
+ void store(String key);
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/EventKey.java b/src/main/java/io/kamax/matrix/event/EventKey.java
new file mode 100644
index 0000000..0ca64fb
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/EventKey.java
@@ -0,0 +1,88 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MalformedEventException;
+import io.kamax.matrix.json.GsonUtil;
+
+import java.util.Optional;
+
+public enum EventKey {
+
+ AuthEvents("auth_events"),
+ Content("content"),
+ Depth("depth"),
+ Hashes("hashes"),
+ Id("event_id"),
+ Origin("origin"),
+ Timestamp("origin_server_ts"),
+ PreviousEvents("prev_events"),
+ PreviousState("prev_state"),
+ RoomId("room_id"),
+ Sender("sender"),
+ Signatures("signatures"),
+ StateKey("state_key"),
+ Type("type"),
+ Membership("membership"),
+ Unsigned("unsigned");
+
+ private String key;
+
+ EventKey(String key) {
+ this.key = key;
+ }
+
+ public String get() {
+ return key;
+ }
+
+ public JsonObject getObj(JsonObject o) {
+ return findObj(o).orElseThrow(() -> new MalformedEventException(key));
+ }
+
+ public JsonElement getElement(JsonObject o) {
+ return GsonUtil.findElement(o, key).orElseThrow(() -> new MalformedEventException(key));
+ }
+
+ public Optional findObj(JsonObject o) {
+ return GsonUtil.findObj(o, key);
+ }
+
+ public Optional findString(JsonObject o) {
+ return GsonUtil.findString(o, key);
+ }
+
+ public String getString(JsonObject o) {
+ return findString(o).orElseThrow(() -> new MalformedEventException(key));
+ }
+
+ public String getStringOrNull(JsonObject o) {
+ return GsonUtil.getStringOrNull(o, key);
+ }
+
+ public long getLong(JsonObject o) {
+ return GsonUtil.getLong(o, key);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_DirectEvent.java b/src/main/java/io/kamax/matrix/event/_DirectEvent.java
new file mode 100644
index 0000000..fb35c7c
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_DirectEvent.java
@@ -0,0 +1,34 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix._MatrixID;
+
+import java.util.List;
+import java.util.Map;
+
+public interface _DirectEvent extends _MatrixEphemeralEvent {
+
+ String Type = "m.direct";
+
+ Map<_MatrixID, List> getMappings();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_MatrixAccountDataEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixAccountDataEvent.java
new file mode 100644
index 0000000..f037128
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_MatrixAccountDataEvent.java
@@ -0,0 +1,24 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+public interface _MatrixAccountDataEvent extends _MatrixEvent {
+}
diff --git a/src/main/java/io/kamax/matrix/event/_MatrixEphemeralEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixEphemeralEvent.java
new file mode 100644
index 0000000..4c4e538
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_MatrixEphemeralEvent.java
@@ -0,0 +1,25 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package io.kamax.matrix.event;
+
+public interface _MatrixEphemeralEvent extends _MatrixEvent {
+}
diff --git a/src/main/java/io/kamax/matrix/event/_MatrixEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixEvent.java
new file mode 100644
index 0000000..751e7eb
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_MatrixEvent.java
@@ -0,0 +1,32 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package io.kamax.matrix.event;
+
+import com.google.gson.JsonObject;
+
+public interface _MatrixEvent {
+
+ String getType();
+
+ JsonObject getJson();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_MatrixPersistentEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixPersistentEvent.java
new file mode 100644
index 0000000..310c2fe
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_MatrixPersistentEvent.java
@@ -0,0 +1,33 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix._MatrixID;
+
+public interface _MatrixPersistentEvent extends _MatrixEvent {
+
+ String getId();
+
+ Long getTime();
+
+ _MatrixID getSender();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java b/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java
new file mode 100644
index 0000000..9a7f0fc
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_MatrixStateEvent.java
@@ -0,0 +1,27 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+public interface _MatrixStateEvent extends _MatrixPersistentEvent {
+
+ String getStateKey();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_ReadReceiptEvent.java b/src/main/java/io/kamax/matrix/event/_ReadReceiptEvent.java
new file mode 100644
index 0000000..cc8a877
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_ReadReceiptEvent.java
@@ -0,0 +1,32 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix.json.event.MatrixJsonReadReceiptEvent;
+
+import java.util.List;
+
+public interface _ReadReceiptEvent extends _MatrixEphemeralEvent {
+
+ List getReceipts();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomAliasesEvent.java b/src/main/java/io/kamax/matrix/event/_RoomAliasesEvent.java
new file mode 100644
index 0000000..c202b28
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomAliasesEvent.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.List;
+
+public interface _RoomAliasesEvent extends _RoomEvent {
+
+ List getAliases();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomAvatarEvent.java b/src/main/java/io/kamax/matrix/event/_RoomAvatarEvent.java
new file mode 100644
index 0000000..8401b80
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomAvatarEvent.java
@@ -0,0 +1,27 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+public interface _RoomAvatarEvent extends _RoomEvent {
+
+ String getUrl();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomCanonicalAliasEvent.java b/src/main/java/io/kamax/matrix/event/_RoomCanonicalAliasEvent.java
new file mode 100644
index 0000000..a095dd4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomCanonicalAliasEvent.java
@@ -0,0 +1,33 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.Optional;
+
+public interface _RoomCanonicalAliasEvent extends _RoomEvent {
+
+ String Type = "m.room.canonical_alias";
+
+ boolean hasAlias();
+
+ Optional getAlias();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomEvent.java b/src/main/java/io/kamax/matrix/event/_RoomEvent.java
new file mode 100644
index 0000000..8b1118f
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomEvent.java
@@ -0,0 +1,27 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+public interface _RoomEvent extends _MatrixPersistentEvent {
+
+ String getRoomId();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomHistoryVisibilityEvent.java b/src/main/java/io/kamax/matrix/event/_RoomHistoryVisibilityEvent.java
new file mode 100644
index 0000000..b9650bf
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomHistoryVisibilityEvent.java
@@ -0,0 +1,34 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix.room.RoomHistoryVisibility;
+
+public interface _RoomHistoryVisibilityEvent extends _RoomEvent {
+
+ /**
+ * There is an enum for handling the return values defined in th specification: {@link RoomHistoryVisibility}
+ *
+ * @return The current setting of the room for the visibility of future messages.
+ */
+ String getHistoryVisibility();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java b/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java
new file mode 100644
index 0000000..92bf3ce
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomMembershipEvent.java
@@ -0,0 +1,37 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix._MatrixID;
+
+import java.util.Optional;
+
+public interface _RoomMembershipEvent extends _RoomEvent {
+
+ String getMembership();
+
+ Optional getAvatarUrl();
+
+ Optional getDisplayName();
+
+ _MatrixID getInvitee();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java b/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java
new file mode 100644
index 0000000..ead99c5
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomMessageEvent.java
@@ -0,0 +1,35 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.Optional;
+
+public interface _RoomMessageEvent extends _RoomEvent {
+
+ String getBody();
+
+ String getBodyType();
+
+ Optional getFormat();
+
+ Optional getFormattedBody();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomNameEvent.java b/src/main/java/io/kamax/matrix/event/_RoomNameEvent.java
new file mode 100644
index 0000000..2cf2b05
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomNameEvent.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.Optional;
+
+public interface _RoomNameEvent extends _RoomEvent {
+
+ Optional getName();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomPowerLevelsEvent.java b/src/main/java/io/kamax/matrix/event/_RoomPowerLevelsEvent.java
new file mode 100644
index 0000000..fa42819
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomPowerLevelsEvent.java
@@ -0,0 +1,46 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.Map;
+import java.util.Optional;
+
+public interface _RoomPowerLevelsEvent extends _RoomEvent {
+
+ Optional getBan();
+
+ Map getEvents();
+
+ Optional getEventsDefault();
+
+ Optional getInvite();
+
+ Optional getKick();
+
+ Optional getRedact();
+
+ Optional getStateDefault();
+
+ Map getUsers();
+
+ Optional getUsersDefault();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_RoomTopicEvent.java b/src/main/java/io/kamax/matrix/event/_RoomTopicEvent.java
new file mode 100644
index 0000000..b2a420d
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_RoomTopicEvent.java
@@ -0,0 +1,29 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import java.util.Optional;
+
+public interface _RoomTopicEvent extends _RoomEvent {
+
+ Optional getTopic();
+
+}
diff --git a/src/main/java/io/kamax/matrix/event/_TagsEvent.java b/src/main/java/io/kamax/matrix/event/_TagsEvent.java
new file mode 100644
index 0000000..ea052c6
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/event/_TagsEvent.java
@@ -0,0 +1,34 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.event;
+
+import io.kamax.matrix.room.Tag;
+
+import java.util.List;
+
+public interface _TagsEvent extends _MatrixEvent {
+
+ String Type = "m.tag";
+
+ List getTags();
+
+}
diff --git a/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java b/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java
new file mode 100644
index 0000000..a4a3989
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/hs/MatrixHomeserver.java
@@ -0,0 +1,58 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.hs;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class MatrixHomeserver implements _MatrixHomeserver {
+
+ private String domain;
+ private URL base;
+
+ private static URL getURL(String url) {
+ try {
+ return new URL(url);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public MatrixHomeserver(String domain, URL baseUrl) {
+ this.domain = domain;
+ this.base = baseUrl;
+ }
+
+ public MatrixHomeserver(String domain, String baseUrl) {
+ this(domain, getURL(baseUrl));
+ }
+
+ @Override
+ public String getDomain() {
+ return domain;
+ }
+
+ @Override
+ public URL getBaseEndpoint() {
+ return base;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/hs/RoomMembership.java b/src/main/java/io/kamax/matrix/hs/RoomMembership.java
new file mode 100644
index 0000000..54e876a
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/hs/RoomMembership.java
@@ -0,0 +1,45 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.hs;
+
+public enum RoomMembership {
+
+ Invite("invite"),
+ Join("join"),
+ Leave("leave"),
+ Ban("ban"),
+ Knock("knock");
+
+ private String id;
+
+ RoomMembership(String id) {
+ this.id = id;
+ }
+
+ public String get() {
+ return id;
+ }
+
+ public boolean is(String id) {
+ return this.id.contentEquals(id);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java b/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java
new file mode 100644
index 0000000..ae8cace
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/hs/_MatrixHomeserver.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.hs;
+
+import java.net.URL;
+
+public interface _MatrixHomeserver {
+
+ String getDomain();
+
+ URL getBaseEndpoint();
+
+}
diff --git a/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java b/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java
new file mode 100644
index 0000000..feb535a
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/hs/_MatrixRoom.java
@@ -0,0 +1,159 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.hs;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixErrorInfo;
+import io.kamax.matrix._MatrixContent;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix._MatrixUserProfile;
+import io.kamax.matrix.room.*;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface _MatrixRoom {
+
+ _MatrixHomeserver getHomeserver();
+
+ String getAddress();
+
+ Optional getName();
+
+ Optional getTopic();
+
+ Optional getAvatarUrl();
+
+ Optional<_MatrixContent> getAvatar();
+
+ String getId();
+
+ /**
+ * Get a state event
+ *
+ * @param type
+ * The type of state to look for
+ * @return An optional JsonObject representing the content key of the event
+ */
+ Optional getState(String type);
+
+ /**
+ * Get a state event
+ *
+ * @param type
+ * The type of state to look for
+ * @param key
+ * The state key to match
+ * @return An optional JsonObject representing the content key of the event
+ */
+ Optional getState(String type, String key);
+
+ void join();
+
+ void join(List servers);
+
+ Optional tryJoin();
+
+ Optional tryJoin(List servers);
+
+ void leave();
+
+ Optional tryLeave();
+
+ void kick(_MatrixID user);
+
+ void kick(_MatrixID user, String reason);
+
+ Optional tryKick(_MatrixID user);
+
+ Optional tryKick(_MatrixID user, String reason);
+
+ String sendEvent(String type, JsonObject content);
+
+ String sendText(String message);
+
+ String sendFormattedText(String formatted, String rawFallback);
+
+ String sendNotice(String message);
+
+ String sendNotice(String formatted, String plain);
+
+ /**
+ * Send a receipt for an event
+ *
+ * @param type
+ * The receipt type to send
+ * @param eventId
+ * The Event ID targeted by the receipt
+ */
+ void sendReceipt(String type, String eventId);
+
+ /**
+ * Send a receipt for an event
+ *
+ * @param type
+ * The receipt type to send
+ * @param eventId
+ * The Event ID targeted by the receipt
+ */
+ void sendReceipt(ReceiptType type, String eventId);
+
+ /**
+ * Send a Read receipt for an event
+ *
+ * @param eventId
+ * The Event ID targeted by the read receipt
+ */
+ void sendReadReceipt(String eventId);
+
+ void invite(_MatrixID mxId);
+
+ List<_MatrixUserProfile> getJoinedUsers();
+
+ _MatrixRoomMessageChunk getMessages(_MatrixRoomMessageChunkOptions options);
+
+ List getAllTags();
+
+ List getUserTags();
+
+ void addUserTag(String tag);
+
+ void addUserTag(String tag, double order);
+
+ void deleteUserTag(String tag);
+
+ void addFavouriteTag();
+
+ void addFavouriteTag(double order);
+
+ void deleteFavouriteTag();
+
+ Optional getFavouriteTag();
+
+ void addLowpriorityTag();
+
+ void addLowpriorityTag(double order);
+
+ Optional getLowpriorityTag();
+
+ void deleteLowpriorityTag();
+}
diff --git a/src/main/java/io/kamax/matrix/is/_IdentityServer.java b/src/main/java/io/kamax/matrix/is/_IdentityServer.java
new file mode 100644
index 0000000..7e1272b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/is/_IdentityServer.java
@@ -0,0 +1,35 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.is;
+
+import io.kamax.matrix._ThreePid;
+import io.kamax.matrix._ThreePidMapping;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface _IdentityServer {
+
+ Optional<_ThreePidMapping> find(_ThreePid threePid);
+
+ List<_ThreePidMapping> find(List<_ThreePid> threePidList);
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/GsonUtil.java b/src/main/java/io/kamax/matrix/json/GsonUtil.java
new file mode 100644
index 0000000..5c87244
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/GsonUtil.java
@@ -0,0 +1,193 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+public class GsonUtil {
+
+ private static Gson instance = build();
+ private static Gson instancePretty = buildPretty();
+
+ private static GsonBuilder buildImpl() {
+ return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .disableHtmlEscaping();
+ }
+
+ public static Gson buildPretty() {
+ return buildImpl().setPrettyPrinting().create();
+ }
+
+ public static Gson build() {
+ return buildImpl().create();
+ }
+
+ public static JsonArray asArray(List elements) {
+ JsonArray a = new JsonArray();
+ elements.forEach(a::add);
+ return a;
+ }
+
+ public static JsonArray asArrayObj(List extends Object> elements) {
+ return asArray(elements.stream().map(e -> get().toJsonTree(e)).collect(Collectors.toList()));
+ }
+
+ public static JsonArray asArray(String... elements) {
+ return asArray(
+ Arrays.stream(elements).map(JsonPrimitive::new).collect(Collectors.toList()));
+ }
+
+ public static JsonArray asArray(Collection elements) {
+ JsonArray a = new JsonArray();
+ elements.forEach(a::add);
+ return a;
+ }
+
+ public static List asList(JsonArray a, Class c) {
+ List l = new ArrayList<>();
+ for (JsonElement v : a) {
+ l.add(GsonUtil.get().fromJson(v, c));
+ }
+ return l;
+ }
+
+ public static List asList(JsonObject obj, String member, Class c) {
+ return asList(getArray(obj, member), c);
+ }
+
+ public static JsonObject makeObj(Object o) {
+ return instance.toJsonTree(o).getAsJsonObject();
+ }
+
+ public static JsonObject makeObj(String key, Object value) {
+ return makeObj(key, instance.toJsonTree(value));
+ }
+
+ public static JsonObject makeObj(String key, JsonElement el) {
+ JsonObject obj = new JsonObject();
+ obj.add(key, el);
+ return obj;
+ }
+
+ public static JsonObject makeObj(Consumer consumer) {
+ JsonObject obj = new JsonObject();
+ consumer.accept(obj);
+ return obj;
+ }
+
+ public static Gson get() {
+ return instance;
+ }
+
+ public static Gson getPretty() {
+ return instancePretty;
+ }
+
+ public static String getPrettyForLog(Object o) {
+ return System.lineSeparator() + getPretty().toJson(o);
+ }
+
+ public static JsonElement parse(String s) {
+ try {
+ return new JsonParser().parse(s);
+ } catch (JsonParseException e) {
+ throw new InvalidJsonException(e);
+ }
+ }
+
+ public static JsonObject parseObj(String s) {
+ try {
+ return parse(s).getAsJsonObject();
+ } catch (IllegalStateException e) {
+ throw new InvalidJsonException("Not an object");
+ }
+ }
+
+ public static JsonArray getArray(JsonObject obj, String member) {
+ return findArray(obj, member).orElseThrow(() -> new InvalidJsonException("Not an array"));
+ }
+
+ public static JsonObject getObj(JsonObject obj, String member) {
+ return findObj(obj, member).orElseThrow(() -> new InvalidJsonException("No object for member " + member));
+ }
+
+ public static Optional findString(JsonObject o, String key) {
+ return findPrimitive(o, key).map(JsonPrimitive::getAsString);
+ }
+
+ public static String getStringOrNull(JsonObject o, String key) {
+ JsonElement el = o.get(key);
+ if (el != null && el.isJsonPrimitive()) {
+ return el.getAsString();
+ } else {
+ return null;
+ }
+ }
+
+ public static String getStringOrThrow(JsonObject obj, String member) {
+ if (!obj.has(member)) {
+ throw new InvalidJsonException(member + " key is missing");
+ }
+
+ return obj.get(member).getAsString();
+ }
+
+ public static Optional findElement(JsonObject o, String key) {
+ return Optional.ofNullable(o.get(key));
+ }
+
+ public static Optional findPrimitive(JsonObject o, String key) {
+ return findElement(o, key).map(el -> el.isJsonPrimitive() ? el.getAsJsonPrimitive() : null);
+ }
+
+ public static JsonPrimitive getPrimitive(JsonObject o, String key) {
+ return findPrimitive(o, key).orElseThrow(() -> new InvalidJsonException("No primitive value for key " + key));
+ }
+
+ public static Optional findLong(JsonObject o, String key) {
+ return findPrimitive(o, key).map(JsonPrimitive::getAsLong);
+ }
+
+ public static long getLong(JsonObject o, String key) {
+ return findLong(o, key).orElseThrow(() -> new InvalidJsonException("No numeric value for key " + key));
+ }
+
+ public static Optional findObj(JsonObject o, String key) {
+ if (!o.has(key)) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(o.getAsJsonObject(key));
+ }
+
+ public static Optional findArray(JsonObject o, String key) {
+ return findElement(o, key).filter(JsonElement::isJsonArray).map(JsonElement::getAsJsonArray);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/InvalidJsonException.java b/src/main/java/io/kamax/matrix/json/InvalidJsonException.java
new file mode 100644
index 0000000..986ffba
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/InvalidJsonException.java
@@ -0,0 +1,35 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import io.kamax.matrix.MatrixException;
+
+public class InvalidJsonException extends MatrixException {
+
+ public InvalidJsonException(Throwable t) {
+ super("M_BAD_JSON", t.getMessage(), t);
+ }
+
+ public InvalidJsonException(String error) {
+ super("M_BAD_JSON", error);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java b/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java
new file mode 100644
index 0000000..bcab68b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/JsonCanonicalException.java
@@ -0,0 +1,33 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class JsonCanonicalException extends RuntimeException {
+
+ public JsonCanonicalException(String message) {
+ super(message);
+ }
+
+ public JsonCanonicalException(Throwable t) {
+ super(t);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/LoginPostBody.java b/src/main/java/io/kamax/matrix/json/LoginPostBody.java
new file mode 100644
index 0000000..d03e0cb
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/LoginPostBody.java
@@ -0,0 +1,58 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class LoginPostBody {
+
+ private String type = "m.login.password";
+ private String user;
+ private String password;
+ private String deviceId;
+ private String initialDeviceDisplayName;
+
+ public LoginPostBody(String user, String password) {
+ this.user = user;
+ this.password = password;
+ }
+
+ public LoginPostBody(String user, String password, String deviceId) {
+ this(user, password);
+ this.deviceId = deviceId;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getInitialDeviceDisplayName() {
+ return initialDeviceDisplayName;
+ }
+
+ public void setInitialDeviceDisplayName(String initialDeviceDisplayName) {
+ this.initialDeviceDisplayName = initialDeviceDisplayName;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/LoginResponse.java b/src/main/java/io/kamax/matrix/json/LoginResponse.java
new file mode 100644
index 0000000..e21c5a3
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/LoginResponse.java
@@ -0,0 +1,45 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class LoginResponse {
+
+ private String access_token;
+ private String home_server;
+ private String user_id;
+ private String device_id;
+
+ public String getAccessToken() {
+ return access_token;
+ }
+
+ public String getHomeServer() {
+ return home_server;
+ }
+
+ public String getUserId() {
+ return user_id;
+ }
+
+ public String getDeviceId() {
+ return device_id;
+ }
+}
diff --git a/src/main/java/io/kamax/matrix/json/MatrixJson.java b/src/main/java/io/kamax/matrix/json/MatrixJson.java
new file mode 100644
index 0000000..8f9baa1
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/MatrixJson.java
@@ -0,0 +1,115 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Comparator;
+import java.util.Map;
+
+public class MatrixJson {
+
+ // Needed to avoid silly try/catch block in lambdas
+ // We only use ByteArray streams, so IOException will not happen (unless irrecoverable situation like OOM)
+ private static class JsonWriterUnchecked extends JsonWriter {
+
+ public JsonWriterUnchecked(Writer out) {
+ super(out);
+ }
+
+ @Override
+ public JsonWriter name(String value) {
+ try {
+ return super.name(value);
+ } catch (IOException e) {
+ throw new JsonCanonicalException(e);
+ }
+ }
+ }
+
+ private static JsonParser parser = new JsonParser();
+
+ private static void encodeCanonical(JsonObject el, JsonWriterUnchecked writer) throws IOException {
+ writer.beginObject();
+ el.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entry -> {
+ writer.name(entry.getKey());
+ encodeCanonicalElement(entry.getValue(), writer);
+ });
+ writer.endObject();
+ }
+
+ private static void encodeCanonicalArray(JsonArray array, JsonWriterUnchecked writer) throws IOException {
+ writer.beginArray();
+ array.forEach(el -> encodeCanonicalElement(el, writer));
+ writer.endArray();
+ }
+
+ private static void encodeCanonicalElement(JsonElement el, JsonWriterUnchecked writer) {
+ try {
+ if (el.isJsonObject()) encodeCanonical(el.getAsJsonObject(), writer);
+ else if (el.isJsonPrimitive()) writer.jsonValue(el.toString());
+ else if (el.isJsonArray()) encodeCanonicalArray(el.getAsJsonArray(), writer);
+ else if (el.isJsonNull()) writer.nullValue();
+ else throw new JsonCanonicalException("Unexpected JSON type, this is a bug, report!");
+ } catch (IOException e) {
+ throw new JsonCanonicalException(e);
+ }
+ }
+
+ public static String encodeCanonical(JsonObject obj) {
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ JsonWriterUnchecked writer = new JsonWriterUnchecked(new OutputStreamWriter(out, StandardCharsets.UTF_8));
+ writer.setIndent("");
+ writer.setHtmlSafe(false);
+ writer.setLenient(false);
+
+ encodeCanonical(obj, writer);
+ writer.close();
+ return out.toString(StandardCharsets.UTF_8.name());
+ } catch (IOException e) {
+ throw new JsonCanonicalException(e);
+ }
+ }
+
+ public static String encodeCanonical(String data) {
+ JsonElement el = parser.parse(data);
+ if (!el.isJsonObject()) {
+ /*
+ * TODO seems implied because of how signing/checking signatures is done and because of
+ * https://matrix.to/#/!XqBunHwQIXUiqCaoxq:matrix.org/$15075894901530229RWcIi:matrix.org
+ * with the "whole object".
+ */
+ throw new JsonCanonicalException("Not a JSON object, cannot encode canonical");
+ }
+ return encodeCanonical(el.getAsJsonObject());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java b/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java
new file mode 100644
index 0000000..96b4280
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/MatrixJsonEventFactory.java
@@ -0,0 +1,76 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event.*;
+import io.kamax.matrix.json.event.*;
+
+import java.util.Optional;
+
+public class MatrixJsonEventFactory {
+
+ public static _MatrixEvent get(JsonObject obj) {
+ String type = obj.get("type").getAsString();
+
+ if ("m.room.member".contentEquals(type)) {
+ return new MatrixJsonRoomMembershipEvent(obj);
+ } else if ("m.room.power_levels".contentEquals(type)) {
+ return new MatrixJsonRoomPowerLevelsEvent(obj);
+ } else if ("m.room.avatar".contentEquals(type)) {
+ return new MatrixJsonRoomAvatarEvent(obj);
+ } else if ("m.room.name".contentEquals(type)) {
+ return new MatrixJsonRoomNameEvent(obj);
+ } else if ("m.room.topic".contentEquals(type)) {
+ return new MatrixJsonRoomTopicEvent(obj);
+ } else if ("m.room.aliases".contentEquals(type)) {
+ return new MatrixJsonRoomAliasesEvent(obj);
+ } else if (_RoomCanonicalAliasEvent.Type.contentEquals(type)) {
+ return new MatrixJsonRoomCanonicalAliasEvent(obj);
+ } else if ("m.room.message".contentEquals(type)) {
+ return new MatrixJsonRoomMessageEvent(obj);
+ } else if ("m.receipt".contentEquals(type)) {
+ return new MatrixJsonReadReceiptEvent(obj);
+ } else if ("m.room.history_visibility".contentEquals(type)) {
+ return new MatrixJsonRoomHistoryVisibilityEvent(obj);
+ } else if (_TagsEvent.Type.contentEquals(type)) {
+ return new MatrixJsonRoomTagsEvent(obj);
+ } else if (_DirectEvent.Type.contentEquals(type)) {
+ return new MatrixJsonDirectEvent(obj);
+ } else {
+ Optional timestamp = EventKey.Timestamp.findString(obj);
+ Optional sender = EventKey.Sender.findString(obj);
+
+ if (!timestamp.isPresent() || !sender.isPresent()) {
+ return new MatrixJsonEphemeralEvent(obj);
+ } else {
+ Optional rId = EventKey.RoomId.findString(obj);
+ if (rId.isPresent()) {
+ return new MatrixJsonRoomEvent(obj);
+ }
+
+ return new MatrixJsonPersistentEvent(obj);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java b/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java
new file mode 100644
index 0000000..85a5a54
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/MatrixJsonObject.java
@@ -0,0 +1,110 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.*;
+
+import java.util.Objects;
+import java.util.Optional;
+
+public class MatrixJsonObject {
+
+ private JsonObject obj;
+
+ public MatrixJsonObject(JsonObject obj) {
+ if (Objects.isNull(obj)) {
+ throw new InvalidJsonException("JSON Object is null");
+ }
+
+ this.obj = obj;
+ }
+
+ protected Optional findString(String field) {
+ return GsonUtil.findString(obj, field);
+ }
+
+ protected String getString(String field) {
+ return GsonUtil.getStringOrNull(obj, field);
+ }
+
+ protected String getStringOrNull(JsonObject obj, String field) {
+ return GsonUtil.findString(obj, field).orElse(null);
+ }
+
+ protected String getStringOrNull(String field) {
+ return getStringOrNull(obj, field);
+ }
+
+ protected int getInt(String field) {
+ return GsonUtil.getPrimitive(obj, field).getAsInt();
+ }
+
+ protected int getInt(String field, int failover) {
+ return GsonUtil.findPrimitive(obj, field).map(JsonPrimitive::getAsInt).orElse(failover);
+ }
+
+ protected Optional findLong(String field) {
+ return GsonUtil.findLong(obj, field);
+ }
+
+ protected long getLong(String field) {
+ return GsonUtil.getLong(obj, field);
+ }
+
+ /*
+ * Returns the Double value, if the key is present, null else
+ */
+ protected Double getDoubleIfPresent(String field) {
+ if (obj.get(field) != null) {
+ return GsonUtil.getPrimitive(obj, field).getAsDouble();
+ }
+ return null;
+ }
+
+ protected JsonObject asObj(JsonElement el) {
+ if (!el.isJsonObject()) {
+ throw new IllegalArgumentException("Not a JSON object");
+ }
+
+ return el.getAsJsonObject();
+ }
+
+ protected JsonObject getObj(String field) {
+ return GsonUtil.getObj(obj, field);
+ }
+
+ protected Optional findObj(String field) {
+ return GsonUtil.findObj(obj, field);
+ }
+
+ protected JsonObject computeObj(String field) {
+ return findObj(field).orElseGet(JsonObject::new);
+ }
+
+ protected Optional findArray(String field) {
+ return GsonUtil.findArray(obj, field);
+ }
+
+ public JsonObject getJson() {
+ return obj;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java b/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java
new file mode 100644
index 0000000..cf61304
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomAliasLookupJson.java
@@ -0,0 +1,46 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import java.util.List;
+
+public class RoomAliasLookupJson {
+
+ private String roomId;
+ private List servers;
+
+ public String getRoomId() {
+ return roomId;
+ }
+
+ public void setRoomId(String roomId) {
+ this.roomId = roomId;
+ }
+
+ public List getServers() {
+ return servers;
+ }
+
+ public void setServers(List servers) {
+ this.servers = servers;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java b/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java
new file mode 100644
index 0000000..724a146
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomCreationRequestJson.java
@@ -0,0 +1,57 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.JsonElement;
+
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.room._RoomCreationOptions;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class RoomCreationRequestJson {
+
+ private String visibility;
+ private String roomAliasName;
+ private String name;
+ private String topic;
+ private Set invite;
+ private Map creationContent;
+ private String preset;
+ private Boolean isDirect;
+ private Boolean guestCanJoin;
+
+ public RoomCreationRequestJson(_RoomCreationOptions options) {
+ this.visibility = options.getVisibility().orElse(null);
+ this.roomAliasName = options.getAliasName().orElse(null);
+ this.name = options.getName().orElse(null);
+ this.topic = options.getTopic().orElse(null);
+ this.invite = options.getInvites().filter(ids -> !ids.isEmpty())
+ .map(ids -> ids.stream().map(_MatrixID::getId).collect(Collectors.toSet())).orElse(null);
+ this.creationContent = options.getCreationContent().filter(c -> !c.isEmpty()).orElse(null);
+ this.preset = options.getPreset().orElse(null);
+ this.isDirect = options.isDirect().orElse(null);
+ this.guestCanJoin = options.isGuestCanJoin().orElse(null);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java b/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java
new file mode 100644
index 0000000..7bf9de6
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomCreationResponseJson.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class RoomCreationResponseJson {
+
+ private String roomId;
+
+ public String getRoomId() {
+ return roomId;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java b/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java
new file mode 100644
index 0000000..5151c48
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomMessageChunkResponseJson.java
@@ -0,0 +1,45 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+import com.google.gson.JsonObject;
+
+import java.util.List;
+
+public class RoomMessageChunkResponseJson {
+
+ private String start;
+ private String end;
+ private List chunk;
+
+ public String getStart() {
+ return start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ public List getChunk() {
+ return chunk;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java b/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java
new file mode 100644
index 0000000..05713d4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomMessageFormattedTextPutBody.java
@@ -0,0 +1,48 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class RoomMessageFormattedTextPutBody extends RoomMessageTextPutBody {
+
+ private String formatted_body;
+ private String format = "org.matrix.custom.html";
+
+ public RoomMessageFormattedTextPutBody(String body, String formattedBody) {
+ super(body);
+
+ this.formatted_body = formattedBody;
+ }
+
+ public RoomMessageFormattedTextPutBody(String msgtype, String body, String formattedBody) {
+ super(msgtype, body);
+
+ this.formatted_body = formattedBody;
+ }
+
+ public String getFormatted_body() {
+ return formatted_body;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java b/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java
new file mode 100644
index 0000000..5683c00
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomMessageTextPutBody.java
@@ -0,0 +1,45 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class RoomMessageTextPutBody {
+
+ private String msgtype = "m.text";
+ private String body;
+
+ public RoomMessageTextPutBody(String body) {
+ this.body = body;
+ }
+
+ public RoomMessageTextPutBody(String msgType, String body) {
+ this(body);
+ this.msgtype = msgType;
+ }
+
+ public String getMsgtype() {
+ return msgtype;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/RoomTagSetBody.java b/src/main/java/io/kamax/matrix/json/RoomTagSetBody.java
new file mode 100644
index 0000000..c791998
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/RoomTagSetBody.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class RoomTagSetBody {
+
+ private String order;
+
+ public RoomTagSetBody(double order) {
+ this.order = String.valueOf(order);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java b/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java
new file mode 100644
index 0000000..9b5f73c
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/UserDisplaynameSetBody.java
@@ -0,0 +1,31 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class UserDisplaynameSetBody {
+
+ private String displayname;
+
+ public UserDisplaynameSetBody(String displayname) {
+ this.displayname = displayname;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java b/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java
new file mode 100644
index 0000000..9b12237
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/VirtualUserRegistrationBody.java
@@ -0,0 +1,40 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json;
+
+public class VirtualUserRegistrationBody {
+
+ private String type = "m.login.application_server";
+ private String username;
+
+ public VirtualUserRegistrationBody(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonDirectEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonDirectEvent.java
new file mode 100644
index 0000000..e73c1fc
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonDirectEvent.java
@@ -0,0 +1,63 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.event._DirectEvent;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.InvalidJsonException;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MatrixJsonDirectEvent extends MatrixJsonEphemeralEvent implements _DirectEvent {
+
+ private Map<_MatrixID, List> mappings = new HashMap<>();
+
+ public MatrixJsonDirectEvent(JsonObject obj) {
+ super(obj);
+
+ if (!StringUtils.equals(Type, getType())) { // FIXME check should be done in the abstract class
+ throw new InvalidJsonException("Type is not " + Type);
+ }
+
+ getObj("content").entrySet().forEach(entry -> {
+ if (!entry.getValue().isJsonArray()) {
+ throw new InvalidJsonException("Content key " + entry.getKey() + " is not an array");
+ }
+ _MatrixID id = MatrixID.asAcceptable(entry.getKey());
+ mappings.put(id, GsonUtil.asList(entry.getValue().getAsJsonArray(), String.class));
+ });
+ }
+
+ @Override
+ public Map<_MatrixID, List> getMappings() {
+ return Collections.unmodifiableMap(mappings);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonEphemeralEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonEphemeralEvent.java
new file mode 100644
index 0000000..d3e6bf4
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonEphemeralEvent.java
@@ -0,0 +1,43 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._MatrixEphemeralEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+public class MatrixJsonEphemeralEvent extends MatrixJsonObject implements _MatrixEphemeralEvent {
+
+ private String type;
+
+ public MatrixJsonEphemeralEvent(JsonObject obj) {
+ super(obj);
+ type = getString("type");
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonPersistentEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonPersistentEvent.java
new file mode 100644
index 0000000..fa231c3
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonPersistentEvent.java
@@ -0,0 +1,68 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.event._MatrixPersistentEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+public class MatrixJsonPersistentEvent extends MatrixJsonObject implements _MatrixPersistentEvent {
+
+ private String id;
+ private String type;
+ private Long time;
+ private int age;
+ private _MatrixID sender;
+
+ public MatrixJsonPersistentEvent(JsonObject obj) {
+ super(obj);
+
+ id = getString("event_id");
+ type = getString("type");
+ time = getLong("origin_server_ts");
+ age = getInt("age", -1);
+ sender = MatrixID.asAcceptable(getString("sender"));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public Long getTime() {
+ return time;
+ }
+
+ @Override
+ public _MatrixID getSender() {
+ return sender;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonReadReceiptEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonReadReceiptEvent.java
new file mode 100644
index 0000000..84c7e10
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonReadReceiptEvent.java
@@ -0,0 +1,95 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix.event._ReadReceiptEvent;
+import io.kamax.matrix.json.GsonUtil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class MatrixJsonReadReceiptEvent extends MatrixJsonEphemeralEvent implements _ReadReceiptEvent {
+
+ /**
+ * Read receipts for a specific event.
+ */
+ public static class Receipt {
+ /**
+ * ID of the event, the read markers point to.
+ */
+ private String eventId;
+
+ /**
+ * Every user whose read marker is set to the event specified by eventId
+ * and it's point in time when this marker has been set to this event.
+ */
+ private Map users;
+
+ public Receipt(String id, Map readMarkers) {
+ this.eventId = id;
+ this.users = readMarkers;
+ }
+
+ public Map getUsersWithTimestamp() {
+ return users;
+ }
+
+ public Set getUsers() {
+ return users.keySet();
+ }
+
+ public String getEventId() {
+ return eventId;
+ }
+ }
+
+ private List receipts;
+
+ @Override
+ public List getReceipts() {
+ return receipts;
+ }
+
+ public MatrixJsonReadReceiptEvent(JsonObject obj) {
+ super(obj);
+
+ JsonObject content = getObj("content");
+ List eventIds = content.entrySet().stream().map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+
+ receipts = eventIds.stream().map(id -> {
+ JsonObject targetEvent = content.getAsJsonObject(id);
+ JsonObject mRead = targetEvent.getAsJsonObject("m.read");
+
+ Map readMarkers = mRead.entrySet().stream()
+ .collect(Collectors.toMap(it -> MatrixID.asAcceptable(it.getKey()),
+ it -> GsonUtil.getLong(it.getValue().getAsJsonObject(), "ts")));
+ return new Receipt(id, readMarkers);
+ }).collect(Collectors.toList());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAliasesEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAliasesEvent.java
new file mode 100644
index 0000000..9756706
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAliasesEvent.java
@@ -0,0 +1,66 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomAliasesEvent;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.Collections;
+import java.util.List;
+
+public class MatrixJsonRoomAliasesEvent extends MatrixJsonRoomEvent implements _RoomAliasesEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private List aliases;
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ setAliases(GsonUtil.asList(obj, "aliases", String.class));
+ }
+
+ public List getAliases() {
+ return aliases;
+ }
+
+ public void setAliases(List aliases) {
+ this.aliases = aliases;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomAliasesEvent(JsonObject obj) {
+ super(obj);
+ this.content = new Content(getObj("content"));
+ }
+
+ @Override
+ public List getAliases() {
+ return Collections.unmodifiableList(content.getAliases());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAvatarEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAvatarEvent.java
new file mode 100644
index 0000000..a843e74
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomAvatarEvent.java
@@ -0,0 +1,56 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomAvatarEvent;
+import io.kamax.matrix.json.GsonUtil;
+
+public class MatrixJsonRoomAvatarEvent extends MatrixJsonRoomEvent implements _RoomAvatarEvent {
+
+ public static class Content {
+
+ private String url;
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomAvatarEvent(JsonObject obj) {
+ super(obj);
+ this.content = GsonUtil.get().fromJson(getObj("content"), Content.class);
+ }
+
+ @Override
+ public String getUrl() {
+ return content.getUrl();
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomCanonicalAliasEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomCanonicalAliasEvent.java
new file mode 100644
index 0000000..082346f
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomCanonicalAliasEvent.java
@@ -0,0 +1,76 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomCanonicalAliasEvent;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Optional;
+
+public class MatrixJsonRoomCanonicalAliasEvent extends MatrixJsonRoomEvent implements _RoomCanonicalAliasEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private String alias;
+
+ public Content(JsonObject content) {
+ super(content);
+ findString("alias").filter(StringUtils::isNotEmpty).ifPresent(this::setAlias);
+ }
+
+ public String getAlias() {
+ return alias;
+ }
+
+ public void setAlias(String alias) {
+ this.alias = alias;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomCanonicalAliasEvent(JsonObject obj) {
+ super(obj);
+
+ if (!StringUtils.equals(Type, getType())) { // FIXME check should be done in the abstract class
+ throw new IllegalArgumentException("Type is not " + Type);
+ }
+
+ this.content = new Content(GsonUtil.getObj(obj, "content"));
+ }
+
+ @Override
+ public boolean hasAlias() {
+ return StringUtils.isNotEmpty(content.getAlias());
+ }
+
+ @Override
+ public Optional getAlias() {
+ return Optional.ofNullable(content.getAlias());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java
new file mode 100644
index 0000000..93ca948
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomEvent.java
@@ -0,0 +1,42 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomEvent;
+
+public class MatrixJsonRoomEvent extends MatrixJsonPersistentEvent implements _RoomEvent {
+
+ private String roomId;
+
+ public MatrixJsonRoomEvent(JsonObject obj) {
+ super(obj);
+
+ roomId = getString("room_id");
+ }
+
+ @Override
+ public String getRoomId() {
+ return roomId;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomHistoryVisibilityEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomHistoryVisibilityEvent.java
new file mode 100644
index 0000000..2b06c01
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomHistoryVisibilityEvent.java
@@ -0,0 +1,62 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomHistoryVisibilityEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+public class MatrixJsonRoomHistoryVisibilityEvent extends MatrixJsonRoomEvent implements _RoomHistoryVisibilityEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private String historyVisibility;
+
+ public Content(JsonObject obj) {
+ super(obj);
+ setHistoryVisibility(getString("history_visibility"));
+ }
+
+ public String getHistoryVisibility() {
+ return historyVisibility;
+ }
+
+ public void setHistoryVisibility(String historyVisibility) {
+ this.historyVisibility = historyVisibility;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomHistoryVisibilityEvent(JsonObject obj) {
+ super(obj);
+
+ content = new Content(getObj("content"));
+ }
+
+ @Override
+ public String getHistoryVisibility() {
+ return content.getHistoryVisibility();
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java
new file mode 100644
index 0000000..d8615ef
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMembershipEvent.java
@@ -0,0 +1,104 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.MatrixID;
+import io.kamax.matrix._MatrixID;
+import io.kamax.matrix.event._RoomMembershipEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.Optional;
+
+public class MatrixJsonRoomMembershipEvent extends MatrixJsonRoomEvent implements _RoomMembershipEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private String membership;
+ private String avatar;
+ private String displayName;
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ setMembership(getString("membership"));
+ setAvatar(avatar = getStringOrNull("avatar_url"));
+ setDisplayName(displayName = getStringOrNull("displayname"));
+ }
+
+ public String getMembership() {
+ return membership;
+ }
+
+ public void setMembership(String membership) {
+ this.membership = membership;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ }
+
+ protected Content content;
+ private _MatrixID invitee;
+
+ public MatrixJsonRoomMembershipEvent(JsonObject obj) {
+ super(obj);
+
+ content = new Content(getObj("content"));
+ invitee = new MatrixID(getString("state_key"));
+ }
+
+ @Override
+ public String getMembership() {
+ return content.getMembership();
+ }
+
+ @Override
+ public Optional getAvatarUrl() {
+ return Optional.ofNullable(content.getAvatar());
+ }
+
+ @Override
+ public Optional getDisplayName() {
+ return Optional.ofNullable(content.getDisplayName());
+ }
+
+ @Override
+ public _MatrixID getInvitee() {
+ return invitee;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java
new file mode 100644
index 0000000..e19b97b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomMessageEvent.java
@@ -0,0 +1,60 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2017 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomMessageEvent;
+import io.kamax.matrix.json.GsonUtil;
+
+import java.util.Optional;
+
+public class MatrixJsonRoomMessageEvent extends MatrixJsonRoomEvent implements _RoomMessageEvent {
+
+ protected JsonObject content;
+
+ public MatrixJsonRoomMessageEvent(JsonObject obj) {
+ super(obj);
+
+ this.content = obj.getAsJsonObject("content");
+ }
+
+ @Override
+ public String getBody() {
+ return content.get("body").getAsString();
+ }
+
+ @Override
+ public String getBodyType() {
+ return content.has("msgtype") ? content.get("msgtype").getAsString() : null;
+ }
+
+ @Override
+ public Optional getFormat() {
+ return GsonUtil.findString(content, "format");
+ }
+
+ @Override
+ public Optional getFormattedBody() {
+ return GsonUtil.findString(content, "formatted_body");
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomNameEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomNameEvent.java
new file mode 100644
index 0000000..6aff318
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomNameEvent.java
@@ -0,0 +1,64 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomNameEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.Optional;
+
+public class MatrixJsonRoomNameEvent extends MatrixJsonRoomEvent implements _RoomNameEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private String name;
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ setName(getStringOrNull("name"));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomNameEvent(JsonObject obj) {
+ super(obj);
+ this.content = new Content(getObj("content"));
+ }
+
+ @Override
+ public Optional getName() {
+ return Optional.ofNullable(content.getName());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomPowerLevelsEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomPowerLevelsEvent.java
new file mode 100644
index 0000000..dce6ce6
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomPowerLevelsEvent.java
@@ -0,0 +1,200 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomPowerLevelsEvent;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class MatrixJsonRoomPowerLevelsEvent extends MatrixJsonRoomEvent implements _RoomPowerLevelsEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private Double ban;
+ private Map events = new HashMap<>();
+ private Double eventsDefault;
+ private Double invite;
+ private Double kick;
+ private Double redact;
+ private Double stateDefault;
+ private Map users = new HashMap<>();
+ private Double usersDefault;
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ setBan(getDoubleIfPresent("ban"));
+ setEventsDefault(getDoubleIfPresent("events_default"));
+ setInvite(getDoubleIfPresent("invite"));
+ setKick(getDoubleIfPresent("kick"));
+ setRedact(getDoubleIfPresent("redact"));
+ setStateDefault(getDoubleIfPresent("state_default"));
+ setUsersDefault(getDoubleIfPresent("users_default"));
+
+ GsonUtil.findObj(obj, "events").ifPresent(eventsJson -> {
+ Map eventsMap = eventsJson.entrySet().stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, it -> it.getValue().getAsDouble()));
+ setEvents(eventsMap);
+ });
+
+ GsonUtil.findObj(obj, "users").ifPresent(usersJson -> {
+ Map usersMap = usersJson.entrySet().stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, it -> it.getValue().getAsDouble()));
+ setUsers(usersMap);
+ });
+ }
+
+ public Double getBan() {
+ return ban;
+ }
+
+ public void setBan(Double ban) {
+ this.ban = ban;
+ }
+
+ public Double getEventsDefault() {
+ return eventsDefault;
+ }
+
+ public void setEventsDefault(Double eventsDefault) {
+ this.eventsDefault = eventsDefault;
+ }
+
+ public Map getEvents() {
+ return events;
+ }
+
+ public void setEvents(Map events) {
+ this.events.putAll(events);
+ }
+
+ public Double getInvite() {
+ return invite;
+ }
+
+ public void setInvite(Double invite) {
+ this.invite = invite;
+ }
+
+ public Double getKick() {
+ return kick;
+ }
+
+ public void setKick(Double kick) {
+ this.kick = kick;
+ }
+
+ public Double getRedact() {
+ return redact;
+ }
+
+ public void setRedact(Double redact) {
+ this.redact = redact;
+ }
+
+ public Double getStateDefault() {
+ return stateDefault;
+ }
+
+ public void setStateDefault(Double stateDefault) {
+ this.stateDefault = stateDefault;
+ }
+
+ public Map getUsers() {
+ return users;
+ }
+
+ public void setUsers(Map users) {
+ this.users.putAll(users);
+ }
+
+ public Double getUsersDefault() {
+ return usersDefault;
+ }
+
+ public void setUsersDefault(Double usersDefault) {
+ this.usersDefault = usersDefault;
+ }
+
+ }
+
+ protected Content content;
+
+ public MatrixJsonRoomPowerLevelsEvent(JsonObject obj) {
+ super(obj);
+
+ content = new Content(getObj("content"));
+ }
+
+ @Override
+ public Optional getBan() {
+ return Optional.ofNullable(content.getBan());
+ }
+
+ @Override
+ public Map getEvents() {
+ return Collections.unmodifiableMap(content.getEvents());
+ }
+
+ @Override
+ public Optional getEventsDefault() {
+ return Optional.ofNullable(content.getEventsDefault());
+ }
+
+ @Override
+ public Optional getInvite() {
+ return Optional.ofNullable(content.getInvite());
+ }
+
+ @Override
+ public Optional getKick() {
+ return Optional.ofNullable(content.getKick());
+ }
+
+ @Override
+ public Optional getRedact() {
+ return Optional.ofNullable(content.getRedact());
+ }
+
+ @Override
+ public Optional getStateDefault() {
+ return Optional.ofNullable(content.getStateDefault());
+ }
+
+ @Override
+ public Map getUsers() {
+ return Collections.unmodifiableMap(content.getUsers());
+ }
+
+ @Override
+ public Optional getUsersDefault() {
+ return Optional.ofNullable(content.getUsersDefault());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTagsEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTagsEvent.java
new file mode 100644
index 0000000..3bea88b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTagsEvent.java
@@ -0,0 +1,98 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Arne Augenstein
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._TagsEvent;
+import io.kamax.matrix.json.GsonUtil;
+import io.kamax.matrix.json.MatrixJsonObject;
+import io.kamax.matrix.room.Tag;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MatrixJsonRoomTagsEvent extends MatrixJsonObject implements _TagsEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private List tags = new ArrayList<>();
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ GsonUtil.findObj(obj, "tags").ifPresent(tagsJson -> {
+ List tags = tagsJson.entrySet().stream().map(it -> {
+ String completeName = it.getKey();
+ String name = completeName;
+ String namespace = "";
+
+ int lastDotIndex = completeName.lastIndexOf(".");
+
+ if (lastDotIndex >= 0 && lastDotIndex < completeName.length() - 1) {
+ namespace = completeName.substring(0, lastDotIndex);
+ name = completeName.substring(lastDotIndex + 1);
+ }
+
+ JsonElement jsonOrder = it.getValue().getAsJsonObject().get("order");
+
+ if (jsonOrder != null) {
+ return new Tag(namespace, name, jsonOrder.getAsDouble());
+ }
+ return new Tag(namespace, name, null);
+ }).collect(Collectors.toList());
+ setTags(tags);
+ });
+ }
+
+ public List getTags() {
+ return tags;
+ }
+
+ public void setTags(List tags) {
+ this.tags = new ArrayList<>(tags);
+ }
+
+ }
+
+ private String type;
+ protected Content content;
+
+ public MatrixJsonRoomTagsEvent(JsonObject obj) {
+ super(obj);
+ type = getString("type");
+ content = new Content(getObj("content"));
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public List getTags() {
+ return Collections.unmodifiableList(content.getTags());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTopicEvent.java b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTopicEvent.java
new file mode 100644
index 0000000..f7c62de
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/json/event/MatrixJsonRoomTopicEvent.java
@@ -0,0 +1,64 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.json.event;
+
+import com.google.gson.JsonObject;
+
+import io.kamax.matrix.event._RoomTopicEvent;
+import io.kamax.matrix.json.MatrixJsonObject;
+
+import java.util.Optional;
+
+public class MatrixJsonRoomTopicEvent extends MatrixJsonRoomEvent implements _RoomTopicEvent {
+
+ public static class Content extends MatrixJsonObject {
+
+ private String topic;
+
+ public Content(JsonObject obj) {
+ super(obj);
+
+ setTopic(getStringOrNull("topic"));
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public void setTopic(String topic) {
+ this.topic = topic;
+ }
+
+ }
+
+ private Content content;
+
+ public MatrixJsonRoomTopicEvent(JsonObject obj) {
+ super(obj);
+ this.content = new Content(getObj("content"));
+ }
+
+ @Override
+ public Optional getTopic() {
+ return Optional.ofNullable(content.getTopic());
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java
new file mode 100644
index 0000000..7a1048c
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunk.java
@@ -0,0 +1,54 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+import io.kamax.matrix.event._MatrixPersistentEvent;
+
+import java.util.List;
+
+public class MatrixRoomMessageChunk implements _MatrixRoomMessageChunk {
+
+ private String startToken;
+ private String endToken;
+ private List<_MatrixPersistentEvent> events;
+
+ public MatrixRoomMessageChunk(String startToken, String endToken, List<_MatrixPersistentEvent> events) {
+ this.startToken = startToken;
+ this.endToken = endToken;
+ this.events = events;
+ }
+
+ @Override
+ public String getStartToken() {
+ return startToken;
+ }
+
+ @Override
+ public String getEndToken() {
+ return endToken;
+ }
+
+ @Override
+ public List<_MatrixPersistentEvent> getEvents() {
+ return events;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java
new file mode 100644
index 0000000..6e0ad25
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/MatrixRoomMessageChunkOptions.java
@@ -0,0 +1,94 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+import java.util.Optional;
+
+public class MatrixRoomMessageChunkOptions implements _MatrixRoomMessageChunkOptions {
+
+ public static class Builder {
+
+ private MatrixRoomMessageChunkOptions obj;
+
+ public Builder() {
+ this.obj = new MatrixRoomMessageChunkOptions();
+ }
+
+ public Builder setFromToken(String token) {
+ obj.from = token;
+ return this;
+ }
+
+ public Builder setToToken(String token) {
+ obj.to = token;
+ return this;
+ }
+
+ public Builder setDirection(String direction) {
+ obj.dir = direction;
+ return this;
+ }
+
+ public Builder setDirection(_MatrixRoomMessageChunkOptions.Direction direction) {
+ return setDirection(direction.get());
+ }
+
+ public Builder setLimit(long limit) {
+ obj.limit = limit;
+ return this;
+ }
+
+ public MatrixRoomMessageChunkOptions get() {
+ return obj;
+ }
+
+ }
+
+ public static Builder build() {
+ return new Builder();
+ }
+
+ private String from;
+ private String to;
+ private String dir;
+ private Long limit;
+
+ @Override
+ public String getFromToken() {
+ return from;
+ }
+
+ @Override
+ public Optional getToToken() {
+ return Optional.ofNullable(to);
+ }
+
+ @Override
+ public String getDirection() {
+ return dir;
+ }
+
+ @Override
+ public Optional getLimit() {
+ return Optional.ofNullable(limit);
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/ReceiptType.java b/src/main/java/io/kamax/matrix/room/ReceiptType.java
new file mode 100644
index 0000000..801713b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/ReceiptType.java
@@ -0,0 +1,37 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+public enum ReceiptType {
+
+ Read("m.read");
+
+ private String id;
+
+ ReceiptType(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/RoomAlias.java b/src/main/java/io/kamax/matrix/room/RoomAlias.java
new file mode 100644
index 0000000..8294963
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/RoomAlias.java
@@ -0,0 +1,82 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class RoomAlias {
+
+ private static final String sigill = "#";
+ private static final Pattern idPattern = Pattern.compile(sigill + "(.+?):(.+)");
+
+ private String id;
+ private String localpart;
+ private String domain;
+
+ public static RoomAlias from(String localpart, String domain) {
+ return from(sigill + localpart + ":" + domain);
+ }
+
+ public static RoomAlias from(String id) {
+ if (id.length() > 255) {
+ throw new IllegalArgumentException("Room aliases cannot be longer than 255 characters");
+ }
+
+ Matcher m = idPattern.matcher(id);
+ if (!m.matches()) {
+ throw new IllegalArgumentException(id + " is not a valid Room alias");
+ }
+
+ RoomAlias r = new RoomAlias();
+ r.id = id;
+ r.localpart = m.group(1);
+ r.domain = m.group(2);
+
+ return r;
+ }
+
+ public static boolean is(String id) {
+ try {
+ from(id);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ private RoomAlias() {
+ // cannot instantiate directly
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getLocalpart() {
+ return localpart;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java b/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java
new file mode 100644
index 0000000..4444689
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/RoomAliasLookup.java
@@ -0,0 +1,41 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class RoomAliasLookup extends RoomAliasMapping implements _RoomAliasLookup {
+
+ private List servers;
+
+ public RoomAliasLookup(String id, String alias, Collection servers) {
+ super(id, alias);
+ this.servers = new ArrayList<>(servers);
+ }
+
+ @Override
+ public List getServers() {
+ return servers;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java b/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java
new file mode 100644
index 0000000..d9032b2
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/RoomAliasMapping.java
@@ -0,0 +1,43 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sàrl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+public class RoomAliasMapping implements _RoomAliasMapping {
+
+ private String id;
+ private String alias;
+
+ public RoomAliasMapping(String id, String alias) {
+ this.id = id;
+ this.alias = alias;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getAlias() {
+ return alias;
+ }
+
+}
diff --git a/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java b/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java
new file mode 100644
index 0000000..810f15b
--- /dev/null
+++ b/src/main/java/io/kamax/matrix/room/RoomCreationOptions.java
@@ -0,0 +1,161 @@
+/*
+ * matrix-java-sdk - Matrix Client SDK for Java
+ * Copyright (C) 2018 Kamax Sarl
+ *
+ * https://www.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.matrix.room;
+
+import com.google.gson.JsonElement;
+
+import io.kamax.matrix._MatrixID;
+
+import java.util.*;
+import java.util.Optional;
+
+public class RoomCreationOptions implements _RoomCreationOptions {
+
+ public static class Builder {
+
+ private RoomCreationOptions obj;
+
+ public Builder() {
+ this.obj = new RoomCreationOptions();
+ }
+
+ public Builder setVisibility(String visibility) {
+ obj.visibility = visibility;
+ return this;
+ }
+
+ public Builder setVisibility(RoomDirectoryVisibility visibility) {
+ return setVisibility(visibility.get());
+ }
+
+ public Builder setAliasName(String aliasName) {
+ obj.aliasName = aliasName;
+ return this;
+ }
+
+ public Builder setName(String name) {
+ obj.name = name;
+ return this;
+ }
+
+ public Builder setTopic(String topic) {
+ obj.topic = topic;
+ return this;
+ }
+
+ public Builder setInvites(Set<_MatrixID> invites) {
+ obj.invites = Collections.unmodifiableSet(new HashSet<>(invites));
+ return this;
+ }
+
+ public Builder setCreationContent(Map creationContent) {
+ obj.creationContent = Collections.unmodifiableMap(new HashMap<>(creationContent));
+ return this;
+ }
+
+ public Builder setPreset(String preset) {
+ obj.preset = preset;
+ return this;
+ }
+
+ public Builder setPreset(RoomCreationPreset preset) {
+ return setPreset(preset.get());
+ }
+
+ public Builder setDirect(boolean isDirect) {
+ obj.isDirect = isDirect;
+ return this;
+ }
+
+ public Builder setGuestCanJoin(boolean guestCanJoin) {
+ obj.guestCanJoin = guestCanJoin;
+ return this;
+ }
+
+ public RoomCreationOptions get() {
+ return obj;
+ }
+ }
+
+ public static Builder build() {
+ return new Builder();
+ }
+
+ public static RoomCreationOptions none() {
+ return build().get();
+ }
+
+ private String visibility;
+ private String aliasName;
+ private String name;
+ private String topic;
+ private Set<_MatrixID> invites = new HashSet<>();
+ private Map creationContent = new HashMap<>();
+ private String preset;
+ private Boolean isDirect;
+ private Boolean guestCanJoin;
+
+ @Override
+ public Optional getVisibility() {
+ return Optional.ofNullable(visibility);
+ }
+
+ @Override
+ public Optional getAliasName() {
+ return Optional.ofNullable(aliasName);
+ }
+
+ @Override
+ public Optional getName() {
+ return Optional.ofNullable(name);
+ }
+
+ @Override
+ public Optional getTopic() {
+ return Optional.ofNullable(topic);
+ }
+
+ @Override
+ public Optional> getInvites() {
+ return Optional.ofNullable(invites);
+ }
+
+ @Override
+ public Optional