
clarifai2.api.request.input.SearchClause Maven / Gradle / Ivy
Show all versions of core Show documentation
package clarifai2.api.request.input;
import clarifai2.internal.grpc.api.ConceptOuterClass;
import clarifai2.internal.grpc.api.DataOuterClass;
import clarifai2.internal.grpc.api.GeoOuterClass;
import clarifai2.internal.grpc.api.ImageOuterClass;
import clarifai2.internal.grpc.api.InputOuterClass;
import clarifai2.internal.grpc.api.OutputOuterClass;
import clarifai2.internal.grpc.api.Search;
import clarifai2.dto.PointF;
import clarifai2.dto.Radius;
import clarifai2.dto.Rectangle;
import clarifai2.dto.input.ClarifaiImage;
import clarifai2.dto.input.ClarifaiInput;
import clarifai2.dto.input.ClarifaiURLImage;
import clarifai2.dto.prediction.Concept;
import clarifai2.exception.ClarifaiException;
import clarifai2.grpc.JsonMarshaller;
import clarifai2.grpc.MetadataConverter;
import clarifai2.internal.JSONAdapterFactory;
import clarifai2.internal.JSONArrayBuilder;
import clarifai2.internal.JSONObjectBuilder;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Struct;
import com.google.protobuf.util.JsonFormat;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static clarifai2.internal.InternalUtil.asGeoPointJson;
import static clarifai2.internal.InternalUtil.asGeoPointProto;
import static clarifai2.internal.InternalUtil.toJson;
public abstract class SearchClause {
private SearchClause() {}
/**
* A search clause that will match inputs that had metadata that matches the metadata on the given
* {@link ClarifaiInput}
*
* @param input the input whose metadata to search by
* @return a {@link SearchClause} to be given to a search endpoint
* @see #matchMetadata(JsonObject)
*/
@NotNull public static SearchClause matchMetadata(@NotNull ClarifaiInput input) {
return matchMetadata(input.metadata());
}
/**
* A search clause that will match inputs that had metadata that matches the given metadata
*
* @param metadata the metadata to search by
* @return a {@link SearchClause} to be given to a search endpoint
*/
@NotNull public static SearchClause matchMetadata(@NotNull JsonObject metadata) {
return new Metadata(metadata);
}
/**
* A search clause that will match inputs that had images with the given URL
*
* This is NOT a visual similarity search. This is a simple string-search for the given image's URL. For visual
* similarity, please use {@link #matchImageVisually(ClarifaiImage)}.
*
* @param image the URL of the image to search by
* @return a {@link SearchClause} to be given to a search endpoint
*/
@NotNull public static SearchClause matchImageURL(@NotNull ClarifaiURLImage image) {
return new InputImage(image);
}
/**
* A search clause that will match inputs that are visually similar to the image with the given URL.
*
* This method is different from {@link #matchImageURL(ClarifaiURLImage)}, which also takes an image,
* but matches inputs that share that image's URL.
*
* @param image the URL of the image to search by
* @return a {@link SearchClause} to be given to a search endpoint
*/
@NotNull public static SearchClause matchImageVisually(@NotNull ClarifaiImage image) {
return new OutputImage(image);
}
/**
* A search clause that will match inputs that the user explicitly tagged with the given concept
*
* Both this method and the related {@link #matchConcept(Concept)} will match inputs that
* the user explicitly tagged with these concepts when uploading the input, but
* {@link #matchConcept(Concept)} will also match inputs that the API predicted to
* contain these concepts.
*
* @param concept the concept to search by
* @return a {@link SearchClause} to be given to a search endpoint
*/
@NotNull public static SearchClause matchUserTaggedConcept(@NotNull Concept concept) {
return new SearchConcept("input", concept);
}
/**
* A search clause that will match inputs both by concepts that the user tagged them with explicitly, and by concepts
* that the API predicted upon the inputs.
*
* This is similar to {@link #matchUserTaggedConcept(Concept)} in that both will match
* images that the user explicitly tagged with these concepts when uploading the input, but this method will also
* match inputs that the API predicted to contain these concepts.
*
* @param concept the concept to search by
* @return a {@link SearchClause} to be given to a search endpoint
*/
@NotNull public static SearchClause matchConcept(@NotNull Concept concept) {
return new SearchConcept("output", concept);
}
@NotNull public static SearchClause matchGeo(@NotNull final PointF center, @NotNull final Radius radius) {
return new GeoCircle(center, radius);
}
@NotNull public static SearchClause matchGeo(@NotNull final PointF topLeft, @NotNull final PointF bottomRight) {
return new GeoRect(topLeft, bottomRight);
}
@NotNull public abstract Search.And serialize();
@JsonAdapter(Metadata.Adapter.class)
static class Metadata extends SearchClause {
@NotNull private final JsonObject metadata;
private Metadata(@NotNull JsonObject metadata) {
this.metadata = metadata;
}
@NotNull @Override public Search.And serialize() {
return Search.And.newBuilder().setInput(
InputOuterClass.Input.newBuilder()
.setData(DataOuterClass.Data.newBuilder().setMetadata(MetadataConverter.jsonObjectToStruct(metadata)))
).build();
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(@Nullable Metadata value, @NotNull Gson gson) {
if (value == null) {
return JsonNull.INSTANCE;
}
return new JSONObjectBuilder()
.add("input", new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("metadata", value.metadata)
)
)
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
@JsonAdapter(InputImage.Adapter.class)
static class InputImage extends SearchClause {
@NotNull private final ClarifaiImage image;
private InputImage(@NotNull ClarifaiImage image) {
this.image = image;
}
@NotNull @Override public Search.And serialize() {
return Search.And.newBuilder().setInput(
InputOuterClass.Input.newBuilder().setData(DataOuterClass.Data.newBuilder().setImage(this.image.serialize()))
).build();
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(@Nullable InputImage value, @NotNull Gson gson) {
if (value == null) {
return JsonNull.INSTANCE;
}
return new JSONObjectBuilder()
.add("input", new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("image", toJson(gson, value.image, ClarifaiImage.class))
)
)
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
@JsonAdapter(OutputImage.Adapter.class)
static class OutputImage extends SearchClause {
@NotNull private final ClarifaiImage image;
private OutputImage(@NotNull ClarifaiImage image) {
this.image = image;
}
@NotNull @Override public Search.And serialize() {
return Search.And.newBuilder().setOutput(
OutputOuterClass.Output.newBuilder().setInput(
InputOuterClass.Input.newBuilder().setData(DataOuterClass.Data.newBuilder().setImage(image.serialize()))
)
).build();
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(OutputImage value, @NotNull Gson gson) {
return new JSONObjectBuilder()
.add("output", new JSONObjectBuilder()
.add("input", new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("image", toJson(gson, value.image, ClarifaiImage.class))
)
)
)
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
@JsonAdapter(SearchConcept.Adapter.class)
static class SearchConcept extends SearchClause {
@NotNull private final String owningObjectName;
@NotNull private final Concept concept;
private SearchConcept(@NotNull String owningObjectName, @NotNull Concept concept) {
this.owningObjectName = owningObjectName;
this.concept = concept;
}
@NotNull @Override public Search.And serialize() {
DataOuterClass.Data.Builder dataBuilder = DataOuterClass.Data.newBuilder().addConcepts(concept.serialize());
if (owningObjectName.equals("input")) {
return Search.And.newBuilder().setInput(InputOuterClass.Input.newBuilder().setData(dataBuilder)).build();
} else if (owningObjectName.equals("output")) {
return Search.And.newBuilder().setOutput(OutputOuterClass.Output.newBuilder().setData(dataBuilder)).build();
} else {
throw new ClarifaiException("Unknown owning object name: " + owningObjectName);
}
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(@Nullable SearchConcept value, @NotNull Gson gson) {
if (value == null) {
return JsonNull.INSTANCE;
}
return new JSONObjectBuilder()
.add(value.owningObjectName, new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("concepts", new JSONArrayBuilder().add(toJson(gson, value.concept, Concept.class)))
)
)
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
@JsonAdapter(GeoCircle.Adapter.class)
static class GeoCircle extends SearchClause {
@NotNull private final PointF center;
@NotNull private final Radius radius;
private GeoCircle(@NotNull PointF center, @NotNull Radius radius) {
this.center = center;
this.radius = radius;
}
@NotNull @Override public Search.And serialize() {
return Search.And.newBuilder().setInput(
InputOuterClass.Input.newBuilder().setData(
DataOuterClass.Data.newBuilder().setGeo(
GeoOuterClass.Geo.newBuilder().setGeoPoint(asGeoPointProto(center)).setGeoLimit(
GeoOuterClass.GeoLimit.newBuilder().setType(radius.unit().toString()).setValue(radius.value())
)
)
)
).build();
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(@Nullable GeoCircle value, @NotNull Gson gson) {
if (value == null) {
return JsonNull.INSTANCE;
}
return new JSONObjectBuilder()
.add("input", new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("geo", new JSONObjectBuilder()
.add("geo_point", asGeoPointJson(value.center))
.add("geo_limit", new JSONObjectBuilder()
.add("type", value.radius.unit().toString())
.add("value", value.radius.value())))))
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
@JsonAdapter(GeoRect.Adapter.class)
static class GeoRect extends SearchClause {
@NotNull private final Rectangle box;
private GeoRect(@NotNull PointF topLeft, @NotNull PointF bottomRight) {
this.box = Rectangle.of(topLeft, bottomRight);
}
@NotNull @Override public Search.And serialize() {
return Search.And.newBuilder().setInput(
InputOuterClass.Input.newBuilder().setData(
DataOuterClass.Data.newBuilder().setGeo(
GeoOuterClass.Geo.newBuilder()
.addGeoBox(
GeoOuterClass.GeoBoxedPoint.newBuilder().setGeoPoint(asGeoPointProto(this.box.topLeft()))
)
.addGeoBox(
GeoOuterClass.GeoBoxedPoint.newBuilder().setGeoPoint(asGeoPointProto(this.box.bottomRight()))
)
)
)
).build();
}
static class Adapter extends JSONAdapterFactory {
@Nullable @Override protected Serializer serializer() {
return new Serializer() {
@NotNull @Override public JsonElement serialize(@Nullable GeoRect value, @NotNull Gson gson) {
if (value == null) {
return JsonNull.INSTANCE;
}
return new JSONObjectBuilder()
.add("input", new JSONObjectBuilder()
.add("data", new JSONObjectBuilder()
.add("geo", new JSONObjectBuilder()
.add("geo_box", new JSONArrayBuilder()
.add(new JSONObjectBuilder().add("geo_point", asGeoPointJson(value.box.topLeft())))
.add(new JSONObjectBuilder().add("geo_point",
asGeoPointJson(value.box.bottomRight())
))))))
.build();
}
};
}
@NotNull @Override protected TypeToken typeToken() {
return new TypeToken() {};
}
}
}
}