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 org.apache.commons.lang.StringUtils;
023import org.sonar.api.utils.WildcardPattern;
024
025import java.io.File;
026import java.util.List;
027
028/**
029 * A class that represents a Java class. This class can either be a Test class or source class
030 *
031 * @since 1.10
032 */
033public class JavaFile extends Resource<JavaPackage> {
034
035  private String filename;
036  private String longName;
037  private String packageKey;
038  private boolean unitTest;
039  private JavaPackage parent;
040
041  /**
042   * Creates a JavaFile that is not a class of test based on package and file names
043   */
044  public JavaFile(String packageName, String className) {
045    this(packageName, className, false);
046  }
047
048  /**
049   * Creates a JavaFile that can be of any type based on package and file names
050   *
051   * @param unitTest whether it is a unit test file or a source file
052   */
053  public JavaFile(String packageKey, String className, boolean unitTest) {
054    if (className == null) {
055      throw new IllegalArgumentException("Java filename can not be null");
056    }
057    this.filename = StringUtils.trim(className);
058    String key;
059    if (StringUtils.isBlank(packageKey)) {
060      this.packageKey = JavaPackage.DEFAULT_PACKAGE_NAME;
061      this.longName = this.filename;
062      key = new StringBuilder().append(this.packageKey).append(".").append(this.filename).toString();
063    } else {
064      this.packageKey = packageKey.trim();
065      key = new StringBuilder().append(this.packageKey).append(".").append(this.filename).toString();
066      this.longName = key;
067    }
068    setKey(key);
069    this.unitTest = unitTest;
070  }
071
072  /**
073   * Creates a source file from its key
074   */
075  public JavaFile(String key) {
076    this(key, false);
077  }
078
079  /**
080   * Creates any JavaFile from its key
081   *
082   * @param unitTest whether it is a unit test file or a source file
083   */
084  public JavaFile(String key, boolean unitTest) {
085    if (key == null) {
086      throw new IllegalArgumentException("Java filename can not be null");
087    }
088    String realKey = StringUtils.trim(key);
089    this.unitTest = unitTest;
090
091    if (realKey.contains(".")) {
092      this.filename = StringUtils.substringAfterLast(realKey, ".");
093      this.packageKey = StringUtils.substringBeforeLast(realKey, ".");
094      this.longName = realKey;
095
096    } else {
097      this.filename = realKey;
098      this.longName = realKey;
099      this.packageKey = JavaPackage.DEFAULT_PACKAGE_NAME;
100      realKey = new StringBuilder().append(JavaPackage.DEFAULT_PACKAGE_NAME).append(".").append(realKey).toString();
101    }
102    setKey(realKey);
103  }
104
105  /**
106   * {@inheritDoc}
107   */
108  @Override
109  public JavaPackage getParent() {
110    if (parent == null) {
111      parent = new JavaPackage(packageKey);
112    }
113    return parent;
114
115  }
116
117  /**
118   * @return null
119   */
120  @Override
121  public String getDescription() {
122    return null;
123  }
124
125  /**
126   * @return Java
127   */
128  @Override
129  public Language getLanguage() {
130    return Java.INSTANCE;
131  }
132
133  /**
134   * {@inheritDoc}
135   */
136  @Override
137  public String getName() {
138    return filename;
139  }
140
141  /**
142   * {@inheritDoc}
143   */
144  @Override
145  public String getLongName() {
146    return longName;
147  }
148
149  /**
150   * @return SCOPE_ENTITY
151   */
152  @Override
153  public String getScope() {
154    return Scopes.FILE;
155  }
156
157  /**
158   * @return QUALIFIER_UNIT_TEST_CLASS or QUALIFIER_CLASS depending whether it is a unit test class
159   */
160  @Override
161  public String getQualifier() {
162    return unitTest ? Qualifiers.UNIT_TEST_FILE : Qualifiers.CLASS;
163  }
164
165  /**
166   * @return whether the JavaFile is a unit test class or not
167   */
168  public boolean isUnitTest() {
169    return unitTest;
170  }
171
172  /**
173   * {@inheritDoc}
174   */
175  @Override
176  public boolean matchFilePattern(String antPattern) {
177    String fileKey = getKey();
178    if (!fileKey.endsWith(".java")) {
179      fileKey += ".java";
180    }
181    if (StringUtils.substringAfterLast(antPattern, "/").indexOf(".") < 0) {
182      antPattern += ".*";
183    }
184    WildcardPattern matcher = WildcardPattern.create(antPattern, ".");
185    return matcher.match(fileKey);
186  }
187
188  public static JavaFile fromRelativePath(String relativePath, boolean unitTest) {
189    if (relativePath != null) {
190      String pacname = null;
191      String classname = relativePath;
192
193      if (relativePath.indexOf('/') >= 0) {
194        pacname = StringUtils.substringBeforeLast(relativePath, "/");
195        pacname = StringUtils.replace(pacname, "/", ".");
196        classname = StringUtils.substringAfterLast(relativePath, "/");
197      }
198      classname = StringUtils.substringBeforeLast(classname, ".");
199      return new JavaFile(pacname, classname, unitTest);
200    }
201    return null;
202  }
203
204  /**
205   * Creates a JavaFile from a file in the source directories
206   *
207   * @return the JavaFile created if exists, null otherwise
208   */
209  public static JavaFile fromIOFile(File file, List<File> sourceDirs, boolean unitTest) {
210    if (file == null || !StringUtils.endsWithIgnoreCase(file.getName(), ".java")) {
211      return null;
212    }
213    String relativePath = DefaultProjectFileSystem.getRelativePath(file, sourceDirs);
214    return fromRelativePath(relativePath, unitTest);
215  }
216
217  /**
218   * Shortcut to fromIOFile with an abolute path
219   */
220  public static JavaFile fromAbsolutePath(String path, List<File> sourceDirs, boolean unitTest) {
221    if (path == null) {
222      return null;
223    }
224    return fromIOFile(new File(path), sourceDirs, unitTest);
225  }
226
227  @Override
228  public String toString() {
229    return getKey();
230  }
231
232}