@Nonnull @Override default Optional<Id> referenceFor(ManyFeatureBean feature, Id reference) { Converter<Id, M> converter = manyReferenceConverter(); return this.valueFor(feature, converter.convert(reference)) .map(converter::revert); }
@Nonnull @Override default Optional<Id> referenceFor(SingleFeatureBean feature, Id reference) { Converter<Id, M> converter = referenceConverter(); return this.valueFor(feature, converter.convert(reference)) .map(converter::revert); }
/** * Returns the vertex referenced by the provided {@code id}. * * @param id the identifier of the vertex to retrieve from the graph * * @return an {@link Optional} containing the vertex referenced by the provided identifier, or {@link * Optional#empty()} when no such vertex exists * * @see #getVertex(Object) * @see Converter#convert(Object) */ @Nonnull public Optional<ElementVertex> getVertex(Id id) { final Object vid = idConverter.convert(id); return Optional.ofNullable(elementCache.get(vid, i -> getElementVertex(i, () -> null))); }
@Override default int appendReference(SingleFeatureBean feature, Id reference) { Converter<Id, M> converter = manyReferenceConverter(); return this.appendValue(feature, converter.convert(reference)); }
@Override default void addReference(ManyFeatureBean feature, Id reference) { Converter<Id, M> converter = manyReferenceConverter(); this.addValue(feature, converter.convert(reference)); }
/** * Returns the vertex referenced by the provided {@code id}. If no such vertex exists, it will be created and added * to the graph. * * @param id the identifier of the vertex to retrieve, or create, from the graph * * @return the vertex * * @see #getVertex(Object) * @see #addVertex(Object) * @see Converter#convert(Object) */ @Nonnull public ElementVertex getOrCreateVertex(Id id) { final Object vid = idConverter.convert(id); return elementCache.get(vid, i -> getElementVertex(i, () -> addElementVertex(i))); }
@Nonnull @Override default Optional<Id> referenceFor(ManyFeatureBean feature, Id reference) { checkNotNull(feature, "feature"); checkNotNull(reference, "reference"); Converter<List<Id>, M> converter = manyReferenceMerger(); List<Id> ids = this.<M>valueOf(feature.withoutPosition()).map(converter::revert).orElse(null); if (isNull(ids) || feature.position() >= ids.size()) { throw new IndexOutOfBoundsException(); } Optional<Id> previousId = Optional.of(ids.get(feature.position())); ids.set(feature.position(), reference); valueFor(feature.withoutPosition(), converter.convert(ids)); return previousId; }
@Nonnull @Override public <V> Stream<V> allValuesOf(SingleFeatureBean feature) { checkNotNull(feature, "feature"); final String ownerId = idConverter.convert(feature.owner()); final String featureId = Integer.toString(feature.id()); final String fieldName = concat(ModelDocument.F_MANY_FEATURE, featureId); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldName)); final Bson projection = include(fieldName); final ModelDocument instance = documents.find(filter).projection(projection).first(); return Optional.ofNullable(instance) .map(ModelDocument::getManyFeatures) .map(m -> m.get(featureId)) .map(Collection::stream) .map(s -> s.map(this::<V>deserializeValue)) .orElseGet(Stream::empty); }
@Nonnull @Override public Optional<SingleFeatureBean> containerOf(Id id) { checkNotNull(id, "id"); final String ownerId = idConverter.convert(id); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(ModelDocument.F_CONTAINER)); final Bson projection = include(ModelDocument.F_CONTAINER); final ModelDocument instance = documents.find(filter).projection(projection).first(); return Optional.ofNullable(instance) .map(ModelDocument::getContainer) .map(ContainerDocument::toBean); }
@Nonnull @Override public Optional<ClassBean> metaClassOf(Id id) { checkNotNull(id, "id"); final String ownerId = idConverter.convert(id); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(ModelDocument.F_METACLASS)); final Bson projection = include(ModelDocument.F_METACLASS); final ModelDocument instance = documents.find(filter).projection(projection).first(); return Optional.ofNullable(instance) .map(ModelDocument::getMetaClass) .map(ClassDocument::toBean); }
@Nonnull @Override public <V> Optional<V> valueOf(SingleFeatureBean feature) { checkNotNull(feature, "feature"); final String ownerId = idConverter.convert(feature.owner()); final String featureId = Integer.toString(feature.id()); final String fieldName = concat(ModelDocument.F_SINGLE_FEATURE, featureId); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldName)); final Bson projection = include(fieldName); final ModelDocument instance = documents.find(filter).projection(projection).first(); return Optional.ofNullable(instance) .map(ModelDocument::getSingleFeatures) .map(m -> m.get(featureId)) .map(this::deserializeValue); }
@Override default void addReference(ManyFeatureBean feature, Id reference) { checkNotNull(feature, "feature"); checkNotNull(reference, "reference"); Converter<List<Id>, M> converter = manyReferenceMerger(); List<Id> ids = this.<M>valueOf(feature.withoutPosition()) .map(converter::revert) .orElseGet(ArrayList::new); checkPositionIndex(feature.position(), ids.size()); ids.add(feature.position(), reference); valueFor(feature.withoutPosition(), converter.convert(ids)); }
/** * Converts the specified {@code bean} in a {@link ContainerDocument}. * * @param bean the bean * * @return the document */ @Nonnull public static ContainerDocument fromBean(SingleFeatureBean bean) { ContainerDocument c = new ContainerDocument(); c.setOwner(CONVERTER.convert(bean.owner())); c.setId(bean.id()); return c; }
@Nonnull @Override public <V> Optional<V> valueFor(SingleFeatureBean feature, V value) { checkNotNull(feature, "feature"); checkNotNull(value, "value"); final String ownerId = idConverter.convert(feature.owner()); final String featureId = Integer.toString(feature.id()); final String fieldName = concat(ModelDocument.F_SINGLE_FEATURE, featureId); final Bson filter = eq(ModelDocument.F_ID, ownerId); final Bson projection = include(fieldName); final Bson update = set(fieldName, serializeValue(value)); final ModelDocument instance = documents.findOneAndUpdate(filter, update, new FindOneAndUpdateOptions().upsert(true).projection(projection)); return Optional.ofNullable(instance) .map(ModelDocument::getSingleFeatures) .map(l -> l.get(featureId)) .map(this::deserializeValue); }
@Override default void addAllReferences(ManyFeatureBean feature, List<Id> collection) { checkNotNull(feature, "feature"); checkNotNull(collection, "collection"); checkNotContainsNull(collection, "collection"); if (collection.isEmpty()) { return; } Converter<List<Id>, M> converter = manyReferenceMerger(); List<Id> ids = this.<M>valueOf(feature.withoutPosition()) .map(converter::revert) .orElseGet(ArrayList::new); int firstPosition = feature.position(); checkPositionIndex(firstPosition, ids.size()); ids.addAll(firstPosition, collection); valueFor(feature.withoutPosition(), converter.convert(ids)); }
@Override public void removeContainer(Id id) { checkNotNull(id, "id"); final String ownerId = idConverter.convert(id); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(ModelDocument.F_CONTAINER)); final Bson update = unset(ModelDocument.F_CONTAINER); documents.updateOne(filter, update); }
@Override public void removeValue(SingleFeatureBean feature) { checkNotNull(feature, "feature"); final String ownerId = idConverter.convert(feature.owner()); final String featureId = Integer.toString(feature.id()); final String fieldName = concat(ModelDocument.F_SINGLE_FEATURE, featureId); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldName)); final Bson update = unset(fieldName); documents.updateOne(filter, update); }
/** * Creates a new {@code ClassVertex} on the {@code graph}. * * @param graph the graph that owns the vertex * @param bean the simple representation of the meta-class * * @return the meta-class vertex that has been added in the graph */ @Nonnull protected static ClassVertex create(ModelGraph graph, ClassBean bean) { final Object id = graph.getIdConverter().convert(ClassVertex.createId(bean)); ClassVertex v = graph.addVertex(id, ClassVertex::new).setName(bean.name()).setUri(bean.uri()); graph.updateIndex(v); return v; }
@Override public void removeAllValues(SingleFeatureBean feature) { checkNotNull(feature, "feature"); final String ownerId = idConverter.convert(feature.owner()); final String fieldName = ModelDocument.F_MANY_FEATURE; final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldName)); final Bson update = unset(fieldName); documents.updateOne(filter, update); }
@Override public void containerFor(Id id, SingleFeatureBean container) { checkNotNull(id, "id"); checkNotNull(container, "container"); final String ownerId = idConverter.convert(id); final ContainerDocument newContainer = ContainerDocument.fromBean(container); final Bson filter = eq(ModelDocument.F_ID, ownerId); final Bson update = combine( set(concat(ModelDocument.F_CONTAINER, ContainerDocument.F_OWNER), newContainer.getOwner()), set(concat(ModelDocument.F_CONTAINER, ContainerDocument.F_ID), newContainer.getId()) ); documents.updateOne(filter, update, new UpdateOptions().upsert(true)); }