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