/* * 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.smodel.adapter.structure.ref; import jetbrains.mps.scope.Scope; import jetbrains.mps.smodel.SNodeUtil; import jetbrains.mps.smodel.adapter.ids.SConceptId; import jetbrains.mps.smodel.adapter.structure.FormatException; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.smodel.constraints.ModelConstraints; import jetbrains.mps.smodel.language.ConceptRegistry; import jetbrains.mps.smodel.runtime.ConceptDescriptor; import jetbrains.mps.smodel.runtime.ReferenceDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.language.SAbstractConcept; import org.jetbrains.mps.openapi.language.SContainmentLink; import org.jetbrains.mps.openapi.language.SReferenceLink; import org.jetbrains.mps.openapi.language.SScope; import org.jetbrains.mps.openapi.model.SNode; public abstract class SReferenceLinkAdapter implements SReferenceLink { public static final String ID_DELIM = ":"; protected String myName; protected SReferenceLinkAdapter(@NotNull String name) { myName = name; } @NotNull @Override public String getName() { return getRoleName(); } @Nullable public abstract ReferenceDescriptor getReferenceDescriptor(); @Override public boolean isValid() { return getReferenceDescriptor() != null; } @NotNull public abstract SAbstractConcept getOwner(); @Override public String getRole() { return getRoleName(); } @Override public boolean isOptional() { ReferenceDescriptor rd = getReferenceDescriptor(); if (rd == null) { return true; } return rd.isOptional(); } @NotNull @Override public SAbstractConcept getTargetConcept() { ReferenceDescriptor rd = getReferenceDescriptor(); if (rd == null) { return SNodeUtil.concept_BaseConcept; } SConceptId id = rd.getTargetConcept(); ConceptDescriptor concept = ConceptRegistry.getInstance().getConceptDescriptor(id); return MetaAdapterFactory.getAbstractConcept(concept); } @Override public boolean isReference() { return true; } @Override public boolean isMultiple() { return false; } public SScope getScope(SNode referenceNode) { Scope scope = ModelConstraints.getReferenceDescriptor(referenceNode, this).getScope(); return new SScopeAdapter(scope, referenceNode); } public SScope getScope(SNode contextNode, @Nullable SContainmentLink link, int index) { Scope scope = ModelConstraints.getReferenceDescriptor(contextNode, link, index, this).getScope(); return new SScopeAdapter(scope, contextNode); } private static class SScopeAdapter implements SScope { private final SNode myContextNode; private final Scope myScope; private SScopeAdapter(@NotNull Scope scope, @NotNull SNode contextNode) { myScope = scope; myContextNode = contextNode; } public Iterable<SNode> getAvailableElements(@Nullable String prefix) { return myScope.getAvailableElements(prefix); } public boolean contains(SNode node) { return myScope.contains(node); } @Nullable public SNode resolve(@NotNull String string) { return myScope.resolve(myContextNode, string); } @Nullable public String getReferenceText(@NotNull SNode node) { return myScope.getReferenceText(myContextNode, node); } } @Override public String toString() { return myName; } public abstract String serialize(); public static SReferenceLinkAdapter deserialize(String s) { if (s.startsWith(SReferenceLinkAdapterById.REF_PREFIX)) { return SReferenceLinkAdapterById.deserialize(s); } else if (s.startsWith(InvalidReferenceLink.INVALID_PREFIX)) { return InvalidReferenceLink.deserialize(s); } else { throw new FormatException("Illegal ref type: " + s); } } }