defmodule Noizu.Weaviate.Class do @moduledoc """ Main class to provide functionalities for Weaviate classes. """ defmodule Meta do defmodule Classification do defstruct [ id: nil, based_on: nil, classified_fields: nil, completed: nil, scope: nil, vector: nil ] end defstruct [ id: nil, class: nil, description: nil, creation_time_unix: nil, last_update_time_unix: nil, vector: nil, vectors: nil, tenant: nil, classification: nil, feature_projection: nil, ] end defmacro __using__(options \\ nil) do quote do Module.register_attribute(__MODULE__, :properties, accumulate: true) Module.register_attribute(__MODULE__, :class_description, accumulate: false) Module.register_attribute(__MODULE__, :class_vector_index_type, accumulate: false) Module.register_attribute(__MODULE__, :class_vector_index_config, accumulate: false) Module.register_attribute(__MODULE__, :class_vectorizer, accumulate: false) Module.register_attribute(__MODULE__, :class_module_config, accumulate: false) Module.register_attribute(__MODULE__, :class_inverted_index_config, accumulate: false) Module.register_attribute(__MODULE__, :class_replication_config, accumulate: false) Module.register_attribute(__MODULE__, :class_multi_tenancy_config, accumulate: false) Module.register_attribute(__MODULE__, :class_vector_config, accumulate: false) Module.register_attribute(__MODULE__, :class_sharding_config, accumulate: false) require Noizu.Weaviate.Class import Noizu.Weaviate.Class, only: [weaviate_class: 2] end end defmacro weaviate_class(class_name, [do: block]) do quote do import Noizu.Weaviate.Class unquote(block) # Define the struct struct_params = [meta: %Noizu.Weaviate.Class.Meta{ id: nil, class: unquote(class_name), description: @class_description, creation_time_unix: nil, last_update_time_unix: nil, vector: nil, vectors: nil, tenant: nil, classification: nil, feature_projection: nil, }, id: nil] ++ Enum.map(@properties, fn {name, _} -> {name, nil} end) @derive Noizu.Weaviate.Class.Protocol defstruct struct_params def __class__(), do: unquote(class_name) def __properties__(), do: @properties def __property__(name), do: Enum.find_value(@properties, fn {k,v} -> k == name && v end) def definition() do %Noizu.Weaviate.Struct.Class{ name: unquote(class_name), description: @class_description, vector_index: @class_vector_index_type, vector_index_config: @class_vector_index_config, vectorizer: @class_vectorizer, module_config: @class_module_config, inverted_index_config: @class_inverted_index_config, replication_config: @class_replication_config, multi_tenancy_config: @class_multi_tenancy_config, vector_config: @class_vector_config, sharding_config: @class_sharding_config, properties: Enum.map(@properties, fn({_, v}) -> v end), } end def from_json(json) do meta = %Noizu.Weaviate.Class.Meta{ id: json[:id], class: json[:class], creation_time_unix: json[:creationTimeUnix], last_update_time_unix: json[:lastUpdateTimeUnix], vector: json[:vector], vectors: json[:vectors], tenant: json[:tenant], classification: json[:classification], feature_projection: json[:featureProjection] } properties = Enum.map(apply(__MODULE__,:__properties__, []), fn {name, _} -> {name, json[:properties][name]} end) __MODULE__.__struct__([{:meta, meta}, {:id, json[:id]} |properties]) end defimpl Jason.Encoder do def encode(this, opts) do [ id: this.id, class: this.meta.class, vector: this.meta.vector, vectors: this.meta.vectors, tenant: this.meta.tenant, properties: Enum.map(apply(this.__struct__,:__properties__, []), fn({k, _}) -> {k, get_in(this, [Access.key(k)])} end) |> Enum.reject(fn({_,v}) -> is_nil(v) end) |> Map.new() ] |> Enum.reject(fn({_,v}) -> is_nil(v) end) |> Map.new() |> Jason.Encode.map(opts) end end defoverridable [ __properties__: 0, __property__: 1, definition: 0, from_json: 1 ] end end def definition(class, options \\ nil) def definition(%Noizu.Weaviate.Struct.Class{} = class, options), do: class def definition(class, options), do: apply(class, :definition, []) def json_handler(class, options \\ nil) def json_handler(%Noizu.Weaviate.Struct.Class{}, _options), do: Noizu.Weaviate.Struct.Class def json_handler(class, _options) when is_atom(class), do: class def json_handler(_, _options), do: Noizu.Weaviate.Struct.Class #=================================== # Macros #=================================== defmacro description(value) do quote do Module.put_attribute(__MODULE__, :class_description, unquote(value)) end end defmacro vector_index_type(value) do quote do Module.put_attribute(__MODULE__, :class_vector_index_type, unquote(value)) end end defmacro vector_index_config(value) do quote do Module.put_attribute(__MODULE__, :class_vector_index_config, unquote(value)) end end defmacro vectorizer(value) do quote do Module.put_attribute(__MODULE__, :class_vectorizer, unquote(value)) end end defmacro module_config(value) do quote do Module.put_attribute(__MODULE__, :class_module_config, unquote(value)) end end defmacro inverted_index_config(value) do quote do Module.put_attribute(__MODULE__, :class_inverted_index_config, unquote(value)) end end defmacro replication_config(value) do quote do Module.put_attribute(__MODULE__, :class_replication_config, unquote(value)) end end defmacro multi_tenancy_config(value) do quote do Module.put_attribute(__MODULE__, :class_multi_tenancy_config, unquote(value)) end end defmacro vector_config(value) do quote do Module.put_attribute(__MODULE__, :class_vector_config, unquote(value)) end end defmacro sharding_config(value) do quote do Module.put_attribute(__MODULE__, :class_sharding_config, unquote(value)) end end defmacro property(name, data_type, opts \\ []) do quote do Module.put_attribute(__MODULE__, :properties, {unquote(name), %Noizu.Weaviate.Struct.Property{ name: unquote(name), data_type: ["#{unquote(data_type)}"], description: Keyword.get(unquote(opts), :description, nil), index_filterable: Keyword.get(unquote(opts), :index_filterable, nil), index_searchable: Keyword.get(unquote(opts), :index_searchable, nil), index_inverted: Keyword.get(unquote(opts), :index_inverted, nil), tokenization: Keyword.get(unquote(opts), :tokenization, nil), module_config: Keyword.get(unquote(opts), :module_config, nil) }}) end end end