1 /*
2 * Copyright 2017 LINE Corporation
3 *
4 * LINE Corporation licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 /*
17 * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
18 *
19 * This software is dual-licensed under:
20 *
21 * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
22 * later version;
23 * - the Apache Software License (ASL) version 2.0.
24 *
25 * The text of this file and of both licenses is available at the root of this
26 * project or, if you have the jar distribution, in directory META-INF/, under
27 * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
28 *
29 * Direct link to the sources:
30 *
31 * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
32 * - ASL 2.0: https://www.apache.org/licenses/LICENSE-2.0.txt
33 */
34
35 package com.linecorp.centraldogma.common.jsonpatch;
36
37 import static java.util.Objects.requireNonNull;
38
39 import com.fasterxml.jackson.annotation.JsonCreator;
40 import com.fasterxml.jackson.annotation.JsonProperty;
41 import com.fasterxml.jackson.core.JsonPointer;
42 import com.fasterxml.jackson.databind.JsonNode;
43
44 /**
45 * JSON Patch {@code copy} operation.
46 *
47 * <p>For this operation, {@code from} is the JSON Pointer of the value to copy,
48 * and {@code path} is the destination where the value should be copied.</p>
49 *
50 * <p>It is an error if {@code from} fails to resolve to a JSON value.</p>
51 */
52 public final class CopyOperation extends DualPathOperation {
53
54 /**
55 * Creates a new instance.
56 */
57 @JsonCreator
58 CopyOperation(@JsonProperty("from") final JsonPointer from,
59 @JsonProperty("path") final JsonPointer path) {
60 super("copy", from, path);
61 }
62
63 @Override
64 public JsonNode apply(final JsonNode node) {
65 requireNonNull(node, "node");
66 final JsonPointer from = from();
67 JsonNode source = node.at(from);
68 if (source.isMissingNode()) {
69 throw new JsonPatchConflictException("non-existent source path: " + from);
70 }
71
72 final JsonPointer path = path();
73 if (path.toString().isEmpty()) {
74 return source;
75 }
76
77 final JsonNode targetParent = ensureTargetParent(node, path);
78 source = source.deepCopy();
79 return targetParent.isArray() ? AddOperation.addToArray(path, node, source)
80 : AddOperation.addToObject(path, node, source);
81 }
82 }