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 */
020package org.sonar.api.resources;
021
022import com.google.common.base.Preconditions;
023import com.google.common.base.Strings;
024import com.google.common.collect.Maps;
025
026import javax.annotation.Nullable;
027import javax.annotation.concurrent.Immutable;
028
029import java.util.Map;
030
031/**
032 * <p>Experimental extension to declare types of resources.</p>
033 * <p>
034 * Since 3.0, ResourceType object can declare properties that give information about the capabilities of the
035 * resource type. Those properties may be used, of instance, to adapt the Web UI according to the type of
036 * the resource being displayed.
037 * <br>
038 * Currently, the following properties can be defined:
039 * </p>
040 * <ul>
041 * <li>"deletable": if set to "true", then this resource can be deleted/purged.</li>
042 * <li>"supportsMeasureFilters": if set to "true", then this resource can be displayed in measure filters</li>
043 * <li>"modifiable_history": if set to "true", then the history of this resource may be modified (deletion of snapshots, modification of events, ...)</li>
044 * <li>"updatable_key" (since 3.2): if set to "true", then it is possible to update the key of this resource</li>
045 * <li>"supportsGlobalDashboards" (since 3.2): if true, this resource can be displayed in global dashboards</li>
046 * <li>"hasRolePolicy" : if true, roles configuration is available in sidebar</li>
047 * <li>"comparable" (since 3.4) : if true, the resource can be compared to other resources</li>
048 * <li>"configurable" (since 3.6) : if true, the settings page can be displayed on the resource</li>
049 * </ul>
050 *
051 * @since 2.14
052 */
053@Immutable
054public class ResourceType {
055
056  /**
057   * Builder used to create {@link ResourceType} objects.
058   */
059  public static class Builder {
060    private static final String SUPPORTS_MEASURE_FILTERS = "supportsMeasureFilters";
061    private String qualifier;
062    private String iconPath;
063    private boolean hasSourceCode = false;
064    private final Map<String, String> properties = Maps.newHashMap();
065
066    /**
067     * Creates a new {@link Builder}
068     *
069     * @param qualifier
070     */
071    public Builder(String qualifier) {
072      this.qualifier = qualifier;
073    }
074
075    /**
076     * Relative path of the icon used to represent the resource type.
077     *
078     * @param iconPath path to icon, relative to context of web-application (e.g. "/images/q/DIR.png")
079     */
080    public Builder setIconPath(@Nullable String iconPath) {
081      this.iconPath = iconPath;
082      return this;
083    }
084
085    /**
086     * @deprecated since 3.0. Use {@link #setProperty(String, String)} with "supportsMeasureFilters" set to "true".
087     */
088    @Deprecated
089    public Builder availableForFilters() {
090      setProperty(SUPPORTS_MEASURE_FILTERS, "true");
091      return this;
092    }
093
094    /**
095     * Tells that the resources of this type will have source code.
096     */
097    public Builder hasSourceCode() {
098      this.hasSourceCode = true;
099      return this;
100    }
101
102    /**
103     * Sets a property on the resource type. See the description of {@link ResourceType} class for more information.
104     *
105     * @since 3.0
106     */
107    public Builder setProperty(String key, String value) {
108      Preconditions.checkNotNull(key);
109      Preconditions.checkNotNull(value);
110      properties.put(key, value);
111
112      // for backward-compatibility since version 3.4
113      if ("availableForFilters".equals(key)) {
114        properties.put(SUPPORTS_MEASURE_FILTERS, value);
115      }
116      return this;
117    }
118
119    /**
120     * @since 3.2
121     */
122    public Builder setProperty(String key, boolean value) {
123      return setProperty(key, String.valueOf(value));
124    }
125
126    /**
127     * Creates an instance of {@link ResourceType} based on all information given to the builder.
128     */
129    public ResourceType build() {
130      if (Strings.isNullOrEmpty(iconPath)) {
131        iconPath = "/images/q/" + qualifier + ".png";
132      }
133      return new ResourceType(this);
134    }
135  }
136
137  /**
138   * Creates a new {@link Builder}
139   *
140   * @param qualifier
141   */
142  public static Builder builder(String qualifier) {
143    Preconditions.checkNotNull(qualifier);
144    Preconditions.checkArgument(qualifier.length() <= 10, "Qualifier is limited to 10 characters");
145    return new Builder(qualifier);
146  }
147
148  private final String qualifier;
149  private final String iconPath;
150  private final boolean hasSourceCode;
151  private Map<String, String> properties;
152
153  private ResourceType(Builder builder) {
154    this.qualifier = builder.qualifier;
155    this.iconPath = builder.iconPath;
156    this.hasSourceCode = builder.hasSourceCode;
157    this.properties = Maps.newHashMap(builder.properties);
158  }
159
160  /**
161   * Qualifier is the unique key.
162   *
163   * @return the qualifier
164   */
165  public String getQualifier() {
166    return qualifier;
167  }
168
169  /**
170   * Returns the relative path of the icon used to represent the resource type
171   *
172   * @return the relative path.
173   */
174  public String getIconPath() {
175    return iconPath;
176  }
177
178  /**
179   * Tells whether resources of this type has source code or not.
180   *
181   * @return true if the type has source code
182   */
183  public boolean hasSourceCode() {
184    return hasSourceCode;
185  }
186
187  public boolean hasProperty(String key) {
188    Preconditions.checkNotNull(key);
189    return properties.containsKey(key);
190  }
191
192  /**
193   * Returns the value of the property for this resource type.
194   *
195   * @return the String value of the property, or NULL if the property hasn't been set.
196   * @since 3.0
197   */
198  public String getStringProperty(String key) {
199    Preconditions.checkNotNull(key);
200    return properties.get(key);
201  }
202
203  /**
204   * Returns the value of the property for this resource type.
205   *
206   * @return the Boolean value of the property. If the property hasn't been set, False is returned.
207   * @since 3.0
208   */
209  public boolean getBooleanProperty(String key) {
210    Preconditions.checkNotNull(key);
211    String value = properties.get(key);
212    return value != null && Boolean.parseBoolean(value);
213  }
214
215  @Override
216  public boolean equals(Object o) {
217    if (this == o) {
218      return true;
219    }
220    if (o == null || getClass() != o.getClass()) {
221      return false;
222    }
223
224    ResourceType that = (ResourceType) o;
225    return qualifier.equals(that.qualifier);
226  }
227
228  @Override
229  public int hashCode() {
230    return qualifier.hashCode();
231  }
232
233  @Override
234  public String toString() {
235    return qualifier;
236  }
237}