Back to project page spring-sync.
The source code is released under:
Apache License
If you think the Android project spring-sync listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright 2014 the original author or authors. */*from w ww. jav a2 s. c o m*/ * 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 org.springframework.sync; import static org.springframework.sync.PathToSpEL.*; import java.util.List; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionException; /** * Abstract base class representing and providing support methods for patch operations. * * @author Craig Walls */ public abstract class PatchOperation { protected final String op; protected final String path; protected final Object value; protected final Expression spelExpression; /** * Constructs the operation. * @param op the operation name. (e.g., 'move') * @param path the path to perform the operation on. (e.g., '/1/description') */ public PatchOperation(String op, String path) { this(op, path, null); } /** * Constructs the operation. * @param op the operation name. (e.g., 'move') * @param path the path to perform the operation on. (e.g., '/1/description') * @param value the value to apply in the operation. Could be an actual value or an implementation of {@link LateObjectEvaluator}. */ public PatchOperation(String op, String path, Object value) { this.op = op; this.path = path; this.value = value; this.spelExpression = pathToExpression(path); } /** * @return the operation name */ public String getOp() { return op; } /** * @return the operation path */ public String getPath() { return path; } /** * @return the operation's value (or {@link LateObjectEvaluator}) */ public Object getValue() { return value; } /** * Pops a value from the given path. * @param target the target from which to pop a value. * @param removePath the path from which to pop a value. Must be a list. * @return the value popped from the list */ protected Object popValueAtPath(Object target, String removePath) { Integer listIndex = targetListIndex(removePath); Expression expression = pathToExpression(removePath); Object value = expression.getValue(target); if (listIndex == null) { try { expression.setValue(target, null); return value; } catch (NullPointerException e) { throw new PatchException("Path '" + removePath + "' is not nullable."); } } else { Expression parentExpression = pathToParentExpression(removePath); List<?> list = (List<?>) parentExpression.getValue(target); list.remove(listIndex >= 0 ? listIndex.intValue() : list.size() - 1); return value; } } /** * Adds a value to the operation's path. * If the path references a list index, the value is added to the list at the given index. * If the path references an object property, the property is set to the value. * @param target The target object. * @param value The value to add. */ protected void addValue(Object target, Object value) { Expression parentExpression = pathToParentExpression(path); Object parent = parentExpression != null ? parentExpression.getValue(target) : null; Integer listIndex = targetListIndex(path); if (parent == null || !(parent instanceof List) || listIndex == null) { spelExpression.setValue(target, value); } else { @SuppressWarnings("unchecked") List<Object> list = (List<Object>) parentExpression.getValue(target); int addAtIndex = listIndex >= 0 ? listIndex.intValue() : list.size(); list.add(addAtIndex, value); } } /** * Sets a value to the operation's path. * @param target The target object. * @param value The value to set. */ protected void setValueOnTarget(Object target, Object value) { spelExpression.setValue(target, value); } /** * Retrieves a value from the operation's path. * @param target the target object. * @return the value at the path on the given target object. */ protected Object getValueFromTarget(Object target) { try { return spelExpression.getValue(target); } catch (ExpressionException e) { throw new PatchException("Unable to get value from target", e); } } /** * Performs late-value evaluation on the operation value if the value is a {@link LateObjectEvaluator}. * @param targetObject the target object, used as assistance in determining the evaluated object's type. * @param entityType the entityType * @param <T> the entity type * @return the result of late-value evaluation if the value is a {@link LateObjectEvaluator}; the value itself otherwise. */ protected <T> Object evaluateValueFromTarget(Object targetObject, Class<T> entityType) { return value instanceof LateObjectEvaluator ? ((LateObjectEvaluator) value).evaluate(entityType) : value; } /** * Perform the operation. * @param target the target of the operation. */ abstract <T> void perform(Object target, Class<T> type); // private helpers private Integer targetListIndex(String path) { String[] pathNodes = path.split("\\/"); String lastNode = pathNodes[pathNodes.length - 1]; if ("~".equals(lastNode)) { return -1; } try { return Integer.parseInt(lastNode); } catch (NumberFormatException e) { return null; } } }