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 java.util.ArrayList;
023import java.util.Date;
024import java.util.List;
025import javax.annotation.CheckForNull;
026import javax.annotation.Nullable;
027import org.apache.commons.lang.StringUtils;
028import org.apache.commons.lang.builder.ToStringBuilder;
029import org.sonar.api.CoreProperties;
030import org.sonar.api.batch.fs.InputModule;
031import org.sonar.api.component.Component;
032import org.sonar.api.config.Settings;
033
034/**
035 * @since 1.10
036 * @deprecated since 5.6 replaced by {@link InputModule}.
037 */
038@Deprecated
039public class Project extends Resource implements Component {
040
041  /**
042   * Internal use
043   */
044  public static final Language NONE_LANGUAGE = new AbstractLanguage("none", "None") {
045    @Override
046    public String[] getFileSuffixes() {
047      return new String[0];
048    }
049  };
050
051  static final String MAVEN_KEY_FORMAT = "%s:%s";
052  private static final String BRANCH_KEY_FORMAT = "%s:%s";
053
054  public static final String SCOPE = Scopes.PROJECT;
055
056  /**
057   * Enumerates the type of possible analysis
058   * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report.
059   */
060  @Deprecated
061  public enum AnalysisType {
062    STATIC, DYNAMIC, REUSE_REPORTS;
063
064    /**
065     * @param includeReuseReportMode whether to count report reuse as dynamic or not
066     * @return whether this a dynamic analysis
067     */
068    public boolean isDynamic(boolean includeReuseReportMode) {
069      return equals(Project.AnalysisType.DYNAMIC) ||
070        (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode);
071    }
072  }
073
074  private String branch;
075  private String name;
076  private String description;
077  private Language language;
078  private Date analysisDate;
079  private AnalysisType analysisType;
080  private String analysisVersion;
081  private Settings settings;
082
083  // For internal use
084  private java.io.File baseDir;
085
086  // modules tree
087  private Project parent;
088  private List<Project> modules = new ArrayList<>();
089
090  public Project(String key) {
091    setKey(key);
092    setEffectiveKey(key);
093  }
094
095  public Project(String key, String branch, String name) {
096    if (StringUtils.isNotBlank(branch)) {
097      setKey(String.format(BRANCH_KEY_FORMAT, key, branch));
098      this.name = String.format("%s %s", name, branch);
099    } else {
100      setKey(key);
101      this.name = name;
102    }
103    setEffectiveKey(getKey());
104    this.branch = branch;
105  }
106
107  public String getBranch() {
108    return branch;
109  }
110
111  /**
112   * For internal use only.
113   */
114  public Project setBranch(String branch) {
115    this.branch = branch;
116    return this;
117  }
118
119  @Override
120  public String getName() {
121    return name;
122  }
123
124  @Override
125  public String getLongName() {
126    return name;
127  }
128
129  @Override
130  public String getDescription() {
131    return description;
132  }
133
134  /**
135   * For internal use only.
136   */
137  public Project setName(String name) {
138    this.name = name;
139    return this;
140  }
141
142  /**
143   * For internal use only.
144   */
145  public Project setDescription(String description) {
146    this.description = description;
147    return this;
148  }
149
150  /**
151   * @return whether the current project is root project
152   */
153  public boolean isRoot() {
154    return getParent() == null;
155  }
156
157  public Project getRoot() {
158    return parent == null ? this : parent.getRoot();
159  }
160
161  /**
162   * @return whether the current project is a module
163   */
164  public boolean isModule() {
165    return !isRoot();
166  }
167
168  /**
169   * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report.
170   */
171  @Deprecated
172  public AnalysisType getAnalysisType() {
173    return analysisType;
174  }
175
176  /**
177   * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report.
178   */
179  @Deprecated
180  public Project setAnalysisType(AnalysisType at) {
181    this.analysisType = at;
182    return this;
183  }
184
185  /**
186   * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision.
187   *
188   * @since 2.0
189   * @deprecated in 3.6. The analysis is now always the latest one (past analysis must be done in a chronological order). See http://jira.sonarsource.com/browse/SONAR-4334
190   */
191  @Deprecated
192  public boolean isLatestAnalysis() {
193    return true;
194  }
195
196  /**
197   * For internal use only.
198   *
199   * @deprecated in 3.6. It's not possible to analyze a project before the latest known quality snapshot.
200   * See http://jira.sonarsource.com/browse/SONAR-4334
201   */
202  @Deprecated
203  public Project setLatestAnalysis(boolean b) {
204    if (!b) {
205      throw new UnsupportedOperationException("The analysis is always the latest one. " +
206        "Past analysis must be done in a chronological order.");
207    }
208    return this;
209  }
210
211  /**
212   * @return the project language when there is only one language
213   * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()}
214   */
215  @Deprecated
216  @Override
217  public Language getLanguage() {
218    return language;
219  }
220
221  /**
222   * Internal use
223   */
224  public Project setLanguage(Language language) {
225    this.language = language;
226    return this;
227  }
228
229  /**
230   * @return the language key or empty if no language is specified
231   * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()}
232   */
233  @Deprecated
234  public String getLanguageKey() {
235    if (settings == null) {
236      throw new IllegalStateException("Project is not yet initialized");
237    }
238    return StringUtils.defaultIfEmpty(settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY), "");
239  }
240
241  /**
242   * Internal use
243   */
244  public Project setSettings(Settings settings) {
245    this.settings = settings;
246    return this;
247  }
248
249  /**
250   * Internal use for backward compatibility. Settings should be retrieved as an IoC dependency.
251   * @deprecated since 5.0
252   */
253  @Deprecated
254  public Settings getSettings() {
255    return settings;
256  }
257
258  /**
259   * For internal use only.
260   */
261  public Project setAnalysisDate(Date analysisDate) {
262    this.analysisDate = analysisDate;
263    return this;
264  }
265
266  /**
267   * For internal use only.
268   */
269  public Project setAnalysisVersion(String analysisVersion) {
270    this.analysisVersion = analysisVersion;
271    return this;
272  }
273
274  /**
275   * @return the scope of the current object
276   */
277  @Override
278  public String getScope() {
279    return Scopes.PROJECT;
280  }
281
282  /**
283   * @return the qualifier of the current object
284   */
285  @Override
286  public String getQualifier() {
287    return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE;
288  }
289
290  @Override
291  public boolean matchFilePattern(String antPattern) {
292    return false;
293  }
294
295  @CheckForNull
296  @Override
297  public Project getParent() {
298    return parent;
299  }
300
301  /**
302   * For internal use only.
303   */
304  public Project setParent(Project parent) {
305    this.parent = parent;
306    if (parent != null) {
307      parent.modules.add(this);
308    }
309    return this;
310  }
311
312  /**
313   * For internal use only.
314   */
315  public void removeFromParent() {
316    if (parent != null) {
317      parent.modules.remove(this);
318    }
319  }
320
321  /**
322   * @return the list of modules
323   */
324  public List<Project> getModules() {
325    return modules;
326  }
327
328  /**
329   * @return the current version of the project
330   */
331  public String getAnalysisVersion() {
332    return analysisVersion;
333  }
334
335  /**
336   * @return the analysis date, i.e. the date that will be used to store the snapshot
337   */
338  public Date getAnalysisDate() {
339    return analysisDate;
340  }
341
342  public static Project createFromMavenIds(String groupId, String artifactId) {
343    return createFromMavenIds(groupId, artifactId, null);
344  }
345
346  public static Project createFromMavenIds(String groupId, String artifactId, @Nullable String branch) {
347    return new Project(String.format(MAVEN_KEY_FORMAT, groupId, artifactId), branch, "");
348  }
349
350  @Override
351  public String toString() {
352    return new ToStringBuilder(this)
353      .append("id", getId())
354      .append("key", getKey())
355      .append("qualifier", getQualifier())
356      .toString();
357  }
358
359  @Override
360  public String key() {
361    return getKey();
362  }
363
364  @Override
365  public String name() {
366    return getName();
367  }
368
369  @Override
370  public String path() {
371    return getPath();
372  }
373
374  @Override
375  public String longName() {
376    return getLongName();
377  }
378
379  @Override
380  public String qualifier() {
381    return getQualifier();
382  }
383
384  // For internal use
385  public void setBaseDir(java.io.File baseDir) {
386    this.baseDir = baseDir;
387  }
388
389  java.io.File getBaseDir() {
390    return baseDir;
391  }
392}