summaryrefslogtreecommitdiff
path: root/xml/dom-openapi/src/com/intellij/util/xml/DomManager.java
blob: 01bc1d8195967c29d3c9d3d7d0b22d14cd56620d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 * Copyright 2000-2009 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.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 implements ModificationTracker {
  public static final Key<Module> MOCK_ELEMENT_MODULE = Key.create("MockElementModule");

  private final static NotNullLazyKey<DomManager, Project> INSTANCE_CACHE = ServiceManager.createLazyKey(DomManager.class);

  public static DomManager getDomManager(Project project) {
    return INSTANCE_CACHE.getValue(project);
  }

  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;
  }
}