001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2009 SonarSource SA
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     */
020    package org.sonar.api.database.model;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.apache.commons.lang.builder.EqualsBuilder;
024    import org.apache.commons.lang.builder.HashCodeBuilder;
025    import org.apache.commons.lang.builder.ToStringBuilder;
026    import org.hibernate.annotations.BatchSize;
027    import org.sonar.api.database.BaseIdentifiable;
028    import org.sonar.api.profiles.RulesProfile;
029    import org.sonar.api.resources.ProjectLink;
030    import org.sonar.api.resources.Resource;
031    
032    import javax.persistence.*;
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    /**
037     * Class to map resource with hibernate model
038     */
039    @Entity
040    @Table(name = "projects")
041    public class ResourceModel extends BaseIdentifiable implements Cloneable {
042    
043      public static final String SCOPE_PROJECT = "PRJ";
044      public static final String QUALIFIER_PROJECT_TRUNK = "TRK";
045    
046      public static final int DESCRIPTION_COLUMN_SIZE = 2000;
047      public static final int NAME_COLUMN_SIZE = 256;
048      public static final int KEY_SIZE = 400;
049    
050      @Column(name = "name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE)
051      private String name;
052    
053      @Column(name = "long_name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE)
054      private String longName;
055    
056      @Column(name = "description", updatable = true, nullable = true, length = DESCRIPTION_COLUMN_SIZE)
057      private String description;
058    
059      @Column(name = "enabled", updatable = true, nullable = false)
060      private Boolean enabled = Boolean.TRUE;
061    
062      @Column(name = "scope", updatable = true, nullable = false, length = 3)
063      private String scope;
064    
065      @Column(name = "qualifier", updatable = true, nullable = false, length = 3)
066      private String qualifier;
067    
068      @Column(name = "kee", updatable = false, nullable = false, length = KEY_SIZE)
069      private String key;
070    
071      @Column(name = "language", updatable = true, nullable = true, length = 5)
072      private String languageKey;
073    
074      @Column(name = "root_id", updatable = true, nullable = true)
075      private Integer rootId;
076    
077      @Column(name = "copy_resource_id", updatable = true, nullable = true)
078      private Integer copyResourceId;
079    
080      @OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
081      @BatchSize(size = 8)
082      private List<ProjectLink> projectLinks = new ArrayList<ProjectLink>();
083    
084      @ManyToOne(fetch = FetchType.LAZY)
085      @JoinColumn(name = "profile_id", updatable = true, nullable = true)
086      private RulesProfile rulesProfile;
087    
088      /**
089       * Default constructor
090       */
091      public ResourceModel() {
092      }
093    
094      /**
095       * <p>Creates a resource model</p>
096       *
097       * @param scope the scope the rule will apply on
098       * @param key the rule key. This is the name of the resource, including the path
099       * @param qualifier the resource qualifier
100       * @param rootId the rootId for the resource
101       * @param name the short name of the resource
102       */
103      public ResourceModel(String scope, String key, String qualifier, Integer rootId, String name) {
104        this.scope = scope;
105        this.key = key;
106        this.rootId = rootId;
107        this.name = name;
108        this.qualifier = qualifier;
109      }
110    
111      /**
112       * Only available at project level.
113       */
114      public List<ProjectLink> getProjectLinks() {
115        return projectLinks;
116      }
117    
118      public void setProjectLinks(List<ProjectLink> projectLinks) {
119        this.projectLinks = projectLinks;
120      }
121    
122      /**
123       * @return a project link given its key if exists, null otherwise
124       */
125      public ProjectLink getProjectLink(String key) {
126        for (ProjectLink projectLink : projectLinks) {
127          if (key.equals(projectLink.getKey())) {
128            return projectLink;
129          }
130        }
131        return null;
132      }
133    
134      /**
135       * Only available at project level.
136       */
137      public String getDescription() {
138        return description;
139      }
140    
141      /**
142       * Sets the resource description, truncated to DESCRIPTION_COLUMN_SIZE
143       */
144      public void setDescription(String description) {
145        this.description = StringUtils.abbreviate(description, DESCRIPTION_COLUMN_SIZE);
146      }
147    
148      public String getName() {
149        return name;
150      }
151    
152      /**
153       * Sets the resource name, truncated to NAME_COLUMN_SIZE
154       */
155      public void setName(String name) {
156        this.name = StringUtils.abbreviate(name, NAME_COLUMN_SIZE);
157        if (this.longName==null) {
158          this.longName = this.name;
159        }
160      }
161    
162      public String getLongName() {
163        return longName;
164      }
165    
166      /**
167       * Sets the long name of the resource, truncated to NAME_COLUMN_SIZE
168       */
169      public void setLongName(String s) {
170        if (StringUtils.isBlank(s)) {
171          this.longName = name;
172        } else {
173          this.longName = StringUtils.abbreviate(s, NAME_COLUMN_SIZE);
174        }
175      }
176    
177      public Boolean getEnabled() {
178        return enabled;
179      }
180    
181      public void setEnabled(Boolean enabled) {
182        this.enabled = enabled;
183      }
184    
185      public String getScope() {
186        return scope;
187      }
188    
189      public void setScope(String scope) {
190        this.scope = scope;
191      }
192    
193      public String getKey() {
194        return key;
195      }
196    
197      public String getLanguageKey() {
198        return languageKey;
199      }
200    
201      public void setLanguageKey(String lang) {
202        this.languageKey = lang;
203      }
204    
205      public Integer getCopyResourceId() {
206        return copyResourceId;
207      }
208    
209      public void setCopyResourceId(Integer copyResourceId) {
210        this.copyResourceId = copyResourceId;
211      }
212    
213      /**
214       * @throws IllegalArgumentException if the key is longer than KEY_SIZE
215       */
216      public void setKey(String key) {
217        if (key.length() > KEY_SIZE) {
218          throw new IllegalArgumentException("Resource key is too long, max is " + KEY_SIZE + " characters. Got : " + key);
219        }
220        this.key = key;
221      }
222    
223      public Integer getRootId() {
224        return rootId;
225      }
226    
227      public void setRootId(Integer rootId) {
228        this.rootId = rootId;
229      }
230    
231      public RulesProfile getRulesProfile() {
232        return rulesProfile;
233      }
234    
235      public void setRulesProfile(RulesProfile rulesProfile) {
236        this.rulesProfile = rulesProfile;
237      }
238    
239      public String getQualifier() {
240        return qualifier;
241      }
242    
243      public void setQualifier(String qualifier) {
244        this.qualifier = qualifier;
245      }
246    
247      @Override
248      public boolean equals(Object obj) {
249        if (!(obj instanceof ResourceModel)) {
250          return false;
251        }
252        if (this == obj) {
253          return true;
254        }
255        ResourceModel other = (ResourceModel) obj;
256        return new EqualsBuilder()
257            .append(key, other.key)
258            .append(enabled, other.enabled)
259            .append(rootId, other.rootId)
260            .isEquals();
261      }
262    
263      @Override
264      public int hashCode() {
265        return new HashCodeBuilder(17, 37)
266            .append(key)
267            .append(enabled)
268            .append(rootId)
269            .toHashCode();
270      }
271    
272      @Override
273      public String toString() {
274        return new ToStringBuilder(this)
275            .append("id", getId())
276            .append("key", key)
277            .append("scope", scope)
278            .append("qualifier", qualifier)
279            .append("name", name)
280            .append("longName", longName)
281            .append("lang", languageKey)
282            .append("enabled", enabled)
283            .append("rootId", rootId)
284            .append("copyResourceId", copyResourceId)
285            .toString();
286      }
287    
288      @Override
289      public Object clone() {
290        ResourceModel clone = new ResourceModel(getScope(), getKey(), getQualifier(), getRootId(), getName());
291        clone.setDescription(getDescription());
292        clone.setEnabled(getEnabled());
293        clone.setProjectLinks(getProjectLinks());
294        clone.setRulesProfile(getRulesProfile());
295        clone.setLanguageKey(getLanguageKey());
296        clone.setCopyResourceId(getCopyResourceId());
297        clone.setLongName(getLongName());
298        return clone;
299      }
300    
301      /**
302       * Maps a resource to a resource model and returns the resource
303       */
304      public static ResourceModel build(Resource resource) {
305        ResourceModel model = new ResourceModel();
306        model.setEnabled(Boolean.TRUE);
307        model.setDescription(resource.getDescription());
308        model.setKey(resource.getKey());
309        if (resource.getLanguage() != null) {
310          model.setLanguageKey(resource.getLanguage().getKey());
311        }
312        if (StringUtils.isNotBlank(resource.getName())) {
313          model.setName(resource.getName());
314        } else {
315          model.setName(resource.getKey());
316        }
317        model.setLongName(resource.getLongName());
318        model.setQualifier(resource.getQualifier());
319        model.setScope(resource.getScope());
320        return model;
321      }
322    
323    }