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