refactored jsf model
[fedora-idea.git] / dom / openapi / src / com / intellij / util / xml / model / impl / CachedMultipleDomModelFactory.java
blob54692b5eded944e51b52c9fdef7229c461b433fc
1 package com.intellij.util.xml.model.impl;
3 import com.intellij.openapi.project.Project;
4 import com.intellij.openapi.util.UserDataHolder;
5 import com.intellij.psi.PsiElement;
6 import com.intellij.psi.util.CachedValueProvider;
7 import com.intellij.psi.xml.XmlFile;
8 import com.intellij.util.containers.ContainerUtil;
9 import com.intellij.util.xml.DomElement;
10 import com.intellij.util.xml.DomFileElement;
11 import com.intellij.util.xml.DomManager;
12 import com.intellij.util.xml.ModelMerger;
13 import com.intellij.util.xml.model.DomModel;
14 import com.intellij.util.xml.model.DomModelCache;
15 import com.intellij.util.xml.model.MultipleDomModelFactory;
16 import org.jetbrains.annotations.NonNls;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
20 import java.util.*;
22 /**
23 * User: Sergey.Vasiliev
25 public abstract class CachedMultipleDomModelFactory<Scope extends UserDataHolder, T extends DomElement, M extends DomModel<T>, C extends PsiElement>
26 extends DomModelFactoryHelper<T>
27 implements CachedDomModelFactory<T,M,Scope>, MultipleDomModelFactory<Scope,T,M> {
29 private final DomModelCache<M, Scope> myCombinedModelCache;
30 private final DomModelCache<List<M>, Scope> myAllModelsCache;
33 protected CachedMultipleDomModelFactory(@NotNull Class<T> aClass,
34 @NotNull ModelMerger modelMerger,
35 final Project project,
36 @NonNls String name) {
37 super(aClass,modelMerger);
39 myCombinedModelCache = new DomModelCache<M, Scope>(project, name + " combined model") {
40 @NotNull
41 protected CachedValueProvider.Result<M> computeValue(@NotNull final Scope scope) {
42 final M combinedModel = computeCombinedModel(scope);
43 return new CachedValueProvider.Result<M>(combinedModel, computeDependencies(combinedModel, scope));
47 myAllModelsCache = new DomModelCache<List<M>, Scope>(project, name + " models list") {
48 @NotNull
49 protected CachedValueProvider.Result<List<M>> computeValue(@NotNull final Scope scope) {
50 final List<M> models = computeAllModels(scope);
51 return new CachedValueProvider.Result<List<M>>(models, computeDependencies(null, scope));
56 @Nullable
57 public abstract M getModel(@NotNull C context);
59 @NotNull
60 public List<M> getAllModels(@NotNull Scope scope) {
62 final List<M> models = myAllModelsCache.getCachedValue(scope);
63 if (models == null) {
64 return Collections.emptyList();
66 else {
67 return models;
71 @Nullable
72 protected abstract List<M> computeAllModels(@NotNull Scope scope);
74 @Nullable
75 public M getCombinedModel(@Nullable Scope scope) {
76 if (scope == null) {
77 return null;
79 return myCombinedModelCache.getCachedValue(scope);
82 @Nullable
83 protected M computeCombinedModel(@NotNull Scope scope) {
84 final List<M> models = getAllModels(scope);
85 switch (models.size()) {
86 case 0:
87 return null;
88 case 1:
89 return models.get(0);
91 final Set<XmlFile> configFiles = new LinkedHashSet<XmlFile>();
92 final LinkedHashSet<DomFileElement<T>> list = new LinkedHashSet<DomFileElement<T>>(models.size());
93 for (M model: models) {
94 final Set<XmlFile> files = model.getConfigFiles();
95 for (XmlFile file: files) {
96 ContainerUtil.addIfNotNull(getDomRoot(file), list);
98 configFiles.addAll(files);
100 final DomFileElement<T> mergedModel = getModelMerger().mergeModels(DomFileElement.class, list);
101 final M firstModel = models.get(0);
102 return createCombinedModel(configFiles, mergedModel, firstModel, scope);
106 * Factory method to create combined model for given module.
107 * Used by {@link #computeCombinedModel(com.intellij.openapi.module.Module)}.
109 * @param configFiles file set including all files for all models returned by {@link #getAllModels(com.intellij.openapi.module.Module)}.
110 * @param mergedModel merged model for all models returned by {@link #getAllModels(com.intellij.openapi.module.Module)}.
111 * @param firstModel the first model returned by {@link #getAllModels(com.intellij.openapi.module.Module)}.
112 * @param scope
113 * @return combined model.
115 protected abstract M createCombinedModel(Set<XmlFile> configFiles, DomFileElement<T> mergedModel, M firstModel, final Scope scope);
117 @NotNull
118 public Set<XmlFile> getConfigFiles(@Nullable C context) {
119 if (context == null) {
120 return Collections.emptySet();
122 final M model = getModel(context);
123 if (model == null) {
124 return Collections.emptySet();
126 else {
127 return model.getConfigFiles();
131 @NotNull
132 public Set<XmlFile> getAllConfigFiles(@NotNull Scope scope) {
133 final HashSet<XmlFile> xmlFiles = new HashSet<XmlFile>();
134 for (M model: getAllModels(scope)) {
135 xmlFiles.addAll(model.getConfigFiles());
137 return xmlFiles;
140 public List<DomFileElement<T>> getFileElements(M model) {
141 final ArrayList<DomFileElement<T>> list = new ArrayList<DomFileElement<T>>(model.getConfigFiles().size());
142 for (XmlFile configFile: model.getConfigFiles()) {
143 final DomFileElement<T> element = DomManager.getDomManager(configFile.getProject()).getFileElement(configFile, myClass);
144 if (element != null) {
145 list.add(element);
148 return list;