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