software.amazon.jsii.JsiiObjectRef Maven / Gradle / Ivy
package software.amazon.jsii;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.jetbrains.annotations.VisibleForTesting;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Represents a remote jsii object reference.
*/
@Internal
public final class JsiiObjectRef {
/**
* The JSON key used to represent an object reference.
*/
static final String TOKEN_REF = "$jsii.byref";
/**
* The JSON key used to represent an interface list.
*/
static final String TOKEN_INTERFACES = "$jsii.interfaces";
/**
* The JSON node.
*/
private JsonNode node;
/**
* The object ID.
*/
private String objId;
/**
* The FQN of the object's type as parsed from the object ID.
*/
private String fqn;
private Set interfaces;
/**
* Private constructor.
* @param objId The object id.
* @param node The JSON node that includes the objref.
*/
private JsiiObjectRef(final String objId, final JsonNode node) {
this(objId, node.has(TOKEN_INTERFACES)
? parseInterfaces(node.get(TOKEN_INTERFACES))
: Collections.emptySet(), node);
}
@VisibleForTesting
JsiiObjectRef(final String objId, final Set interfaces) {
this(objId, interfaces, JsiiObjectRef.makeJson(objId, interfaces));
}
private JsiiObjectRef(final String objId, final Set interfaces, final JsonNode node) {
this.objId = objId;
int fqnDelimiter = this.objId.lastIndexOf("@");
this.fqn = this.objId.substring(0, fqnDelimiter);
this.interfaces = interfaces;
this.node = node;
}
/**
* Creates an object reference.
* @param objRef The object reference.
* @return A {@link JsiiObjectRef} object.
*/
public static JsiiObjectRef parse(final JsonNode objRef) {
if (!objRef.has(TOKEN_REF)) {
throw new JsiiError("Malformed object reference. Expecting " + TOKEN_REF);
}
return new JsiiObjectRef(objRef.get(TOKEN_REF).textValue(), objRef);
}
/**
* Creates an object ref from an object ID.
* @param objId Object ID.
* @return The new object ref.
*/
public static JsiiObjectRef fromObjId(final String objId) {
ObjectNode node = JsonNodeFactory.instance.objectNode();
node.put(TOKEN_REF, objId);
return new JsiiObjectRef(objId, node);
}
JsiiObjectRef withInterface(final String fqn) {
final Set interfaces = new HashSet<>(this.interfaces);
interfaces.add(fqn);
return new JsiiObjectRef(this.objId, interfaces);
}
private static JsonNode makeJson(final String objId, final Set interfaces) {
final ObjectNode node = JsonNodeFactory.instance.objectNode();
node.put(TOKEN_REF, objId);
final ArrayNode jsonInterfaces = JsonNodeFactory.instance.arrayNode();
for (final String iface : interfaces) {
jsonInterfaces.add(JsonNodeFactory.instance.textNode(iface));
}
node.set(TOKEN_INTERFACES, jsonInterfaces);
return node;
}
private static Set parseInterfaces(final JsonNode node) {
if (!node.isArray()) {
throw new Error(String.format("Invalid value for %s. Expected array but received %s", TOKEN_INTERFACES, node));
}
final Set result = new HashSet<>();
node.forEach(entry -> {
if (!entry.isTextual()) {
throw new Error(String.format("Invalid entry in %s. Expected only strings, but received %s", TOKEN_INTERFACES, entry));
}
result.add(entry.asText());
});
return Collections.unmodifiableSet(result);
}
/**
* @return The jsii FQN (fully qualified name) of the object's type.
*/
public String getFqn() {
return fqn;
}
/**
* @return The JSON node for this objref.
*/
public JsonNode toJson() {
return node;
}
/**
* @return The object ID.
*/
public String getObjId() {
return objId;
}
/**
* @return the lsit of interfaces implemented by the object
*/
public Set getInterfaces() {
return interfaces;
}
@Override
public String toString() {
return objId;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || !(obj instanceof JsiiObjectRef)) {
return false;
}
final JsiiObjectRef other = (JsiiObjectRef) obj;
return this.objId.equals(other.objId);
}
@Override
public int hashCode() {
return this.objId.hashCode();
}
}