001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info 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 java.util.HashMap;
024import java.util.Map;
025import javax.annotation.Nullable;
026import javax.annotation.concurrent.Immutable;
027
028import static java.util.Objects.requireNonNull;
029import static org.apache.commons.lang.StringUtils.isEmpty;
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 = new HashMap<>(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    requireNonNull(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    requireNonNull(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    requireNonNull(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    requireNonNull(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 String qualifier;
160    private String iconPath;
161    private boolean hasSourceCode = false;
162    private final Map<String, String> properties = new HashMap<>();
163
164    /**
165     * Creates a new {@link Builder}
166     */
167    public Builder(String qualifier) {
168      this.qualifier = qualifier;
169    }
170
171    /**
172     * Relative path of the icon used to represent the resource type.
173     *
174     * @param iconPath path to icon, relative to context of web-application (e.g. "/images/q/DIR.png")
175     */
176    public Builder setIconPath(@Nullable String iconPath) {
177      this.iconPath = iconPath;
178      return this;
179    }
180
181    /**
182     * @deprecated since 3.0. Use {@link #setProperty(String, String)} with "supportsMeasureFilters" set to "true".
183     */
184    @Deprecated
185    public Builder availableForFilters() {
186      return this;
187    }
188
189    /**
190     * Tells that the resources of this type will have source code.
191     */
192    public Builder hasSourceCode() {
193      this.hasSourceCode = true;
194      return this;
195    }
196
197    /**
198     * Sets a property on the resource type. See the description of {@link ResourceType} class for more information.
199     *
200     * @since 3.0
201     */
202    public Builder setProperty(String key, String value) {
203      requireNonNull(key);
204      requireNonNull(value);
205      properties.put(key, value);
206      return this;
207    }
208
209    /**
210     * @since 3.2
211     */
212    public Builder setProperty(String key, boolean value) {
213      return setProperty(key, String.valueOf(value));
214    }
215
216    /**
217     * Creates an instance of {@link ResourceType} based on all information given to the builder.
218     */
219    public ResourceType build() {
220      if (isEmpty(iconPath)) {
221        iconPath = "/images/q/" + qualifier + ".png";
222      }
223      return new ResourceType(this);
224    }
225  }
226}