/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.parser.spi.meta;
import com.google.common.annotations.Beta;
import com.google.common.base.Verify;
import org.opendaylight.yangtools.concepts.Immutable;
@Beta
public final class CopyHistory implements Immutable {
private static final CopyType[] VALUES = CopyType.values();
private static final CopyHistory[][] CACHE = new CopyHistory[VALUES.length][];
static {
/*
* Cache size is dependent on number of items in CopyType, it costs N * 2^N objects.
* For 4 types that boils down to 4 * 16 = 64 objects.
* For 5 types that boils down to 5 * 32 = 160 objects.
* For 6 types that boils down to 6 * 64 = 384 objects.
*
* If we ever hit 6 types, the caching strategy needs to be revisited.
*/
Verify.verify(VALUES.length < 6);
}
private static final CopyHistory ORIGINAL = cacheObject(CopyType.ORIGINAL, CopyType.ORIGINAL.bit());
private final short operations;
private final short lastOperation;
private CopyHistory(final int operations, final CopyType lastOperation) {
this.operations = (short) operations;
this.lastOperation = (short) lastOperation.ordinal();
}
public static CopyHistory original() {
return ORIGINAL;
}
private static CopyHistory[] cacheArray(final CopyType lastOperation) {
final int ordinal = lastOperation.ordinal();
CopyHistory[] ret = CACHE[ordinal];
if (ret == null) {
synchronized (CACHE) {
ret = CACHE[ordinal];
if (ret == null) {
ret = new CopyHistory[1 << VALUES.length];
CACHE[ordinal] = ret;
}
}
}
return ret;
}
private static CopyHistory cacheObject(final CopyType lastOperation, final int operations) {
final CopyHistory[] array = cacheArray(lastOperation);
CopyHistory ret = array[operations];
if (ret == null) {
synchronized (array) {
ret = array[operations];
if (ret == null) {
ret = new CopyHistory(operations, lastOperation);
array[operations] = ret;
}
}
}
return ret;
}
public boolean contains(final CopyType type) {
return (operations & type.bit()) != 0;
}
public CopyType getLastOperation() {
return VALUES[lastOperation];
}
public CopyHistory append(final CopyType typeOfCopy, final CopyHistory toAppend) {
final int newOperations = operations | toAppend.operations | typeOfCopy.bit();
if (newOperations == operations && typeOfCopy.ordinal() == lastOperation) {
return this;
}
return cacheObject(typeOfCopy, newOperations);
}
@Override
public int hashCode() {
return Integer.hashCode(operations | (lastOperation << Short.SIZE));
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof CopyHistory)) {
return false;
}
final CopyHistory other = (CopyHistory) obj;
return operations == other.operations && lastOperation == other.lastOperation;
}
}