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