apoc.atomic.Atomic Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc-core Show documentation
Show all versions of apoc-core Show documentation
Core package for Neo4j Procedures
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 apoc.atomic;
import apoc.atomic.util.AtomicUtils;
import apoc.util.ArrayBackedList;
import apoc.util.MapUtil;
import apoc.util.Util;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
import org.apache.commons.lang3.ArrayUtils;
import org.neo4j.exceptions.Neo4jException;
import org.neo4j.graphdb.Entity;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Transaction;
import org.neo4j.procedure.*;
/**
* @author AgileLARUS
* @since 20-06-17
*/
public class Atomic {
@Context
public Transaction tx;
/**
* increment a property's value
*/
@Procedure(name = "apoc.atomic.add", mode = Mode.WRITE)
@Description("Sets the given property to the sum of itself and the given `INTEGER` or `FLOAT` value.\n"
+ "The procedure then sets the property to the returned sum.")
public Stream add(
@Name("container") Object container,
@Name("propertyName") String property,
@Name("number") Number number,
@Name(value = "retryAttempts", defaultValue = "5") Long retryAttempts) {
checkIsEntity(container);
final Number[] newValue = new Number[1];
final Number[] oldValue = new Number[1];
Entity entity = Util.rebind(tx, (Entity) container);
final ExecutionContext executionContext = new ExecutionContext(tx, entity);
retry(
executionContext,
(context) -> {
oldValue[0] = (Number) entity.getProperty(property);
newValue[0] = AtomicUtils.sum((Number) entity.getProperty(property), number);
entity.setProperty(property, newValue[0]);
return context.entity.getProperty(property);
},
retryAttempts);
return Stream.of(new AtomicResults(entity, property, oldValue[0], newValue[0]));
}
/**
* decrement a property's value
*/
@Procedure(name = "apoc.atomic.subtract", mode = Mode.WRITE)
@Description("Sets the property of a value to itself minus the given `INTEGER` or `FLOAT` value.\n"
+ "The procedure then sets the property to the returned sum.")
public Stream subtract(
@Name("container") Object container,
@Name("propertyName") String property,
@Name("number") Number number,
@Name(value = "retryAttempts", defaultValue = "5") Long retryAttempts) {
checkIsEntity(container);
Entity entity = Util.rebind(tx, (Entity) container);
final Number[] newValue = new Number[1];
final Number[] oldValue = new Number[1];
final ExecutionContext executionContext = new ExecutionContext(tx, entity);
retry(
executionContext,
(context) -> {
oldValue[0] = (Number) entity.getProperty(property);
newValue[0] = AtomicUtils.sub((Number) entity.getProperty(property), number);
entity.setProperty(property, newValue[0]);
return context.entity.getProperty(property);
},
retryAttempts);
return Stream.of(new AtomicResults(entity, property, oldValue[0], newValue[0]));
}
/**
* concat a property's value
*/
@Procedure(name = "apoc.atomic.concat", mode = Mode.WRITE)
@Description("Sets the given property to the concatenation of itself and the `STRING` value.\n"
+ "The procedure then sets the property to the returned `STRING`.")
public Stream concat(
@Name("container") Object container,
@Name("propertyName") String property,
@Name("string") String string,
@Name(value = "retryAttempts", defaultValue = "5") Long retryAttempts) {
checkIsEntity(container);
Entity entity = Util.rebind(tx, (Entity) container);
final String[] newValue = new String[1];
final String[] oldValue = new String[1];
final ExecutionContext executionContext = new ExecutionContext(tx, entity);
retry(
executionContext,
(context) -> {
oldValue[0] = entity.getProperty(property).toString();
newValue[0] = oldValue[0].concat(string);
entity.setProperty(property, newValue[0]);
return context.entity.getProperty(property);
},
retryAttempts);
return Stream.of(new AtomicResults(entity, property, oldValue[0], newValue[0]));
}
/**
* insert a value into an array property value
*/
@Procedure(name = "apoc.atomic.insert", mode = Mode.WRITE)
@Description("Inserts a value at position into the `LIST` value of a property.\n"
+ "The procedure then sets the result back on the property.")
public Stream insert(
@Name("container") Object container,
@Name("propertyName") String property,
@Name("position") Long position,
@Name("value") Object value,
@Name(value = "retryAttempts", defaultValue = "5") Long retryAttempts) {
checkIsEntity(container);
Entity entity = Util.rebind(tx, (Entity) container);
final Object[] oldValue = new Object[1];
final Object[] newValue = new Object[1];
final ExecutionContext executionContext = new ExecutionContext(tx, entity);
retry(
executionContext,
(context) -> {
oldValue[0] = entity.getProperty(property);
List