io.evitadb.api.requestResponse.data.ReferenceContract Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of evita_api Show documentation
Show all versions of evita_api Show documentation
Module contains external API of the evitaDB.
/*
*
* _ _ ____ ____
* _____ _(_) |_ __ _| _ \| __ )
* / _ \ \ / / | __/ _` | | | | _ \
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/FgForrest/evitaDB/blob/master/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.evitadb.api.requestResponse.data;
import io.evitadb.api.query.require.EntityFetch;
import io.evitadb.api.query.require.EntityGroupFetch;
import io.evitadb.api.requestResponse.data.mutation.reference.ReferenceKey;
import io.evitadb.api.requestResponse.data.structure.Entity;
import io.evitadb.api.requestResponse.data.structure.EntityReference;
import io.evitadb.api.requestResponse.schema.AttributeSchemaContract;
import io.evitadb.api.requestResponse.schema.Cardinality;
import io.evitadb.api.requestResponse.schema.EvolutionMode;
import io.evitadb.api.requestResponse.schema.ReferenceSchemaContract;
import io.evitadb.dataType.EvitaDataTypes;
import io.evitadb.utils.MemoryMeasuringConstants;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
import java.util.Optional;
/**
* Contract for classes that allow reading information about references in {@link Entity} instance.
*
* @author Jan Novotný ([email protected]), FG Forrest a.s. (c) 2021
*/
public interface ReferenceContract extends AttributesContract, Droppable, Comparable, ContentComparator {
/**
* Method allows to access unique and primary identifier of the ReferenceContract within {@link EntityContract}.
*/
@Nonnull
ReferenceKey getReferenceKey();
/**
* Returns name of the reference. The name always corresponds with {@link #getReferenceSchema()} name.
*/
@Nonnull
default String getReferenceName() {
return getReferenceKey().referenceName();
}
/**
* Returns primary key of the referenced (internal or external) entity.
*/
default int getReferencedPrimaryKey() {
return getReferenceKey().primaryKey();
}
/**
* Returns body of the referenced entity in case its fetching was requested via {@link EntityFetch}
* constraint.
*/
@Nonnull
Optional getReferencedEntity();
/**
* Returns referenced entity type - conforming to {@link ReferenceSchemaContract#getReferencedEntityType()}.
*/
@Nonnull
String getReferencedEntityType();
/**
* Returns cardinality of the reference. The name always corresponds with {@link #getReferenceSchema()} cardinality.
*/
@Nonnull
Cardinality getReferenceCardinality();
/**
* Returns reference group. Group is composed of entity type and primary key of the referenced group entity.
* Group may or may not be Evita entity.
*/
@Nonnull
Optional getGroup();
/**
* Returns body of the referenced entity in case its fetching was requested via {@link EntityGroupFetch}
* constraint.
*/
@Nonnull
Optional getGroupEntity();
/**
* Returns schema that describes this type of reference.
* NULL can be returned in case schema hasn't yet known the reference type, but will be automatically created
* if {@link EvolutionMode#ADDING_REFERENCES} is allowed. So the NULL will be returned in very rare cases.
*/
@Nonnull
Optional getReferenceSchema();
/**
* Returns schema that describes this type of reference or throws an exception.
* NULL can be returned in case schema hasn't yet known the reference type, but will be automatically created
* if {@link EvolutionMode#ADDING_REFERENCES} is allowed. So the NULL will be returned in very rare cases.
*/
@Nonnull
ReferenceSchemaContract getReferenceSchemaOrThrow();
/**
* Referenced entity is a business key - we can compare according it.
*/
@Override
default int compareTo(ReferenceContract o) {
return getReferenceKey().compareTo(o.getReferenceKey());
}
/**
* Method returns gross estimation of the in-memory size of this instance. The estimation is expected not to be
* a precise one. Please use constants from {@link MemoryMeasuringConstants} for size computation.
*/
default int estimateSize() {
return MemoryMeasuringConstants.OBJECT_HEADER_SIZE
// version
+ MemoryMeasuringConstants.INT_SIZE +
// dropped
+MemoryMeasuringConstants.BYTE_SIZE +
// referenced entity
+MemoryMeasuringConstants.REFERENCE_SIZE + getReferenceKey().estimateSize() +
// group
+MemoryMeasuringConstants.REFERENCE_SIZE + getGroup().stream().mapToInt(GroupEntityReference::estimateSize).sum() +
// schema
+MemoryMeasuringConstants.REFERENCE_SIZE;
}
/**
* Returns true if reference differs by any "business" related data from other reference.
*/
@Override
default boolean differsFrom(@Nullable ReferenceContract otherReference) {
if (otherReference == null) return true;
if (!Objects.equals(getReferenceKey(), otherReference.getReferenceKey())) return true;
if (getGroup().map(it -> it.differsFrom(otherReference.getGroup().orElse(null))).orElseGet(() -> otherReference.getGroup().isPresent()))
return true;
if (dropped() != otherReference.dropped()) return true;
return AttributesContract.anyAttributeDifferBetween(this, otherReference);
}
/**
* This class envelopes reference to the reference group. It adds support for versioning and tombstone on top of basic
* {@link EntityReference} structure.
*
* @param referencedEntity reference to {@link Entity#getType()} of the referenced entity. Might be also any {@link String}
* that identifies type some external resource not maintained by Evita.
* @param primaryKey reference to {@link Entity#getPrimaryKey()} of the referenced entity. Might be also any integer
* that uniquely identifies some external resource of type {@link #getType()} not maintained by Evita.
* @param version contains version of this object and gets increased with any entity update. Allows to execute
* optimistic locking i.e. avoiding parallel modifications.
* @param dropped contains TRUE if reference group reference was dropped - i.e. removed. Such reference is not removed (unless
* tidying process does it), but are lying in reference with tombstone flag. Dropped reference
* can be overwritten by a new value continuing with the versioning where it was stopped for the last time.
*/
record GroupEntityReference(@Nonnull String referencedEntity, int primaryKey, int version, boolean dropped)
implements EntityReferenceContract, Droppable, Serializable, ContentComparator {
@Serial private static final long serialVersionUID = 7432447904441796055L;
@Nonnull
@Override
public String getType() {
return referencedEntity;
}
@Nonnull
@Override
public Integer getPrimaryKey() {
return primaryKey;
}
@Override
public boolean dropped() {
return dropped;
}
@Override
public int version() {
return version;
}
@Override
public int compareTo(@Nonnull GroupEntityReference o) {
return compareReferenceContract(o);
}
/**
* Returns true if reference group differs by any "business" related data from other reference group.
*/
@Override
public boolean differsFrom(@Nullable GroupEntityReference otherReferenceGroup) {
if (otherReferenceGroup == null) {
return true;
}
if (!Objects.equals(primaryKey, otherReferenceGroup.primaryKey())) {
return true;
}
return dropped != otherReferenceGroup.dropped();
}
public int estimateSize() {
return MemoryMeasuringConstants.OBJECT_HEADER_SIZE +
// type
EvitaDataTypes.estimateSize(referencedEntity) +
// primary key
MemoryMeasuringConstants.INT_SIZE +
//version
MemoryMeasuringConstants.INT_SIZE +
// dropped
MemoryMeasuringConstants.BYTE_SIZE;
}
@Override
public String toString() {
return (dropped ? "❌ " : "") +
"`" + referencedEntity + "`" + " with key " + getPrimaryKey();
}
}
}