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