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.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.
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 * 
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  private final String qualifier;
057  private final String iconPath;
058  private final boolean hasSourceCode;
059  private Map<String, String> properties;
060
061  private ResourceType(Builder builder) {
062    this.qualifier = builder.qualifier;
063    this.iconPath = builder.iconPath;
064    this.hasSourceCode = builder.hasSourceCode;
065    this.properties = Maps.newHashMap(builder.properties);
066  }
067
068  /**
069   * Qualifier is the unique key.
070   *
071   * @return the qualifier
072   */
073  public String getQualifier() {
074    return qualifier;
075  }
076
077  /**
078   * Returns the relative path of the icon used to represent the resource type
079   *
080   * @return the relative path.
081   */
082  public String getIconPath() {
083    return iconPath;
084  }
085
086  /**
087   * Tells whether resources of this type has source code or not.
088   *
089   * @return true if the type has source code
090   */
091  public boolean hasSourceCode() {
092    return hasSourceCode;
093  }
094
095  public boolean hasProperty(String key) {
096    Preconditions.checkNotNull(key);
097    return properties.containsKey(key);
098  }
099
100  /**
101   * Returns the value of the property for this resource type.
102   *
103   * @return the String value of the property, or NULL if the property hasn't been set.
104   * @since 3.0
105   */
106  public String getStringProperty(String key) {
107    Preconditions.checkNotNull(key);
108    return properties.get(key);
109  }
110
111  /**
112   * Returns the value of the property for this resource type.
113   *
114   * @return the Boolean value of the property. If the property hasn't been set, False is returned.
115   * @since 3.0
116   */
117  public boolean getBooleanProperty(String key) {
118    Preconditions.checkNotNull(key);
119    String value = properties.get(key);
120    return value != null && Boolean.parseBoolean(value);
121  }
122
123  @Override
124  public boolean equals(Object o) {
125    if (this == o) {
126      return true;
127    }
128    if (o == null || getClass() != o.getClass()) {
129      return false;
130    }
131
132    ResourceType that = (ResourceType) o;
133    return qualifier.equals(that.qualifier);
134  }
135
136  @Override
137  public int hashCode() {
138    return qualifier.hashCode();
139  }
140
141  @Override
142  public String toString() {
143    return qualifier;
144  }
145
146  /**
147   * Creates a new {@link Builder}
148   */
149  public static Builder builder(String qualifier) {
150    Preconditions.checkNotNull(qualifier);
151    Preconditions.checkArgument(qualifier.length() <= 10, "Qualifier is limited to 10 characters");
152    return new Builder(qualifier);
153  }
154
155  /**
156   * Builder used to create {@link ResourceType} objects.
157   */
158  public static class Builder {
159    private static final String SUPPORTS_MEASURE_FILTERS = "supportsMeasureFilters";
160    private String qualifier;
161    private String iconPath;
162    private boolean hasSourceCode = false;
163    private final Map<String, String> properties = Maps.newHashMap();
164
165    /**
166     * Creates a new {@link Builder}
167     */
168    public Builder(String qualifier) {
169      this.qualifier = qualifier;
170    }
171
172    /**
173     * Relative path of the icon used to represent the resource type.
174     *
175     * @param iconPath path to icon, relative to context of web-application (e.g. "/images/q/DIR.png")
176     */
177    public Builder setIconPath(@Nullable String iconPath) {
178      this.iconPath = iconPath;
179      return this;
180    }
181
182    /**
183     * @deprecated since 3.0. Use {@link #setProperty(String, String)} with "supportsMeasureFilters" set to "true".
184     */
185    @Deprecated
186    public Builder availableForFilters() {
187      setProperty(SUPPORTS_MEASURE_FILTERS, "true");
188      return this;
189    }
190
191    /**
192     * Tells that the resources of this type will have source code.
193     */
194    public Builder hasSourceCode() {
195      this.hasSourceCode = true;
196      return this;
197    }
198
199    /**
200     * Sets a property on the resource type. See the description of {@link ResourceType} class for more information.
201     *
202     * @since 3.0
203     */
204    public Builder setProperty(String key, String value) {
205      Preconditions.checkNotNull(key);
206      Preconditions.checkNotNull(value);
207      properties.put(key, value);
208
209      // for backward-compatibility since version 3.4
210      if ("availableForFilters".equals(key)) {
211        properties.put(SUPPORTS_MEASURE_FILTERS, value);
212      }
213      return this;
214    }
215
216    /**
217     * @since 3.2
218     */
219    public Builder setProperty(String key, boolean value) {
220      return setProperty(key, String.valueOf(value));
221    }
222
223    /**
224     * Creates an instance of {@link ResourceType} based on all information given to the builder.
225     */
226    public ResourceType build() {
227      if (Strings.isNullOrEmpty(iconPath)) {
228        iconPath = "/images/q/" + qualifier + ".png";
229      }
230      return new ResourceType(this);
231    }
232  }
233}