cleanup
[idea/community.git] / platform / lang-impl / src / com / intellij / facet / impl / FacetModelBase.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.facet.impl;
4
5 import com.intellij.facet.Facet;
6 import com.intellij.facet.FacetModel;
7 import com.intellij.facet.FacetTypeId;
8 import com.intellij.openapi.util.MultiValuesMap;
9 import com.intellij.openapi.util.Pair;
10 import org.jetbrains.annotations.NotNull;
11 import org.jetbrains.annotations.Nullable;
12
13 import java.util.*;
14
15 /**
16  * @author nik
17  */
18 public abstract class FacetModelBase implements FacetModel {
19   private volatile Map<FacetTypeId<?>, Collection<Facet<?>>> myType2Facets;
20   private volatile Map<Pair<Facet<?>, FacetTypeId<?>>, Collection<Facet<?>>> myChildFacets;
21   private volatile Facet<?>[] mySortedFacets;
22
23   @Override
24   @NotNull
25   public Facet<?>[] getSortedFacets() {
26     if (mySortedFacets == null) {
27       final Facet<?>[] allFacets = getAllFacets();
28       if (allFacets.length == 0) {
29         mySortedFacets = Facet.EMPTY_ARRAY;
30       }
31       else {
32         LinkedHashSet<Facet<?>> facets = new LinkedHashSet<>();
33         for (Facet<?> facet : allFacets) {
34           addUnderlyingFacets(facets, facet);
35         }
36         mySortedFacets = facets.toArray(Facet.EMPTY_ARRAY);
37       }
38     }
39     return mySortedFacets;
40   }
41
42   private static void addUnderlyingFacets(final LinkedHashSet<? super Facet<?>> facets, final Facet<?> facet) {
43     final Facet<?> underlyingFacet = facet.getUnderlyingFacet();
44     if (underlyingFacet != null && !facets.contains(facet)) {
45       addUnderlyingFacets(facets, underlyingFacet);
46     }
47     facets.add(facet);
48   }
49
50   @Override
51   @NotNull
52   public <F extends Facet<?>> Collection<F> getFacetsByType(@NotNull Facet<?> underlyingFacet, FacetTypeId<F> typeId) {
53     if (myChildFacets == null) {
54       MultiValuesMap<Pair<Facet<?>, FacetTypeId<?>>, Facet<?>> children = new MultiValuesMap<>();
55       for (Facet<?> facet : getAllFacets()) {
56         final Facet<?> underlying = facet.getUnderlyingFacet();
57         if (underlying != null) {
58           children.put(new Pair<>(underlying,  facet.getTypeId()), facet);
59         }
60       }
61
62       Map<Pair<Facet<?>, FacetTypeId<?>>, Collection<Facet<?>>> childFacets = new HashMap<>();
63       for (Pair<Facet<?>, FacetTypeId<?>> pair : children.keySet()) {
64         final Collection<Facet<?>> facets = children.get(pair);
65         childFacets.put(pair, Collections.unmodifiableCollection(facets));
66       }
67       myChildFacets = childFacets;
68     }
69     //noinspection unchecked
70     final Collection<F> facets = (Collection<F>)myChildFacets.get(new Pair<>(underlyingFacet, typeId));
71     return facets != null ? facets : Collections.emptyList();
72   }
73
74   @Override
75   @NotNull
76   public String getFacetName(@NotNull Facet facet) {
77     return facet.getName();
78   }
79
80   @Override
81   @Nullable
82   public <F extends Facet<?>> F findFacet(final FacetTypeId<F> type, final String name) {
83     final Collection<F> fs = getFacetsByType(type);
84     for (F f : fs) {
85       if (f.getName().equals(name)) {
86         return f;
87       }
88     }
89     return null;
90   }
91
92   @Override
93   @Nullable
94   public <F extends Facet<?>> F getFacetByType(@NotNull final Facet<?> underlyingFacet, final FacetTypeId<F> typeId) {
95     final Collection<F> fs = getFacetsByType(underlyingFacet, typeId);
96     return fs.isEmpty() ? null : fs.iterator().next();
97   }
98
99   @Override
100   @Nullable
101   public <F extends Facet<?>> F getFacetByType(FacetTypeId<F> typeId) {
102     final Collection<F> facets = getFacetsByType(typeId);
103     return facets.isEmpty() ? null : facets.iterator().next();
104   }
105
106   @Override
107   @NotNull
108   public <F extends Facet<?>> Collection<F> getFacetsByType(FacetTypeId<F> typeId) {
109     if (myType2Facets == null) {
110       MultiValuesMap<FacetTypeId<?>, Facet<?>> typeToFacets = new MultiValuesMap<>();
111       for (Facet<?> facet : getAllFacets()) {
112         typeToFacets.put(facet.getTypeId(), facet);
113       }
114       Map<FacetTypeId<?>, Collection<Facet<?>>> typeToFacetsCollection = new HashMap<>();
115       for (FacetTypeId<?> id : typeToFacets.keySet()) {
116         final Collection<Facet<?>> facets = typeToFacets.get(id);
117         typeToFacetsCollection.put(id, Collections.unmodifiableCollection(facets));
118       }
119       myType2Facets = typeToFacetsCollection;
120     }
121
122     final Collection<F> facets = (Collection<F>)myType2Facets.get(typeId);
123     return facets != null ? facets : Collections.emptyList();
124   }
125
126   protected void facetsChanged() {
127     myChildFacets = null;
128     myType2Facets = null;
129     mySortedFacets = null;
130   }
131 }