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.Set; 032import java.util.function.Predicate; 033import java.util.stream.Collectors; 034import java.util.stream.Stream; 035import org.sonar.api.ce.ComputeEngineSide; 036import org.sonar.api.server.ServerSide; 037 038import static java.util.Collections.unmodifiableList; 039import static java.util.Collections.unmodifiableMap; 040import static java.util.Collections.unmodifiableSet; 041import static java.util.Objects.requireNonNull; 042 043/** 044 * @since 2.14 045 */ 046@Beta 047@ServerSide 048@ComputeEngineSide 049public class ResourceTypes { 050 051 public static final Predicate<ResourceType> AVAILABLE_FOR_FILTERS = input -> input != null && input.getBooleanProperty("supportsMeasureFilters"); 052 053 private final Map<String, ResourceTypeTree> treeByQualifier; 054 private final Map<String, ResourceType> typeByQualifier; 055 private final Collection<ResourceType> orderedTypes; 056 private final Collection<ResourceType> rootTypes; 057 058 public ResourceTypes() { 059 this(new ResourceTypeTree[0]); 060 } 061 062 public ResourceTypes(ResourceTypeTree[] trees) { 063 requireNonNull(trees); 064 065 Map<String, ResourceTypeTree> treeMap = new LinkedHashMap<>(); 066 Map<String, ResourceType> typeMap = new LinkedHashMap<>(); 067 Collection<ResourceType> rootsSet = new LinkedHashSet<>(); 068 069 for (ResourceTypeTree tree : trees) { 070 rootsSet.add(tree.getRootType()); 071 for (ResourceType type : tree.getTypes()) { 072 if (treeMap.containsKey(type.getQualifier())) { 073 throw new IllegalStateException("Qualifier " + type.getQualifier() + " is defined in several trees"); 074 } 075 treeMap.put(type.getQualifier(), tree); 076 typeMap.put(type.getQualifier(), type); 077 } 078 } 079 treeByQualifier = unmodifiableMap(new LinkedHashMap<>(treeMap)); 080 typeByQualifier = unmodifiableMap(new LinkedHashMap<>(typeMap)); 081 rootTypes = unmodifiableList(new ArrayList<>(rootsSet)); 082 orderedTypes = unmodifiableSet(orderedTypes(typeMap)); 083 } 084 085 private static Set<ResourceType> orderedTypes(Map<String, ResourceType> typeByQualifier) { 086 Map<String, ResourceType> mutableTypesByQualifier = new LinkedHashMap<>(typeByQualifier); 087 ResourceType view = mutableTypesByQualifier.remove(Qualifiers.VIEW); 088 ResourceType subView = mutableTypesByQualifier.remove(Qualifiers.SUBVIEW); 089 ResourceType application = mutableTypesByQualifier.remove(Qualifiers.APP); 090 091 return Stream.concat(Stream.of(view, subView, application), mutableTypesByQualifier.values().stream()) 092 .filter(Objects::nonNull) 093 .collect(Collectors.toCollection(LinkedHashSet::new)); 094 } 095 096 public ResourceType get(String qualifier) { 097 ResourceType type = typeByQualifier.get(qualifier); 098 return type != null ? type : ResourceType.builder(qualifier).build(); 099 } 100 101 public Collection<ResourceType> getAll() { 102 return typeByQualifier.values(); 103 } 104 105 public Collection<ResourceType> getAllOrdered() { 106 return orderedTypes; 107 } 108 109 public Collection<ResourceType> getRoots() { 110 return rootTypes; 111 } 112 113 public Collection<ResourceType> getAll(Predicate<ResourceType> predicate) { 114 return typeByQualifier.values().stream() 115 .filter(predicate) 116 .collect(Collectors.toList()); 117 } 118 119 public Collection<ResourceType> getAllWithPropertyKey(String propertyKey) { 120 return typeByQualifier.values() 121 .stream() 122 .filter(Objects::nonNull) 123 .filter(input -> input.hasProperty(propertyKey)) 124 .collect(Collectors.toList()); 125 } 126 127 public Collection<ResourceType> getAllWithPropertyValue(String propertyKey, String propertyValue) { 128 return typeByQualifier.values() 129 .stream() 130 .filter(Objects::nonNull) 131 .filter(input -> Objects.equals(propertyValue, input.getStringProperty(propertyKey))) 132 .collect(Collectors.toList()); 133 } 134 135 public Collection<ResourceType> getAllWithPropertyValue(String propertyKey, boolean propertyValue) { 136 return typeByQualifier.values() 137 .stream() 138 .filter(Objects::nonNull) 139 .filter(input -> input.getBooleanProperty(propertyKey) == propertyValue) 140 .collect(Collectors.toList()); 141 } 142 143 public List<String> getChildrenQualifiers(String qualifier) { 144 ResourceTypeTree tree = getTree(qualifier); 145 if (tree != null) { 146 return tree.getChildren(qualifier); 147 } 148 return Collections.emptyList(); 149 } 150 151 public List<ResourceType> getChildren(String qualifier) { 152 return getChildrenQualifiers(qualifier) 153 .stream() 154 .map(typeByQualifier::get) 155 .collect(Collectors.toList()); 156 } 157 158 public List<String> getLeavesQualifiers(String qualifier) { 159 ResourceTypeTree tree = getTree(qualifier); 160 if (tree != null) { 161 return tree.getLeaves(); 162 } 163 return Collections.emptyList(); 164 } 165 166 public ResourceTypeTree getTree(String qualifier) { 167 return treeByQualifier.get(qualifier); 168 } 169 170 public ResourceType getRoot(String qualifier) { 171 return getTree(qualifier).getRootType(); 172 } 173 174}