/* * 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.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; /** * Abstract class containing the "Framework" of the PMD-Model Contains Method to * check for Resources and Markers and abstract Methods, that need to bee * implemented in classes to construct the model. The standard PMD-Model * contains: the Root -> Project(s) -> Package(s) -> File(s) * * @author SebastianRaffel ( 16.05.2005 ), Philippe Herlin, Sven Jacob * */ public abstract class AbstractPMDRecord { public static final int TYPE_ROOT = IResource.ROOT; public static final int TYPE_PROJECT = IResource.PROJECT; public static final int TYPE_PACKAGE = IResource.FOLDER; public static final int TYPE_FILE = IResource.FILE; public static final int TYPE_MARKER = 16; public static final AbstractPMDRecord[] EMPTY_RECORDS = new AbstractPMDRecord[0]; /** * @return the Name of the Element */ public abstract String getName(); /** * Gets the parent Element. For a File this is a Package, for a Package this * is a Project and for a Project this is the Root. * * @return the parent Element */ public abstract AbstractPMDRecord getParent(); /** * Gets a List for all children. The Structure is Root -> Project(s) -> * Package(s) -> File(s). * * @return a List of the child-Elements */ public abstract AbstractPMDRecord[] getChildren(); /** * Returns the children as an ArrayList * * @return an ArrayList with the child-Elements */ public List<AbstractPMDRecord> getChildrenAsList() { return new ArrayList<AbstractPMDRecord>(Arrays.asList(getChildren())); } /** * Gets the Resource corresponding to this Element. The Resource can be the * Root, a Project, a Folder (Packages are Folders) or a File. * * @return the Resource for this Element */ public abstract IResource getResource(); /** * Gets the Resource Type. One of ROOT, PROJECT, PACKAGE or FILE. * * @return the Resource type */ public abstract int getResourceType(); /** * Adds a Resource to the Model and returns a new AbstractPMDRecord for it. * * @param resource, the Element to insert * @return a new AbstractPMDRecord with the given Element in it or null if * the Resource does not exist */ public abstract AbstractPMDRecord addResource(IResource resource); /** * Removes a Resource and also deletes the Record for it. Returns the * removed Record. * * @param resource, the Resource to remove * @return the Record for the Resource or null if the Resource does not * exist */ public abstract AbstractPMDRecord removeResource(IResource resource); /** * Gets the number of violations (markers) that belong to a priority. * * @param prio priority to search for * @return number of found violations */ public abstract int getNumberOfViolationsToPriority(int prio, boolean invertMarkerAndFileRecords); /** * Gets the counted lines of code (loc). * This works recursive. * * @return loc lines of code */ public abstract int getLOC(); /** * Gets the number of methods. * This works recursive. * * @return number of counted methods */ public abstract int getNumberOfMethods(); /** * Creates the children Elements. This method should be called in every * Constructor to create a Model recursively. * * @return an Array of child-Records for the Element. */ protected abstract AbstractPMDRecord[] createChildren(); /** * Checks, if this Element has Error-Markers in it. Calls the underlying * children (Recursion) to also check for Markers. The Recursion needs to be * stopped by overwriting this function in one implementing class. * * @return true, if the element or one of its children has Markers, false * otherwise */ public boolean hasMarkers() { final AbstractPMDRecord[] children = getChildren(); boolean result = false; for (int i = 0; i < children.length && !result; i++) { // recursively check children elements if (children[i].hasMarkers()) { result = true; } } return result; } /** * Finds Error-Markers for this element and recursively for its children * Elements. The Recursion needs to be stopped by overwriting this function * in some implementing Class. * * @return an Array of Markers or null, if no Markers were found */ public IMarker[] findMarkers() { final List<IMarker> markerList = new ArrayList<IMarker>(); final AbstractPMDRecord[] children = getChildren(); for (AbstractPMDRecord element : children) { if (element.hasMarkers()) { // get the children markers final IMarker[] childrenMarkers = element.findMarkers(); if (childrenMarkers != null) { // ...and add them to the list markerList.addAll(Arrays.asList(childrenMarkers)); } } } return markerList.isEmpty() ? null : markerList.toArray(new IMarker[markerList.size()]); // NOPMD by Herlin on 07/10/06 15:51 } /** * Finds Markers that have a given Attribute with a given Value. Finds * children Markers recursively (needs to be stopped by overwriting). * * @param attributeName, the Name of the Attribute to search for * @param value, the Value, the Attribute should have * @return a List of Markers that have the given attribute and Value or * null, if no Markers were found */ public IMarker[] findMarkersByAttribute(String attributeName, Object value) { final List<IMarker> markerList = new ArrayList<IMarker>(); final AbstractPMDRecord[] children = getChildren(); for (AbstractPMDRecord element : children) { // search the children for the Markers final IMarker[] childrenMarkers = element.findMarkersByAttribute(attributeName, value); // ... and add their Markers to the List markerList.addAll(Arrays.asList(childrenMarkers)); } return markerList.toArray(new IMarker[markerList.size()]); } /** * Finds a Resource and returns the corresponding Record. Recursively searches * the children, needs to be stopped by overwriting. * * @param resource, the Resource to search for * @return the corresponding AbstractPMDRecord for the Resource or null, if * the Resource could not be found */ public AbstractPMDRecord findResource(IResource resource) { AbstractPMDRecord record = null; final List<AbstractPMDRecord> thisChildren = getChildrenAsList(); for (int l = 0; l < thisChildren.size() && record == null; l++) { final AbstractPMDRecord thisChild = thisChildren.get(l); // check the children if the Resource exists if (thisChild.getResource().equals(resource)) { record = thisChild; } // if it is not the current children, but the Type are different // it could be one of the grand children // check this childs children recursively else if (thisChild.getResourceType() != resource.getType()) { final AbstractPMDRecord grandChild = thisChild.findResource(resource); if (grandChild != null) { record = grandChild; } } } return record; } /** * Finds a Resource with a given Name and Type. Checks children recursively * (needs to be stopped by overwriting). * * @param name, the Name of the Resource * @param type, the Type, one of ROOT, PROJECT, PACKAGE or FILE * @return the Record for the Resource or null, if the Resource could not be * found */ public AbstractPMDRecord findResourceByName(String name, int type) { AbstractPMDRecord record = null; final List<AbstractPMDRecord> thisChildren = getChildrenAsList(); for (int l = 0; l < thisChildren.size() && record == null; l++) { final AbstractPMDRecord thisChild = thisChildren.get(l); // If type and name are equals, then the record is the one we search if (thisChild.getResourceType() == type && thisChild.getName().equalsIgnoreCase(name)) { record = thisChild; } // else we check the child's children the same way else { final AbstractPMDRecord grandChild = thisChild.findResourceByName(name, type); if (grandChild != null) { record = grandChild; } } } return record; } /** * Finds all Resources with a given Name and Type. Checks children recursively * (needs to be stopped by overwriting). * * @param name, the Name of the Resource * @param type, the Type, one of ROOT, PROJECT, PACKAGE or FILE * @return all resources that match the name and type */ public List<AbstractPMDRecord> findResourcesByName(String name, int type) { final List<AbstractPMDRecord> records = new ArrayList<AbstractPMDRecord>(); final List<AbstractPMDRecord> thisChildren = getChildrenAsList(); for (AbstractPMDRecord thisChild : thisChildren) { // If type and name are equals, then the record is the one we search if (thisChild.getResourceType() == type && thisChild.getName().equalsIgnoreCase(name)) { records.add(thisChild); } // else we check the child's children the same way else { final List<AbstractPMDRecord> grandChilds = thisChild.findResourcesByName(name, type); records.addAll(grandChilds); } } return records; } }