/* * 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.facet.impl; import com.intellij.facet.Facet; import com.intellij.facet.FacetModel; import com.intellij.facet.FacetTypeId; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; /** * @author nik */ public abstract class FacetModelBase implements FacetModel { private volatile Map<FacetTypeId, Collection<Facet>> myType2Facets; private volatile Map<Pair<Facet, FacetTypeId>, Collection<Facet>> myChildFacets; private volatile Facet[] mySortedFacets; @Override @NotNull public Facet[] getSortedFacets() { if (mySortedFacets == null) { final Facet[] allFacets = getAllFacets(); if (allFacets.length == 0) { mySortedFacets = Facet.EMPTY_ARRAY; } else { LinkedHashSet<Facet> facets = new LinkedHashSet<>(); for (Facet facet : allFacets) { addUnderlyingFacets(facets, facet); } mySortedFacets = facets.toArray(new Facet[facets.size()]); } } return mySortedFacets; } private static void addUnderlyingFacets(final LinkedHashSet<Facet> facets, final Facet facet) { final Facet underlyingFacet = facet.getUnderlyingFacet(); if (underlyingFacet != null && !facets.contains(facet)) { addUnderlyingFacets(facets, underlyingFacet); } facets.add(facet); } @Override @NotNull public <F extends Facet> Collection<F> getFacetsByType(@NotNull Facet underlyingFacet, FacetTypeId<F> typeId) { if (myChildFacets == null) { MultiValuesMap<Pair<Facet, FacetTypeId>, Facet> children = new MultiValuesMap<>(); for (Facet facet : getAllFacets()) { final Facet underlying = facet.getUnderlyingFacet(); if (underlying != null) { children.put(Pair.create(underlying, facet.getTypeId()), facet); } } Map<Pair<Facet, FacetTypeId>, Collection<Facet>> childFacets = new HashMap<>(); for (Pair<Facet, FacetTypeId> pair : children.keySet()) { final Collection<Facet> facets = children.get(pair); childFacets.put(pair, Collections.unmodifiableCollection(facets)); } myChildFacets = childFacets; } //noinspection unchecked final Collection<F> facets = (Collection<F>)myChildFacets.get(new Pair(underlyingFacet, typeId)); return facets != null ? facets : Collections.emptyList(); } @Override @NotNull public String getFacetName(@NotNull Facet facet) { return facet.getName(); } @Override @Nullable public <F extends Facet> F findFacet(final FacetTypeId<F> type, final String name) { final Collection<F> fs = getFacetsByType(type); for (F f : fs) { if (f.getName().equals(name)) { return f; } } return null; } @Override @Nullable public <F extends Facet> F getFacetByType(@NotNull final Facet underlyingFacet, final FacetTypeId<F> typeId) { final Collection<F> fs = getFacetsByType(underlyingFacet, typeId); return fs.isEmpty() ? null : fs.iterator().next(); } @Override @Nullable public <F extends Facet> F getFacetByType(FacetTypeId<F> typeId) { final Collection<F> facets = getFacetsByType(typeId); return facets.isEmpty() ? null : facets.iterator().next(); } @Override @NotNull public <F extends Facet> Collection<F> getFacetsByType(FacetTypeId<F> typeId) { if (myType2Facets == null) { MultiValuesMap<FacetTypeId, Facet> typeToFacets = new MultiValuesMap<>(); for (Facet facet : getAllFacets()) { typeToFacets.put(facet.getTypeId(), facet); } Map<FacetTypeId, Collection<Facet>> typeToFacetsCollection = new HashMap<>(); for (FacetTypeId id : typeToFacets.keySet()) { final Collection<Facet> facets = typeToFacets.get(id); typeToFacetsCollection.put(id, Collections.unmodifiableCollection(facets)); } myType2Facets = typeToFacetsCollection; } final Collection<F> facets = (Collection<F>)myType2Facets.get(typeId); return facets != null ? facets : Collections.emptyList(); } protected void facetsChanged() { myChildFacets = null; myType2Facets = null; mySortedFacets = null; } }