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