/*
* Copyright 2003-2016 JetBrains s.r.o.
*
* 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 jetbrains.mps.workbench.index;
import jetbrains.mps.smodel.SNodePointer;
import jetbrains.mps.util.EqualUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.annotations.Immutable;
import org.jetbrains.mps.openapi.model.SModelId;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.model.SNodeId;
import org.jetbrains.mps.openapi.model.SNodeReference;
import org.jetbrains.mps.openapi.module.SModuleId;
import org.jetbrains.mps.openapi.module.SModuleReference;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
/**
* Storage-friendly but human-hostile representation of a node identity, to keep where node might need to get resolved, but
* no reporting to user (to present a human-readable model/module name) is expected.
* <p/>
* This class is intentionally kept free of IDEA interfaces (e.g. the code to serialize with IDEA Indexer is kept in {@link SNodeEntryExternalizer})
* to make it possible to move to to SModel implementation module (it looks as a nice candidate to replace serialized SNodeReference where
* no human-readable names are of use).
* <p/>
* Implementation note: it's essential to implement equals/hashCode to use this class as Value for c.i.util.indexing.FileBasedIndexExtension
*
* @author Artem Tikhomirov
* @since 3.4
*/
@Immutable
public final class SNodeEntry {
private final SModuleId myModule;
private final SModelId myModel;
private final SNodeId myNode;
public SNodeEntry(@NotNull SNodeReference node) {
SModelReference modelReference = node.getModelReference();
if (modelReference == null) {
throw new IllegalArgumentException(String.format("Pointer to unknown node: %s", node));
}
myModule = modelReference.getModelId().isGloballyUnique() ? null : modelReference.getModuleReference().getModuleId();
myModel = modelReference.getModelId();
myNode = node.getNodeId();
}
public SNodeEntry(@Nullable SModuleId module, @NotNull SModelId model, @NotNull SNodeId node) {
assert module != null || model.isGloballyUnique();
myModule = module;
myModel = model;
myNode = node;
}
@Nullable
public SModuleId getModuleId() {
return myModule;
}
@NotNull
public SModelId getModelId() {
return myModel;
}
@NotNull
public SNodeId getNodeId() {
return myNode;
}
@NotNull
public SNodeReference getNodePointer() {
SModuleReference moduleRef = myModule == null ? null : PersistenceFacade.getInstance().createModuleReference(myModule, "");
SModelReference modelRef = PersistenceFacade.getInstance().createModelReference(moduleRef, myModel, "");
return new SNodePointer(modelRef, myNode);
}
@Override
public int hashCode() {
return myNode.hashCode() * 31 + myModel.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SNodeEntry) {
SNodeEntry o = (SNodeEntry) obj;
return myNode.equals(o.myNode) && myModel.equals(o.myModel) && EqualUtil.equals(myModule, o.myModule);
}
return false;
}
}