/*
* Created on 7 mai 2005
*
* Copyright (c) 2006, PMD for Eclipse Development Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed in part by support from
* the Defense Advanced Research Project Agency (DARPA)"
* * Neither the name of "PMD for Eclipse Development Team" nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.sourceforge.pmd.eclipse.ui.model;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import net.sourceforge.pmd.eclipse.ui.nls.StringKeys;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
/**
* AbstractPMDRecord for Projects creates Packages when instantiated
*
* @author SebastianRaffel ( 16.05.2005 ), Philippe Herlin, Sven Jacob
*
*/
public class ProjectRecord extends AbstractPMDRecord {
private final IProject project;
private final RootRecord parent;
private AbstractPMDRecord[] children;
private boolean isJavaProject = false;
/**
* Constructor
*
* @param proj, the Project
* @param record, the RootRecord
*/
public ProjectRecord(IProject project, RootRecord record) {
super();
if (project == null) {
throw new IllegalArgumentException("project cannot be null");
}
if (record == null) {
throw new IllegalArgumentException("record cannot be null");
}
this.project = project;
this.parent = record;
try {
isJavaProject = project.hasNature(JavaCore.NATURE_ID);
}
catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (project.isAccessible()) {
children = createChildren();
} else {
children = EMPTY_RECORDS;
}
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getParent()
*/
@Override
public AbstractPMDRecord getParent() {
return parent;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getChildren()
*/
@Override
public AbstractPMDRecord[] getChildren() {
return children; // NOPMD by Herlin on 09/10/06 00:43
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getResource()
*/
@Override
public IResource getResource() {
return project;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#createChildren()
*/
@Override
protected final AbstractPMDRecord[] createChildren() {
final Set<AbstractPMDRecord> packages = new HashSet<AbstractPMDRecord>();
try {
// search for Packages
project.accept(new IResourceVisitor() {
public boolean visit(IResource resource) throws CoreException {
boolean visitChildren;
switch (resource.getType()) {
case IResource.FOLDER:
visitChildren = (ProjectRecord.this.isJavaProject) ? visitAsPackages(resource) : visitAsFolders(resource);
break;
case IResource.PROJECT:
visitChildren = true;
break;
default:
visitChildren = false;
}
return visitChildren;
}
private Boolean visitAsPackages(IResource resource) {
IJavaElement javaMember = JavaCore.create(resource);
if(javaMember == null) {
return true;
}
else {
if (javaMember instanceof IPackageFragmentRoot) {
// if the Element is the Root of all Packages
// get all packages from it and add them to the
// list
// (e.g. for "org.eclipse.core.resources" and
// "org.eclipse.core" the root is
// "org.eclipse.core")
packages.addAll(createPackagesFromFragmentRoot((IPackageFragmentRoot) javaMember));
} else if (javaMember instanceof IPackageFragment
&& javaMember.getParent() instanceof IPackageFragmentRoot) {
// if the Element is a Package get its Root and
// do the same as above
final IPackageFragment fragment = (IPackageFragment) javaMember;
packages.addAll(createPackagesFromFragmentRoot((IPackageFragmentRoot) fragment.getParent()));
}
return false;
}
}
private Boolean visitAsFolders(IResource resource) {
IFolder folder = (IFolder) resource;
packages.addAll(createPackagesFromFolderRoot(folder));
return false;
}
});
} catch (CoreException ce) {
PMDPlugin.getDefault().logError(StringKeys.ERROR_CORE_EXCEPTION + this.toString(), ce);
}
// return the List as an Array of Packages
return packages.toArray(new AbstractPMDRecord[packages.size()]);
}
/**
* Search for the Packages to a given FragmentRoot (Package-Root) and create
* PackageRecords for them
*
* @param root
* @return
*/
protected final Set<PackageRecord> createPackagesFromFragmentRoot(IPackageFragmentRoot root) {
final Set<PackageRecord> packages = new HashSet<PackageRecord>();
IJavaElement[] fragments = null;
try {
// search for all children
fragments = root.getChildren();
for (IJavaElement fragment : fragments) {
if (fragment instanceof IPackageFragment) {
// create a PackageRecord for the Fragment
// and add it to the list
packages.add(new PackageRecord((IPackageFragment) fragment, this)); // NOPMD
// by
// Herlin
// on
// 09/10/06
// 00:47
}
}
} catch (JavaModelException jme) {
PMDPlugin.getDefault().logError(StringKeys.ERROR_JAVAMODEL_EXCEPTION + this.toString(), jme);
}
return packages;
}
protected final Set<FolderRecord> createPackagesFromFolderRoot(IFolder rootFolder) {
final Set<FolderRecord> folder = new HashSet<FolderRecord>();
try {
for (IResource resource : rootFolder.members()) {
if (resource instanceof IFolder) {
folder.add(new FolderRecord((IFolder) resource, this)); // NOPMD
}
}
}
catch (CoreException e) {
e.printStackTrace();
}
return folder;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getName()
*/
@Override
public String getName() {
return project.getName();
}
/**
* Checks, if the underlying Project is open
*
* @return true, if the Project is open, false otherwise
*/
public boolean isProjectOpen() {
return project.isOpen();
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getResourceType()
*/
@Override
public int getResourceType() {
return TYPE_PROJECT;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#addResource(org.eclipse.core.resources.IResource)
*/
@Override
public AbstractPMDRecord addResource(IResource resource) {
AbstractPMDRecord added = null;
// we only care about Files
if (resource instanceof IFile) {
if(isJavaProject) {
added = addToJavaProject(resource);
}
else {
added = addToOtherProject(resource);
}
}
return added;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#removeResource(org.eclipse.core.resources.IResource)
*/
@Override
public AbstractPMDRecord removeResource(IResource resource) {
AbstractPMDRecord removed = null;
// we only care about Files
if (resource instanceof IFile) {
if(isJavaProject) {
removed = removeFromJavaProject(resource);
}
else {
removed = removeFromOtherProject(resource);
}
}
return removed;
}
private AbstractPMDRecord removeFromJavaProject(IResource resource) {
AbstractPMDRecord removedResource = null;
IPackageFragment fragment;
final IJavaElement element = JavaCore.create(resource.getParent());
if (element instanceof IPackageFragment) {
fragment = (IPackageFragment) element;
} else {
fragment = ((IPackageFragmentRoot) element).getPackageFragment("");
}
PackageRecord packageRec;
// like above we compare Fragments to find the right Package
for (int k = 0; k < children.length && removedResource == null; k++) {
packageRec = (PackageRecord) children[k];
if (packageRec.getFragment().equals(fragment)) {
// if we found it, we remove the File
final AbstractPMDRecord fileRec = packageRec.removeResource(resource);
if (packageRec.getChildren().length == 0) {
// ... and if the Package is empty too
// we also remove it
final List<AbstractPMDRecord> packages = getChildrenAsList();
packages.remove(packageRec);
children = new AbstractPMDRecord[packages.size()]; // NOPMD
// by
// Herlin
// on
// 09/10/06
// 00:54
packages.toArray(children);
}
removedResource = fileRec;
}
}
return removedResource;
}
private AbstractPMDRecord removeFromOtherProject(IResource resource) {
AbstractPMDRecord removedResource = null;
IFolder folder = (IFolder) resource.getParent();
FolderRecord folderRec;
// like above we compare Fragments to find the right Package
for (int k = 0; k < children.length && removedResource == null; k++) {
folderRec = (FolderRecord) children[k];
if (folderRec.getFolder().equals(folder)) {
// if we found it, we remove the File
final AbstractPMDRecord fileRec = folderRec.removeResource(resource);
if (folderRec.getChildren().length == 0) {
// ... and if the Package is empty too
// we also remove it
final List<AbstractPMDRecord> packages = getChildrenAsList();
packages.remove(folderRec);
children = new AbstractPMDRecord[packages.size()]; // NOPMD
// by
// Herlin
// on
// 09/10/06
// 00:54
packages.toArray(children);
}
removedResource = fileRec;
}
}
return removedResource;
}
private AbstractPMDRecord addToJavaProject(IResource resource) {
AbstractPMDRecord addedResource = null;
IJavaElement javaMember = JavaCore.create(resource.getParent());
if (javaMember instanceof IPackageFragmentRoot) {
javaMember = ((IPackageFragmentRoot) javaMember).getPackageFragment("");
}
final IPackageFragment fragment = (IPackageFragment) javaMember;
// we search int the children Packages for the File's Package
// by comparing their Fragments
for (int k = 0; k < children.length && addedResource == null; k++) {
final PackageRecord packageRec = (PackageRecord) children[k];
if (packageRec.getFragment().equals(fragment)) {
// if the Package exists
// we delegate to its addResource-function
addedResource = packageRec.addResource(resource);
}
}
// ... else we create a new Record for the new Package
if (addedResource == null) {
final PackageRecord packageRec = new PackageRecord(fragment, this);
final List<AbstractPMDRecord> packages = getChildrenAsList();
packages.add(packageRec);
// ... and we add a new FileRecord to it
children = new AbstractPMDRecord[packages.size()];
packages.toArray(children);
addedResource = packageRec.addResource(resource);
}
return addedResource;
}
private AbstractPMDRecord addToOtherProject(IResource resource) {
AbstractPMDRecord addedResource = null;
IFolder folder = (IFolder) resource.getParent();
// we search int the children Packages for the File's Package
// by comparing their Fragments
for (int k = 0; k < children.length && addedResource == null; k++) {
final FolderRecord folderRec = (FolderRecord) children[k];
if (folderRec.getFolder().equals(folder)) {
// if the Package exists
// we delegate to its addResource-function
addedResource = folderRec.addResource(resource);
}
}
// ... else we create a new Record for the new Package
if (addedResource == null) {
final FolderRecord packageRec = new FolderRecord(folder, this);
final List<AbstractPMDRecord> packages = getChildrenAsList();
packages.add(packageRec);
// ... and we add a new FileRecord to it
children = new AbstractPMDRecord[packages.size()];
packages.toArray(children);
addedResource = packageRec.addResource(resource);
}
return addedResource;
}
/**
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getNumberOfViolationsToPriority(int)
*/
@Override
public int getNumberOfViolationsToPriority(int prio, boolean invertMarkerAndFileRecords) {
int number = 0;
for (AbstractPMDRecord element : children) {
number += element.getNumberOfViolationsToPriority(prio, invertMarkerAndFileRecords);
}
return number;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getLOC()
*/
@Override
public int getLOC() {
int number = 0;
for (AbstractPMDRecord element : children) {
number += element.getLOC();
}
return number;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.pmd.eclipse.ui.model.AbstractPMDRecord#getNumberOfMethods()
*/
@Override
public int getNumberOfMethods() {
int number = 0;
for (AbstractPMDRecord element : children) {
number += element.getNumberOfMethods();
}
return number;
}
}