/* * 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; } }