blob: 49b2f759fca080119a3444781e927b86dab17c66 [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.util.xml;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiReferenceFactory;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.reflect.AbstractDomChildrenDescription;
import com.intellij.util.xml.reflect.DomGenericInfo;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Type;
/**
* @author peter
*/
public abstract class DomManager extends CompositeModificationTracker implements ModificationTracker {
public static final Key<Module> MOCK_ELEMENT_MODULE = Key.create("MockElementModule");
private static final NotNullLazyKey<DomManager, Project> INSTANCE_CACHE = ServiceManager.createLazyKey(DomManager.class);
public static DomManager getDomManager(Project project) {
return INSTANCE_CACHE.getValue(project);
}
public DomManager(@NotNull Project project) {
super(PsiManager.getInstance(project).getModificationTracker().getOutOfCodeBlockModificationTracker());
}
public abstract Project getProject();
/**
* @param file XML file
* @param domClass desired DOM element class
* @return New or cached DOM file element for the given file. All registered {@link com.intellij.util.xml.DomFileDescription}s are
* asked if they are responsible for the file {@link com.intellij.util.xml.DomFileDescription#isMyFile(com.intellij.psi.xml.XmlFile, com.intellij.openapi.module.Module)}.
* If there is a {@link com.intellij.util.xml.DomFileDescription} that is responsible for the file, but its {@link DomFileDescription#getRootElementClass()}
* result is incompatible with domClass parameter, null is returned
*/
@Nullable
public abstract <T extends DomElement> DomFileElement<T> getFileElement(XmlFile file, Class<T> domClass);
@Nullable
@Deprecated
/**
* @deprecated use {@link #getFileElement(XmlFile, Class)}
*/
public abstract <T extends DomElement> DomFileElement<T> getFileElement(XmlFile file);
@NotNull
@Deprecated
/**
* @deprecated use {@link #getFileElement(XmlFile, Class)}
*/
public abstract <T extends DomElement> DomFileElement<T> getFileElement(XmlFile file, Class<T> aClass, @NonNls String rootTagName);
public abstract void addDomEventListener(DomEventListener listener, Disposable parentDisposable);
/**
* @param type Type. Only {@link Class} and {@link java.lang.reflect.ParameterizedType} are allowed
* @return {@link com.intellij.util.xml.reflect.DomGenericInfo} instance for the desired type
*/
public abstract DomGenericInfo getGenericInfo(Type type);
/**
* @param element tag
* @return DOM element for the given tag. If DOM isn't initialized for the containing file, it will be initialized
*/
@Nullable
public abstract DomElement getDomElement(@Nullable final XmlTag element);
/**
* @param element attribute
* @return DOM element for the given XML attribute. If DOM isn't initialized for the containing file, it will be initialized
*/
@Nullable
public abstract GenericAttributeValue getDomElement(final XmlAttribute element);
/**
* @param aClass Desired DOM element class
* @param module One may wish the result to think that it is in a particular module
* @param physical see {@link com.intellij.psi.PsiFile#isPhysical()}
* @return DOM element which doesn't have any real file under itself. A mock file is created for it. See
* {@link com.intellij.psi.PsiFileFactory#createFileFromText(String, com.intellij.openapi.fileTypes.FileType, CharSequence, long, boolean, boolean)}
*/
public abstract <T extends DomElement> T createMockElement(Class<T> aClass, final Module module, final boolean physical);
/**
* @param element DOM element
* @return true if this element was created by {@link #createMockElement(Class, com.intellij.openapi.module.Module, boolean)} method
*/
public abstract boolean isMockElement(DomElement element);
/**
* Creates DOM element of needed type, that is wrapper around real DOM element. Once the wrapped element
* becomes invalid, a new value is requested from provider parameter, so there's a possibility to
* restore the functionality. The resulting element will also implement StableElement interface.
*
* @param provider provides values to be wrapped
* @return stable DOM element
*/
public abstract <T extends DomElement> T createStableValue(Factory<T> provider);
public abstract <T> T createStableValue(final Factory<T> provider, final Condition<T> validator);
/**
* Registers a new {@link com.intellij.util.xml.DomFileDescription} within the manager. The description parameter describes some DOM
* parameters and restrictions to the particular XML files, that need DOM support. Should be called on
* {@link com.intellij.openapi.components.ProjectComponent} loading.
* @param description The description in question
* @deprecated Make your file description an extension (see {@link com.intellij.util.xml.DomFileDescription#EP_NAME})
*/
public abstract void registerFileDescription(DomFileDescription description);
/**
* @return {@link com.intellij.util.xml.ConverterManager} instance
* @deprecated This will be moved at the application level
*/
public abstract ConverterManager getConverterManager();
@Deprecated
public abstract void addPsiReferenceFactoryForClass(Class clazz, PsiReferenceFactory psiReferenceFactory);
public abstract ModelMerger createModelMerger();
/**
* @param element reference element
* @return element that represents the resolve scope for the given reference. {@link com.intellij.util.xml.DomResolveConverter} uses
* this method to resolve DOM references. This result's subtree will be traversed recursively searching for the reference target. See
* {@link com.intellij.util.xml.Resolve} annotation.
*/
@NotNull
public abstract DomElement getResolvingScope(GenericDomValue element);
/**
* @param element Named DOM element
* @return The scope within which the element's name identity will be checked by
* {@link com.intellij.util.xml.highlighting.DomHighlightingHelper#checkNameIdentity(DomElement, com.intellij.util.xml.highlighting.DomElementAnnotationHolder)}
*/
@Nullable
public abstract DomElement getIdentityScope(DomElement element);
/**
* @return {@link com.intellij.util.xml.TypeChooserManager} instance
*/
public abstract TypeChooserManager getTypeChooserManager();
@Nullable
public abstract AbstractDomChildrenDescription findChildrenDescription(@NotNull XmlTag templateChildTag, @NotNull DomElement parent);
@Nullable
public final DomFileDescription<?> getDomFileDescription(final XmlFile xmlFile) {
final DomFileElement<DomElement> element = getFileElement(xmlFile);
return element != null ? element.getFileDescription() : null;
}
}