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 com.google.common.base.Preconditions; 024import com.google.common.base.Predicate; 025import com.google.common.collect.Collections2; 026import com.google.common.collect.ImmutableList; 027import com.google.common.collect.ImmutableMap; 028import com.google.common.collect.ImmutableSet; 029import com.google.common.collect.Lists; 030import com.google.common.collect.Maps; 031import com.google.common.collect.Sets; 032import java.util.ArrayList; 033import java.util.Collection; 034import java.util.Collections; 035import java.util.List; 036import java.util.Map; 037import java.util.Objects; 038import javax.annotation.Nullable; 039import org.sonar.api.ce.ComputeEngineSide; 040import org.sonar.api.server.ServerSide; 041 042/** 043 * @since 2.14 044 */ 045@Beta 046@ServerSide 047@ComputeEngineSide 048public class ResourceTypes { 049 050 public static final Predicate<ResourceType> AVAILABLE_FOR_FILTERS = input -> input != null && input.getBooleanProperty("supportsMeasureFilters"); 051 052 private final Map<String, ResourceTypeTree> treeByQualifier; 053 private final Map<String, ResourceType> typeByQualifier; 054 private final Collection<ResourceType> orderedTypes; 055 private final Collection<ResourceType> rootTypes; 056 057 public ResourceTypes() { 058 this(new ResourceTypeTree[0]); 059 } 060 061 public ResourceTypes(ResourceTypeTree[] trees) { 062 Preconditions.checkNotNull(trees); 063 064 Map<String, ResourceTypeTree> treeMap = Maps.newHashMap(); 065 Map<String, ResourceType> typeMap = Maps.newLinkedHashMap(); 066 Collection<ResourceType> rootsSet = Sets.newHashSet(); 067 068 for (ResourceTypeTree tree : trees) { 069 rootsSet.add(tree.getRootType()); 070 for (ResourceType type : tree.getTypes()) { 071 if (treeMap.containsKey(type.getQualifier())) { 072 throw new IllegalStateException("Qualifier " + type.getQualifier() + " is defined in several trees"); 073 } 074 treeMap.put(type.getQualifier(), tree); 075 typeMap.put(type.getQualifier(), type); 076 } 077 } 078 treeByQualifier = ImmutableMap.copyOf(treeMap); 079 typeByQualifier = ImmutableMap.copyOf(typeMap); 080 rootTypes = ImmutableList.copyOf(rootsSet); 081 082 List<ResourceType> mutableOrderedTypes = new ArrayList<>(); 083 ResourceType view = null; 084 ResourceType subView = null; 085 for (ResourceType resourceType : typeByQualifier.values()) { 086 if (Qualifiers.VIEW.equals(resourceType.getQualifier())) { 087 view = resourceType; 088 } else if (Qualifiers.SUBVIEW.equals(resourceType.getQualifier())) { 089 subView = resourceType; 090 } else { 091 mutableOrderedTypes.add(resourceType); 092 } 093 } 094 if (subView != null) { 095 mutableOrderedTypes.add(0, subView); 096 } 097 if (view != null) { 098 mutableOrderedTypes.add(0, view); 099 } 100 101 orderedTypes = ImmutableSet.copyOf(mutableOrderedTypes); 102 } 103 104 public ResourceType get(String qualifier) { 105 ResourceType type = typeByQualifier.get(qualifier); 106 return type != null ? type : ResourceType.builder(qualifier).build(); 107 } 108 109 public Collection<ResourceType> getAll() { 110 return typeByQualifier.values(); 111 } 112 113 public Collection<ResourceType> getAllOrdered() { 114 return orderedTypes; 115 } 116 117 public Collection<ResourceType> getRoots() { 118 return rootTypes; 119 } 120 121 public Collection<ResourceType> getAll(Predicate<ResourceType> predicate) { 122 return Collections2.filter(typeByQualifier.values(), predicate); 123 } 124 125 private static class PropertyKeyPredicate implements Predicate<ResourceType> { 126 private final String propertyKey; 127 128 public PropertyKeyPredicate(String propertyKey) { 129 this.propertyKey = propertyKey; 130 } 131 132 @Override 133 public boolean apply(@Nullable ResourceType input) { 134 return input != null && input.hasProperty(propertyKey); 135 } 136 } 137 138 public Collection<ResourceType> getAllWithPropertyKey(final String propertyKey) { 139 return Collections2.filter(typeByQualifier.values(), new PropertyKeyPredicate(propertyKey)); 140 } 141 142 private static class StringPropertyValuePredicate implements Predicate<ResourceType> { 143 private final String propertyValue; 144 private final String propertyKey; 145 146 public StringPropertyValuePredicate(String propertyValue, String propertyKey) { 147 this.propertyValue = propertyValue; 148 this.propertyKey = propertyKey; 149 } 150 151 @Override 152 public boolean apply(@Nullable ResourceType input) { 153 return input != null && Objects.equals(propertyValue, input.getStringProperty(propertyKey)); 154 } 155 } 156 157 public Collection<ResourceType> getAllWithPropertyValue(final String propertyKey, final String propertyValue) { 158 return Collections2.filter(typeByQualifier.values(), new StringPropertyValuePredicate(propertyValue, propertyKey)); 159 } 160 161 private static class BooleanPropertyValuePredicate implements Predicate<ResourceType> { 162 private final String propertyKey; 163 private final boolean propertyValue; 164 165 public BooleanPropertyValuePredicate(String propertyKey, boolean propertyValue) { 166 this.propertyKey = propertyKey; 167 this.propertyValue = propertyValue; 168 } 169 170 @Override 171 public boolean apply(@Nullable ResourceType input) { 172 return input != null && input.getBooleanProperty(propertyKey) == propertyValue; 173 } 174 } 175 176 public Collection<ResourceType> getAllWithPropertyValue(final String propertyKey, final boolean propertyValue) { 177 return Collections2.filter(typeByQualifier.values(), new BooleanPropertyValuePredicate(propertyKey, propertyValue)); 178 } 179 180 public List<String> getChildrenQualifiers(String qualifier) { 181 ResourceTypeTree tree = getTree(qualifier); 182 if (tree != null) { 183 return tree.getChildren(qualifier); 184 } 185 return Collections.emptyList(); 186 } 187 188 public List<ResourceType> getChildren(String qualifier) { 189 return Lists.transform(getChildrenQualifiers(qualifier), typeByQualifier::get); 190 } 191 192 public List<String> getLeavesQualifiers(String qualifier) { 193 ResourceTypeTree tree = getTree(qualifier); 194 if (tree != null) { 195 return tree.getLeaves(); 196 } 197 return Collections.emptyList(); 198 } 199 200 public ResourceTypeTree getTree(String qualifier) { 201 return treeByQualifier.get(qualifier); 202 } 203 204 public ResourceType getRoot(String qualifier) { 205 return getTree(qualifier).getRootType(); 206 } 207 208}