/*
* 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.runtime.illegal;
import jetbrains.mps.smodel.adapter.ids.MetaIdFactory;
import jetbrains.mps.smodel.adapter.ids.SConceptId;
import jetbrains.mps.smodel.adapter.ids.SContainmentLinkId;
import jetbrains.mps.smodel.adapter.ids.SPropertyId;
import jetbrains.mps.smodel.adapter.ids.SReferenceLinkId;
import jetbrains.mps.smodel.runtime.ConceptDescriptor;
import jetbrains.mps.smodel.runtime.ConceptKind;
import jetbrains.mps.smodel.runtime.LinkDescriptor;
import jetbrains.mps.smodel.runtime.PropertyDescriptor;
import jetbrains.mps.smodel.runtime.ReferenceDescriptor;
import jetbrains.mps.smodel.runtime.StaticScope;
import jetbrains.mps.util.NameUtil;
import jetbrains.mps.util.containers.ConcurrentHashSet;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SNodeReference;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class IllegalConceptDescriptor implements ConceptDescriptor {
private static final Logger LOG = LogManager.getLogger(IllegalConceptDescriptor.class);
private static final Set<String> ourReportedConcepts = new ConcurrentHashSet<>();
private static final Set<SConceptId> ourReportedConceptIds = new ConcurrentHashSet<>();
private boolean myReported = false;
@NotNull
private final SConceptId myConceptId;
@NotNull
private final String myConceptName;
@Nullable
private final String myLanguageName; // null indicates we don't know concept name nor language name
/**
* Covers the case when attempt to find a concept by its known id failed.
* Generally shall not face {@link MetaIdFactory#INVALID_CONCEPT_ID}, although
* tolerates the value ({@link #getConceptFqName} gives different name in this case).
*
* @param concept
*/
public IllegalConceptDescriptor(@NotNull SConceptId concept) {
myConceptId = concept;
myConceptName = concept == MetaIdFactory.INVALID_CONCEPT_ID ? MetaIdFactory.INVALID_CONCEPT_NAME : "<unknown>";
myLanguageName = null;
}
/**
* General case when we know name of the concept being looked up
*/
public IllegalConceptDescriptor(@NotNull SConceptId concept, @NotNull String conceptQualifiedName) {
myConceptId = concept;
myConceptName = conceptQualifiedName;
// language name won't be null even if conceptQualifiedName doesn't match expected pattern.
myLanguageName = NameUtil.namespaceFromConceptFQName(conceptQualifiedName);
}
private void reportWarn() {
if (myReported) {
return;
}
myReported = true;
if (myLanguageName != null) {
if (ourReportedConcepts.add(myConceptName)) {
String msg = "IllegalConceptDescriptor created for concept %s. Please check the language %s is built and compiled.";
LOG.warn(String.format(msg, myConceptName, myLanguageName));
}
} else {
if (ourReportedConceptIds.add(myConceptId)) {
String msg = "IllegalConceptDescriptor created for concept %s.";
LOG.warn(String.format(msg, myConceptId));
}
}
}
@NotNull
@Override
public SConceptId getId() {
reportWarn();
return myConceptId;
}
@Override
public String getConceptFqName() {
reportWarn();
return myConceptName;
}
@Override
public String getSuperConcept() {
reportWarn();
return null;
}
@Override
public boolean isInterfaceConcept() {
reportWarn();
return false;
}
@Override
public Set<SReferenceLinkId> getReferenceIds() {
reportWarn();
return Collections.emptySet();
}
@Override
public Collection<ReferenceDescriptor> getReferenceDescriptors() {
reportWarn();
return Collections.emptySet();
}
@Override
public ReferenceDescriptor getRefDescriptor(SReferenceLinkId id) {
reportWarn();
return null;
}
@Override
public PropertyDescriptor getPropertyDescriptor(String name) {
reportWarn();
return null;
}
@Override
public ReferenceDescriptor getRefDescriptor(String name) {
reportWarn();
return null;
}
@Override
public LinkDescriptor getLinkDescriptor(String name) {
reportWarn();
return null;
}
@Override
public Set<SContainmentLinkId> getLinkIds() {
reportWarn();
return Collections.emptySet();
}
@Override
public Collection<LinkDescriptor> getLinkDescriptors() {
reportWarn();
return Collections.emptySet();
}
@Override
public LinkDescriptor getLinkDescriptor(SContainmentLinkId id) {
reportWarn();
return null;
}
@Override
public StaticScope getStaticScope() {
reportWarn();
return StaticScope.GLOBAL;
}
@Override
public Set<SPropertyId> getPropertyIds() {
reportWarn();
return Collections.emptySet();
}
@Override
public Collection<PropertyDescriptor> getPropertyDescriptors() {
reportWarn();
return Collections.emptySet();
}
@Override
public PropertyDescriptor getPropertyDescriptor(SPropertyId id) {
reportWarn();
return null;
}
@Override
public ConceptKind getConceptKind() {
reportWarn();
return ConceptKind.NORMAL;
}
@Override
public boolean isAbstract() {
reportWarn();
return false;
}
@Override
public boolean isFinal() {
reportWarn();
return false;
}
@Override
public boolean isRootable() {
return false;
}
@NotNull
@Override
public String getConceptAlias() {
reportWarn();
return "";
}
@Override
public String getConceptShortDescription() {
reportWarn();
return "";
}
@Override
public String getHelpUrl() {
reportWarn();
return "";
}
@Nullable
@Override
public SNodeReference getSourceNode() {
return null;
}
@Nullable
@Override
public SConceptId getSuperConceptId() {
reportWarn();
return MetaIdFactory.INVALID_CONCEPT_ID;
}
@Override
public List<SConceptId> getParentsIds() {
reportWarn();
return Collections.emptyList();
}
@Override
public boolean isAssignableTo(SConceptId conceptId) {
reportWarn();
return false;
}
@Override
public Set<SConceptId> getAncestorsIds() {
reportWarn();
return Collections.emptySet();
}
}