001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.resources;
021
022import com.google.common.annotations.Beta;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.LinkedHashMap;
027import java.util.LinkedHashSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Objects;
031import java.util.function.Predicate;
032import java.util.stream.Collectors;
033import org.sonar.api.ce.ComputeEngineSide;
034import org.sonar.api.server.ServerSide;
035
036import static java.util.Collections.unmodifiableList;
037import static java.util.Collections.unmodifiableMap;
038import static java.util.Collections.unmodifiableSet;
039import static java.util.Objects.requireNonNull;
040
041/**
042 * @since 2.14
043 */
044@Beta
045@ServerSide
046@ComputeEngineSide
047public class ResourceTypes {
048
049  public static final Predicate<ResourceType> AVAILABLE_FOR_FILTERS = input -> input != null && input.getBooleanProperty("supportsMeasureFilters");
050
051  private final Map<String, ResourceTypeTree> treeByQualifier;
052  private final Map<String, ResourceType> typeByQualifier;
053  private final Collection<ResourceType> orderedTypes;
054  private final Collection<ResourceType> rootTypes;
055
056  public ResourceTypes() {
057    this(new ResourceTypeTree[0]);
058  }
059
060  public ResourceTypes(ResourceTypeTree[] trees) {
061    requireNonNull(trees);
062
063    Map<String, ResourceTypeTree> treeMap = new LinkedHashMap<>();
064    Map<String, ResourceType> typeMap = new LinkedHashMap<>();
065    Collection<ResourceType> rootsSet = new LinkedHashSet<>();
066
067    for (ResourceTypeTree tree : trees) {
068      rootsSet.add(tree.getRootType());
069      for (ResourceType type : tree.getTypes()) {
070        if (treeMap.containsKey(type.getQualifier())) {
071          throw new IllegalStateException("Qualifier " + type.getQualifier() + " is defined in several trees");
072        }
073        treeMap.put(type.getQualifier(), tree);
074        typeMap.put(type.getQualifier(), type);
075      }
076    }
077    treeByQualifier = unmodifiableMap(new LinkedHashMap<>(treeMap));
078    typeByQualifier = unmodifiableMap(new LinkedHashMap<>(typeMap));
079    rootTypes = unmodifiableList(new ArrayList<>(rootsSet));
080
081    List<ResourceType> mutableOrderedTypes = new ArrayList<>();
082    ResourceType view = null;
083    ResourceType subView = null;
084    for (ResourceType resourceType : typeByQualifier.values()) {
085      if (Qualifiers.VIEW.equals(resourceType.getQualifier())) {
086        view = resourceType;
087      } else if (Qualifiers.SUBVIEW.equals(resourceType.getQualifier())) {
088        subView = resourceType;
089      } else {
090        mutableOrderedTypes.add(resourceType);
091      }
092    }
093    if (subView != null) {
094      mutableOrderedTypes.add(0, subView);
095    }
096    if (view != null) {
097      mutableOrderedTypes.add(0, view);
098    }
099
100    orderedTypes = unmodifiableSet(new LinkedHashSet<>(mutableOrderedTypes));
101  }
102
103  public ResourceType get(String qualifier) {
104    ResourceType type = typeByQualifier.get(qualifier);
105    return type != null ? type : ResourceType.builder(qualifier).build();
106  }
107
108  public Collection<ResourceType> getAll() {
109    return typeByQualifier.values();
110  }
111
112  public Collection<ResourceType> getAllOrdered() {
113    return orderedTypes;
114  }
115
116  public Collection<ResourceType> getRoots() {
117    return rootTypes;
118  }
119
120  public Collection<ResourceType> getAll(Predicate<ResourceType> predicate) {
121    return typeByQualifier.values().stream()
122      .filter(predicate)
123      .collect(Collectors.toList());
124  }
125
126  public Collection<ResourceType> getAllWithPropertyKey(String propertyKey) {
127    return typeByQualifier.values()
128      .stream()
129      .filter(Objects::nonNull)
130      .filter(input -> input.hasProperty(propertyKey))
131      .collect(Collectors.toList());
132  }
133
134  public Collection<ResourceType> getAllWithPropertyValue(String propertyKey, String propertyValue) {
135    return typeByQualifier.values()
136      .stream()
137      .filter(Objects::nonNull)
138      .filter(input -> Objects.equals(propertyValue, input.getStringProperty(propertyKey)))
139      .collect(Collectors.toList());
140  }
141
142  public Collection<ResourceType> getAllWithPropertyValue(String propertyKey, boolean propertyValue) {
143    return typeByQualifier.values()
144      .stream()
145      .filter(Objects::nonNull)
146      .filter(input -> input.getBooleanProperty(propertyKey) == propertyValue)
147      .collect(Collectors.toList());
148  }
149
150  public List<String> getChildrenQualifiers(String qualifier) {
151    ResourceTypeTree tree = getTree(qualifier);
152    if (tree != null) {
153      return tree.getChildren(qualifier);
154    }
155    return Collections.emptyList();
156  }
157
158  public List<ResourceType> getChildren(String qualifier) {
159    return getChildrenQualifiers(qualifier)
160      .stream()
161      .map(typeByQualifier::get)
162      .collect(Collectors.toList());
163  }
164
165  public List<String> getLeavesQualifiers(String qualifier) {
166    ResourceTypeTree tree = getTree(qualifier);
167    if (tree != null) {
168      return tree.getLeaves();
169    }
170    return Collections.emptyList();
171  }
172
173  public ResourceTypeTree getTree(String qualifier) {
174    return treeByQualifier.get(qualifier);
175  }
176
177  public ResourceType getRoot(String qualifier) {
178    return getTree(qualifier).getRootType();
179  }
180
181}