001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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     */
020    package org.sonar.api.resources;
021    
022    import com.google.common.annotations.Beta;
023    import com.google.common.base.Function;
024    import com.google.common.base.Objects;
025    import com.google.common.base.Preconditions;
026    import com.google.common.base.Predicate;
027    import com.google.common.collect.Collections2;
028    import com.google.common.collect.ImmutableList;
029    import com.google.common.collect.ImmutableMap;
030    import com.google.common.collect.Lists;
031    import com.google.common.collect.Maps;
032    import com.google.common.collect.Sets;
033    import org.sonar.api.ServerComponent;
034    import org.sonar.api.task.TaskComponent;
035    
036    import javax.annotation.Nullable;
037    
038    import java.util.Collection;
039    import java.util.Collections;
040    import java.util.List;
041    import java.util.Map;
042    
043    /**
044     * @since 2.14
045     */
046    @Beta
047    public class ResourceTypes implements TaskComponent, ServerComponent {
048    
049      public static final Predicate<ResourceType> AVAILABLE_FOR_FILTERS = new Predicate<ResourceType>() {
050        public boolean apply(@Nullable ResourceType input) {
051          return input != null && input.getBooleanProperty("supportsMeasureFilters");
052        }
053      };
054    
055      private final Map<String, ResourceTypeTree> treeByQualifier;
056      private final Map<String, ResourceType> typeByQualifier;
057      private final Collection<ResourceType> rootTypes;
058    
059      public ResourceTypes(ResourceTypeTree[] trees) {
060        Preconditions.checkNotNull(trees);
061    
062        Map<String, ResourceTypeTree> treeMap = Maps.newHashMap();
063        Map<String, ResourceType> typeMap = Maps.newLinkedHashMap();
064        Collection<ResourceType> rootsSet = Sets.newHashSet();
065    
066        for (ResourceTypeTree tree : trees) {
067          rootsSet.add(tree.getRootType());
068          for (ResourceType type : tree.getTypes()) {
069            if (treeMap.containsKey(type.getQualifier())) {
070              throw new IllegalStateException("Qualifier " + type.getQualifier() + " is defined in several trees");
071            }
072            treeMap.put(type.getQualifier(), tree);
073            typeMap.put(type.getQualifier(), type);
074          }
075        }
076        treeByQualifier = ImmutableMap.copyOf(treeMap);
077        typeByQualifier = ImmutableMap.copyOf(typeMap);
078        rootTypes = ImmutableList.copyOf(rootsSet);
079      }
080    
081      public ResourceType get(String qualifier) {
082        ResourceType type = typeByQualifier.get(qualifier);
083        return type != null ? type : ResourceType.builder(qualifier).build();
084      }
085    
086      public Collection<ResourceType> getAll() {
087        return typeByQualifier.values();
088      }
089    
090      public Collection<ResourceType> getRoots() {
091        return rootTypes;
092      }
093    
094      public Collection<ResourceType> getAll(Predicate<ResourceType> predicate) {
095        return Collections2.filter(typeByQualifier.values(), predicate);
096      }
097    
098      private static class PropertyKeyPredicate implements Predicate<ResourceType> {
099        private final String propertyKey;
100    
101        public PropertyKeyPredicate(String propertyKey) {
102          this.propertyKey = propertyKey;
103        }
104    
105        public boolean apply(@Nullable ResourceType input) {
106          return input != null && input.hasProperty(propertyKey);
107        }
108      }
109    
110      public Collection<ResourceType> getAllWithPropertyKey(final String propertyKey) {
111        return Collections2.filter(typeByQualifier.values(), new PropertyKeyPredicate(propertyKey));
112      }
113    
114      private static class StringPropertyValuePredicate implements Predicate<ResourceType> {
115        private final String propertyValue;
116        private final String propertyKey;
117    
118        public StringPropertyValuePredicate(String propertyValue, String propertyKey) {
119          this.propertyValue = propertyValue;
120          this.propertyKey = propertyKey;
121        }
122    
123        public boolean apply(@Nullable ResourceType input) {
124          return input != null && Objects.equal(propertyValue, input.getStringProperty(propertyKey));
125        }
126      }
127    
128      public Collection<ResourceType> getAllWithPropertyValue(final String propertyKey, final String propertyValue) {
129        return Collections2.filter(typeByQualifier.values(), new StringPropertyValuePredicate(propertyValue, propertyKey));
130      }
131    
132      private static class BooleanPropertyValuePredicate implements Predicate<ResourceType> {
133        private final String propertyKey;
134        private final boolean propertyValue;
135    
136        public BooleanPropertyValuePredicate(String propertyKey, boolean propertyValue) {
137          this.propertyKey = propertyKey;
138          this.propertyValue = propertyValue;
139        }
140    
141        public boolean apply(@Nullable ResourceType input) {
142          return input != null && input.getBooleanProperty(propertyKey) == propertyValue;
143        }
144      }
145    
146      public Collection<ResourceType> getAllWithPropertyValue(final String propertyKey, final boolean propertyValue) {
147        return Collections2.filter(typeByQualifier.values(), new BooleanPropertyValuePredicate(propertyKey, propertyValue));
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 Lists.transform(getChildrenQualifiers(qualifier), new Function<String, ResourceType>() {
160          public ResourceType apply(String s) {
161            return typeByQualifier.get(s);
162          }
163        });
164      }
165    
166      public List<String> getLeavesQualifiers(String qualifier) {
167        ResourceTypeTree tree = getTree(qualifier);
168        if (tree != null) {
169          return tree.getLeaves();
170        }
171        return Collections.emptyList();
172      }
173    
174      public ResourceTypeTree getTree(String qualifier) {
175        return treeByQualifier.get(qualifier);
176      }
177    
178      public ResourceType getRoot(String qualifier){
179        return getTree(qualifier).getRootType();
180      }
181    
182    }