@Nonnull @Override public <V> Optional<V> valueOf(ManyFeatureBean 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 String fieldNameWithPos = concat(fieldName, Integer.toString(feature.position())); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldNameWithPos)); final Bson projection = slice(fieldName, feature.position(), 1); final ModelDocument instance = documents.find(filter).projection(projection).first(); return Optional.ofNullable(instance) .map(ModelDocument::getManyFeatures) .map(m -> m.get(featureId)) .filter(l -> !l.isEmpty()) .map(l -> l.get(0)) .map(this::deserializeValue); }
@Nonnull @Override public <V> Optional<V> valueFor(ManyFeatureBean 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_MANY_FEATURE, featureId); final String fieldNameWithPos = concat(fieldName, Integer.toString(feature.position())); final Bson filter = and(eq(ModelDocument.F_ID, ownerId), exists(fieldNameWithPos)); final Bson projection = slice(fieldName, feature.position(), 1); final Bson update = set(fieldNameWithPos, serializeValue(value)); final ModelDocument instance = documents.findOneAndUpdate(filter, update, new FindOneAndUpdateOptions().projection(projection)); final Optional<V> previousValue = Optional.ofNullable(instance) .map(ModelDocument::getManyFeatures) .map(m -> m.get(featureId)) .filter(l -> !l.isEmpty()) .map(l -> l.get(0)) .map(this::deserializeValue); if (!previousValue.isPresent()) { throw new IndexOutOfBoundsException(); } return previousValue; }