package rocks.inspectit.shared.cs.indexing.storage.impl;
import org.apache.commons.lang.builder.ToStringBuilder;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.communication.data.InvocationSequenceData;
import rocks.inspectit.shared.all.indexing.IIndexQuery;
import rocks.inspectit.shared.cs.indexing.indexer.IBranchIndexer;
import rocks.inspectit.shared.cs.indexing.storage.IStorageBranchIndexer;
import rocks.inspectit.shared.cs.indexing.storage.IStorageTreeComponent;
import rocks.inspectit.shared.cs.storage.util.StorageUtil;
/**
* Implementation of the indexer for the {@link IStorageTreeComponent}. This indexer delegate the
* key creation to the {@link IBranchIndexer}.
*
* @author Ivan Senic
*
* @param <E>
* Type of element indexed by indexer.
*/
public class StorageBranchIndexer<E extends DefaultData> implements IStorageBranchIndexer<E> {
/**
* Id that will be passed to the child indexers/leafs if {@link #passId} is true.
*/
private int id;
/**
* The delegate indexer for keys creation.
*/
private IBranchIndexer<E> delegateIndexer;
/**
* The indexer that is next in the hierarchy.
*/
private StorageBranchIndexer<E> childIndexer;
/**
* If pass ID mode is on. With this mode, all sub-components created with this indexer will have
* same ID, thus write will be done in same file.
*/
private boolean passId;
/**
* No-args constructor.
*/
public StorageBranchIndexer() {
}
/**
* This constructor will generate unique ID and will not set child indexer.
*
* @param delegateIndexer
* Provides delegate indexer with a constructor.
* @param passId
* If pass ID mode is on. With this mode, all sub-components created with this
* indexer will have same ID, thus write will be done in same file.
*/
public StorageBranchIndexer(IBranchIndexer<E> delegateIndexer, boolean passId) {
this(delegateIndexer, null, StorageUtil.getRandomInt(), passId);
}
/**
* This constructor allows setting of all properties except ID that will be uniquely generated.
*
* @param delegateIndexer
* Provides delegate indexer with a constructor.
* @param childIndexer
* Provides child indexer.
* @param passId
* If pass ID mode is on. With this mode, all sub-components created with this
* indexer will have same ID, thus write will be done in same file.
*/
public StorageBranchIndexer(IBranchIndexer<E> delegateIndexer, StorageBranchIndexer<E> childIndexer, boolean passId) {
this(delegateIndexer, childIndexer, StorageUtil.getRandomInt(), passId);
}
/**
* This constructor allows setting of all properties.
*
* @param delegateIndexer
* Provides delegate indexer with a constructor.
* @param childIndexer
* Provides child indexer.
* @param id
* Id given to this indexer.
* @param sharedId
* If shared ID mode is on. With this mode, all components created with this indexer
* will have same ID, thus write will be done in same file.
*/
public StorageBranchIndexer(IBranchIndexer<E> delegateIndexer, StorageBranchIndexer<E> childIndexer, int id, boolean sharedId) {
this.delegateIndexer = delegateIndexer;
this.childIndexer = childIndexer;
this.id = id;
this.passId = sharedId;
}
/**
* {@inheritDoc}
*/
@Override
public Object getKey(E element) {
return delegateIndexer.getKey(element);
}
/**
* {@inheritDoc}
*/
@Override
public Object[] getKeys(IIndexQuery query) {
return delegateIndexer.getKeys(query);
}
/**
* {@inheritDoc}
*/
@Override
public boolean sharedInstance() {
return delegateIndexer.sharedInstance();
}
/**
* {@inheritDoc}
*/
@Override
public IStorageBranchIndexer<E> getNewInstance() {
IBranchIndexer<E> branchIndexer = null;
if (sharedInstance()) {
branchIndexer = delegateIndexer;
} else {
branchIndexer = delegateIndexer.getNewInstance();
}
StorageBranchIndexer<E> storageBranchIndexer = new StorageBranchIndexer<>(branchIndexer, childIndexer, passId);
return storageBranchIndexer;
}
/**
* {@inheritDoc}
*/
@Override
public IStorageTreeComponent<E> getNextTreeComponent(E object) {
if (null != childIndexer) {
// if there is child indexer we need to create a branch
if (!childIndexer.isPassId() && !passId) {
// if child is not shared and we don't need to pass id
// just create new branch with child indexer
return new StorageBranch<>(childIndexer);
} else {
// create new instance of child indexer and pass id if necessary
IStorageBranchIndexer<E> indexer = childIndexer.getNewInstance();
if (passId) {
indexer.setId(id);
}
return new StorageBranch<>(indexer);
}
} else {
// if not we need to create Leaf, and pass id is necessary
if (object instanceof InvocationSequenceData) {
// for invocations ArrayBasedStorageLeaf
if (passId) {
return new ArrayBasedStorageLeaf<>(id);
} else {
return new ArrayBasedStorageLeaf<>();
}
} else {
// for everything else LeafWithNoDescriptors
if (passId) {
return new LeafWithNoDescriptors<>(id);
} else {
return new LeafWithNoDescriptors<>();
}
}
}
}
/**
* Gets {@link #id}.
*
* @return {@link #id}
*/
public int getId() {
return id;
}
/**
* Sets {@link #id}.
*
* @param id
* New value for {@link #id}
*/
@Override
public void setId(int id) {
this.id = id;
}
/**
* Gets {@link #passId}.
*
* @return {@link #passId}
*/
public boolean isPassId() {
return passId;
}
/**
* Sets {@link #passId}.
*
* @param sharedId
* New value for {@link #passId}
*/
public void setPassId(boolean sharedId) {
this.passId = sharedId;
}
/**
* Gets {@link #delegateIndexer}.
*
* @return {@link #delegateIndexer}
*/
IBranchIndexer<E> getDelegateIndexer() {
return delegateIndexer;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((childIndexer == null) ? 0 : childIndexer.hashCode());
result = (prime * result) + ((delegateIndexer == null) ? 0 : delegateIndexer.hashCode());
return result;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
StorageBranchIndexer<E> other = (StorageBranchIndexer<E>) obj;
if (childIndexer == null) {
if (other.childIndexer != null) {
return false;
}
} else if (!childIndexer.equals(other.childIndexer)) {
return false;
}
if (delegateIndexer == null) {
if (other.delegateIndexer != null) {
return false;
}
} else if (!delegateIndexer.equals(other.delegateIndexer)) {
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
ToStringBuilder toStringBuilder = new ToStringBuilder(this);
toStringBuilder.append("id", id);
toStringBuilder.append("delegateIndexer", delegateIndexer);
toStringBuilder.append("childIndexer", childIndexer);
toStringBuilder.append("passId", passId);
return toStringBuilder.toString();
}
}