81154477a4d9192abfb31596835e49144206f352
[idea/community.git] / platform / lang-impl / src / com / intellij / facet / impl / FacetModelBase.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.facet.impl;
18
19 import com.intellij.facet.Facet;
20 import com.intellij.facet.FacetModel;
21 import com.intellij.facet.FacetTypeId;
22 import com.intellij.openapi.util.MultiValuesMap;
23 import com.intellij.openapi.util.Pair;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
26
27 import java.util.*;
28
29 /**
30  * @author nik
31  */
32 public abstract class FacetModelBase implements FacetModel {
33   private volatile Map<FacetTypeId, Collection<Facet>> myType2Facets;
34   private volatile Map<Pair<Facet, FacetTypeId>, Collection<Facet>> myChildFacets;
35   private volatile Facet[] mySortedFacets;
36
37   @Override
38   @NotNull
39   public Facet[] getSortedFacets() {
40     if (mySortedFacets == null) {
41       final Facet[] allFacets = getAllFacets();
42       if (allFacets.length == 0) {
43         mySortedFacets = Facet.EMPTY_ARRAY;
44       }
45       else {
46         LinkedHashSet<Facet> facets = new LinkedHashSet<>();
47         for (Facet facet : allFacets) {
48           addUnderlyingFacets(facets, facet);
49         }
50         mySortedFacets = facets.toArray(Facet.EMPTY_ARRAY);
51       }
52     }
53     return mySortedFacets;
54   }
55
56   private static void addUnderlyingFacets(final LinkedHashSet<? super Facet> facets, final Facet facet) {
57     final Facet underlyingFacet = facet.getUnderlyingFacet();
58     if (underlyingFacet != null && !facets.contains(facet)) {
59       addUnderlyingFacets(facets, underlyingFacet);
60     }
61     facets.add(facet);
62   }
63
64   @Override
65   @NotNull
66   public <F extends Facet> Collection<F> getFacetsByType(@NotNull Facet underlyingFacet, FacetTypeId<F> typeId) {
67     if (myChildFacets == null) {
68       MultiValuesMap<Pair<Facet, FacetTypeId>, Facet> children = new MultiValuesMap<>();
69       for (Facet facet : getAllFacets()) {
70         final Facet underlying = facet.getUnderlyingFacet();
71         if (underlying != null) {
72           children.put(Pair.create(underlying,  facet.getTypeId()), facet);
73         }
74       }
75
76       Map<Pair<Facet, FacetTypeId>, Collection<Facet>> childFacets = new HashMap<>();
77       for (Pair<Facet, FacetTypeId> pair : children.keySet()) {
78         final Collection<Facet> facets = children.get(pair);
79         childFacets.put(pair, Collections.unmodifiableCollection(facets));
80       }
81       myChildFacets = childFacets;
82     }
83     //noinspection unchecked
84     final Collection<F> facets = (Collection<F>)myChildFacets.get(new Pair(underlyingFacet, typeId));
85     return facets != null ? facets : Collections.emptyList();
86   }
87
88   @Override
89   @NotNull
90   public String getFacetName(@NotNull Facet facet) {
91     return facet.getName();
92   }
93
94   @Override
95   @Nullable
96   public <F extends Facet> F findFacet(final FacetTypeId<F> type, final String name) {
97     final Collection<F> fs = getFacetsByType(type);
98     for (F f : fs) {
99       if (f.getName().equals(name)) {
100         return f;
101       }
102     }
103     return null;
104   }
105
106   @Override
107   @Nullable
108   public <F extends Facet> F getFacetByType(@NotNull final Facet underlyingFacet, final FacetTypeId<F> typeId) {
109     final Collection<F> fs = getFacetsByType(underlyingFacet, typeId);
110     return fs.isEmpty() ? null : fs.iterator().next();
111   }
112
113   @Override
114   @Nullable
115   public <F extends Facet> F getFacetByType(FacetTypeId<F> typeId) {
116     final Collection<F> facets = getFacetsByType(typeId);
117     return facets.isEmpty() ? null : facets.iterator().next();
118   }
119
120   @Override
121   @NotNull
122   public <F extends Facet> Collection<F> getFacetsByType(FacetTypeId<F> typeId) {
123     if (myType2Facets == null) {
124       MultiValuesMap<FacetTypeId, Facet> typeToFacets = new MultiValuesMap<>();
125       for (Facet facet : getAllFacets()) {
126         typeToFacets.put(facet.getTypeId(), facet);
127       }
128       Map<FacetTypeId, Collection<Facet>> typeToFacetsCollection = new HashMap<>();
129       for (FacetTypeId id : typeToFacets.keySet()) {
130         final Collection<Facet> facets = typeToFacets.get(id);
131         typeToFacetsCollection.put(id, Collections.unmodifiableCollection(facets));
132       }
133       myType2Facets = typeToFacetsCollection;
134     }
135
136     final Collection<F> facets = (Collection<F>)myType2Facets.get(typeId);
137     return facets != null ? facets : Collections.emptyList();
138   }
139
140   protected void facetsChanged() {
141     myChildFacets = null;
142     myType2Facets = null;
143     mySortedFacets = null;
144   }
145 }