blob: daf7de410668ede23f0d06ab36325a0b2ea51e6a [file] [log] [blame]
/*
* Copyright 2000-2014 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 com.intellij.psi.impl.source.html.dtd;
import com.intellij.html.RelaxedHtmlNSDescriptor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.SimpleFieldCache;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.schema.TypeDescriptor;
import com.intellij.xml.impl.schema.XmlNSTypeDescriptorProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* @author Maxim.Mossienko
*/
public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware, XmlNSTypeDescriptorProvider {
private final XmlNSDescriptor myDelegate;
private final boolean myRelaxed;
private final boolean myCaseSensitive;
private static final SimpleFieldCache<Map<String, XmlElementDescriptor>, HtmlNSDescriptorImpl> myCachedDeclsCache = new SimpleFieldCache<Map<String, XmlElementDescriptor>, HtmlNSDescriptorImpl>() {
@Override
protected Map<String, XmlElementDescriptor> compute(final HtmlNSDescriptorImpl htmlNSDescriptor) {
return htmlNSDescriptor.doBuildCachedMap();
}
@Override
protected Map<String, XmlElementDescriptor> getValue(final HtmlNSDescriptorImpl htmlNSDescriptor) {
return htmlNSDescriptor.myCachedDecls;
}
@Override
protected void putValue(final Map<String, XmlElementDescriptor> map, final HtmlNSDescriptorImpl htmlNSDescriptor) {
htmlNSDescriptor.myCachedDecls = map;
}
};
private volatile Map<String, XmlElementDescriptor> myCachedDecls;
public HtmlNSDescriptorImpl(XmlNSDescriptor _delegate) {
this(_delegate, _delegate instanceof RelaxedHtmlNSDescriptor, false);
}
public HtmlNSDescriptorImpl(XmlNSDescriptor _delegate, boolean relaxed, boolean caseSensitive) {
myDelegate = _delegate;
myRelaxed = relaxed;
myCaseSensitive = caseSensitive;
}
private Map<String,XmlElementDescriptor> buildDeclarationMap() {
return myCachedDeclsCache.get(this);
}
// Read-only calculation
private HashMap<String, XmlElementDescriptor> doBuildCachedMap() {
HashMap<String, XmlElementDescriptor> decls = new HashMap<String, XmlElementDescriptor>();
XmlElementDescriptor[] elements = myDelegate == null ? XmlElementDescriptor.EMPTY_ARRAY : myDelegate.getRootElementsDescriptors(null);
for (XmlElementDescriptor element : elements) {
decls.put(
element.getName(),
new HtmlElementDescriptorImpl(element, myRelaxed, myCaseSensitive)
);
}
return decls;
}
@Override
public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
String name = tag.getLocalName();
if (!myCaseSensitive) name = name.toLowerCase();
XmlElementDescriptor xmlElementDescriptor = buildDeclarationMap().get(name);
if (xmlElementDescriptor == null && myRelaxed) {
xmlElementDescriptor = myDelegate.getElementDescriptor(tag);
}
return xmlElementDescriptor;
}
@Override
@NotNull
public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument document) {
return myDelegate == null ? XmlElementDescriptor.EMPTY_ARRAY : myDelegate.getRootElementsDescriptors(document);
}
@Override
@Nullable
public XmlFile getDescriptorFile() {
return myDelegate == null ? null : myDelegate.getDescriptorFile();
}
@Override
public boolean isHierarhyEnabled() {
return false;
}
@Override
public PsiElement getDeclaration() {
return myDelegate == null ? null : myDelegate.getDeclaration();
}
@Override
public String getName(PsiElement context) {
return myDelegate == null ? "" : myDelegate.getName(context);
}
@Override
public String getName() {
return myDelegate == null ? "" : myDelegate.getName();
}
@Override
public void init(PsiElement element) {
myDelegate.init(element);
}
@Override
public Object[] getDependences() {
return myDelegate == null ? null : myDelegate.getDependences();
}
@Override
public TypeDescriptor getTypeDescriptor(String name, XmlTag context) {
return myDelegate instanceof XmlNSTypeDescriptorProvider ?
((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(name, context) : null;
}
@Override
public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
return myDelegate instanceof XmlNSTypeDescriptorProvider ?
((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(descriptorTag) : null;
}
}