2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.spi.meta;
10 import com.google.common.annotations.Beta;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.MoreObjects;
13 import com.google.common.base.Verify;
14 import java.util.Arrays;
15 import java.util.stream.Collectors;
16 import org.opendaylight.yangtools.concepts.Immutable;
17 import org.opendaylight.yangtools.yang.model.api.CopyableNode;
20 public final class CopyHistory implements Immutable, CopyableNode {
21 private static final CopyType[] VALUES = CopyType.values();
23 private static final CopyHistory[][] CACHE = new CopyHistory[VALUES.length][];
27 * Cache size is dependent on number of items in CopyType, it costs N * 2^N objects.
28 * For 4 types that boils down to 4 * 16 = 64 objects.
29 * For 5 types that boils down to 5 * 32 = 160 objects.
30 * For 6 types that boils down to 6 * 64 = 384 objects.
32 * If we ever hit 6 types, the caching strategy needs to be revisited.
34 Verify.verify(VALUES.length < 6);
37 private static final CopyHistory ORIGINAL = cacheObject(CopyType.ORIGINAL, CopyType.ORIGINAL.bit());
38 private static final int IS_ADDED_BY_USES_BITS =
39 CopyType.ADDED_BY_USES_AUGMENTATION.bit() | CopyType.ADDED_BY_USES.bit();
40 private static final int IS_AUGMENTING_BITS =
41 CopyType.ADDED_BY_USES_AUGMENTATION.bit() | CopyType.ADDED_BY_AUGMENTATION.bit();
43 private final short operations;
44 private final short lastOperation;
46 private CopyHistory(final int operations, final CopyType lastOperation) {
47 this.operations = (short) operations;
48 this.lastOperation = (short) lastOperation.ordinal();
51 public static CopyHistory original() {
55 public static CopyHistory of(final CopyType copyType, final CopyHistory copyHistory) {
56 return ORIGINAL.append(copyType, copyHistory);
59 private static CopyHistory[] cacheArray(final CopyType lastOperation) {
60 final int ordinal = lastOperation.ordinal();
61 CopyHistory[] ret = CACHE[ordinal];
63 synchronized (CACHE) {
66 ret = new CopyHistory[1 << VALUES.length];
75 private static CopyHistory cacheObject(final CopyType lastOperation, final int operations) {
76 final CopyHistory[] array = cacheArray(lastOperation);
77 CopyHistory ret = array[operations];
79 synchronized (array) {
80 ret = array[operations];
82 ret = new CopyHistory(operations, lastOperation);
83 array[operations] = ret;
92 // FIXME: 7.0.0: hide this method
93 public boolean contains(final CopyType type) {
94 return (operations & type.bit()) != 0;
97 public CopyType getLastOperation() {
98 return VALUES[lastOperation];
102 public boolean isAugmenting() {
103 return (operations & IS_AUGMENTING_BITS) != 0;
107 public boolean isAddedByUses() {
108 return (operations & IS_ADDED_BY_USES_BITS) != 0;
112 CopyHistory append(final CopyType typeOfCopy, final CopyHistory toAppend) {
113 final int newOperations = operations | toAppend.operations | typeOfCopy.bit();
114 if (newOperations == operations && typeOfCopy.ordinal() == lastOperation) {
118 return cacheObject(typeOfCopy, newOperations);
122 public int hashCode() {
123 return Integer.hashCode(operations | lastOperation << Short.SIZE);
127 public boolean equals(final Object obj) {
131 if (!(obj instanceof CopyHistory)) {
134 final CopyHistory other = (CopyHistory) obj;
135 return operations == other.operations && lastOperation == other.lastOperation;
139 public String toString() {
140 return MoreObjects.toStringHelper(this).add("lastOperation", getLastOperation())
141 .add("operations", Arrays.stream(VALUES).filter(value -> (value.bit() & operations) != 0)
142 .collect(Collectors.toList()))