Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.adobe.ac.pmd.rules.core; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import java.util.regex.Pattern; import net.sourceforge.pmd.CommonAbstractRule; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.properties.IntegerProperty; import net.sourceforge.pmd.rules.regex.RegexHelper; import org.apache.commons.lang.StringUtils; import com.adobe.ac.pmd.IFlexViolation; import com.adobe.ac.pmd.files.IFlexFile; import com.adobe.ac.pmd.nodes.IPackage; import com.adobe.ac.pmd.rules.core.thresholded.IThresholdedRule; /** * Abstract FlexPMD rule. Extends this class if you want to find violations at a * very low level. Otherwise extends AbstractAstFlexRule, or * AbstractRegexpBasedRule. * * @author xagnetti */ public abstract class AbstractFlexRule extends CommonAbstractRule implements IFlexRule { protected static final String MAXIMUM = "maximum"; protected static final String MINIMUM = "minimum"; private static final String AS3_COMMENT_TOKEN = "//"; private static final Logger LOGGER = Logger.getLogger(AbstractFlexRule.class.getName()); private static final String MXML_COMMENT_TOKEN = "<!--"; private IFlexFile currentFile; private IPackage currentPackageNode; private Set<String> excludes; private Map<String, IFlexFile> filesInSourcePath; /** * */ public AbstractFlexRule() { super(); setDefaultPriority(); } /** * not used in FlexPMD */ public final void apply(final List<?> astCompilationUnits, final RuleContext ctx) { } /** * @return Extracts the rulename from the qualified name of the underlying * class */ public final String getRuleName() { final String qualifiedClassName = this.getClass().getName(); final String className = StringUtils.substringAfter(qualifiedClassName, "."); return className.replace("Rule", ""); } /* * (non-Javadoc) * @see * com.adobe.ac.pmd.rules.core.IFlexRule#processFile(com.adobe.ac.pmd.files * .IFlexFile, com.adobe.ac.pmd.nodes.IPackage, java.util.Map) */ public final List<IFlexViolation> processFile(final IFlexFile file, final IPackage packageNode, final Map<String, IFlexFile> files) { List<IFlexViolation> violations = new ArrayList<IFlexViolation>(); currentFile = file; filesInSourcePath = files; currentPackageNode = packageNode; if (isConcernedByTheCurrentFile() && !isFileExcluded(file)) { onRuleStart(); violations = findViolationsInCurrentFile(); } return violations; } /* * (non-Javadoc) * @see com.adobe.ac.pmd.rules.core.IFlexRule#setExcludes(java.util.Set) */ public void setExcludes(final Set<String> excludesToBeSet) { excludes = excludesToBeSet; } /** * @param violatedLine * @return */ boolean isViolationIgnored(final String violatedLine) { final boolean containsNoPmd = lineContainsNoPmd(violatedLine, MXML_COMMENT_TOKEN) || lineContainsNoPmd(violatedLine, AS3_COMMENT_TOKEN); if (!containsNoPmd) { return false; } final String name = getRuleName().replaceAll("Rule", ""); final String ruleName = name.contains(".") ? StringUtils.substringAfterLast(name, ".") : name; final String strippedLine = computeStrippedLine(violatedLine); return strippedLineContainsNoPmdAndRuleName(MXML_COMMENT_TOKEN, ruleName, strippedLine) || strippedLineContainsNoPmdAndRuleName(AS3_COMMENT_TOKEN, ruleName, strippedLine); } /** * @param violations * @param position * @return */ protected final IFlexViolation addViolation(final List<IFlexViolation> violations, final ViolationPosition position) { final IFlexViolation violation = new Violation(position, this, getCurrentFile()); final int beginLine = position.getBeginLine(); prettyPrintMessage(violation); if (beginLine == -1 || beginLine == 0) { violations.add(violation); } else if (beginLine <= getCurrentFile().getLinesNb()) { if (isViolationIgnored(getCurrentFile().getLineAt(beginLine))) { LOGGER.info(getRuleName() + " has been ignored in " + getCurrentFile().getFilename() + " (" + beginLine + ")"); } else { violations.add(violation); } } return violation; } protected final IFlexViolation addViolation(final List<IFlexViolation> violations, final ViolationPosition position, final String... messageToReplace) { final IFlexViolation violation = addViolation(violations, position); for (int i = 0; i < messageToReplace.length; i++) { violation.replacePlaceholderInMessage(messageToReplace[i], i); } return violation; } /** * @return */ protected abstract List<IFlexViolation> findViolationsInCurrentFile(); /** * @return the current file under investigation */ protected IFlexFile getCurrentFile() { return currentFile; } /** * @return */ protected final IPackage getCurrentPackageNode() { return currentPackageNode; } /** * @return */ protected abstract ViolationPriority getDefaultPriority(); /** * @return */ protected final Map<String, IFlexFile> getFilesInSourcePath() { return filesInSourcePath; } /** * @param rule * @return */ protected final Map<String, PropertyDescriptor> getThresholdedRuleProperties(final IThresholdedRule rule) { final Map<String, PropertyDescriptor> properties = new LinkedHashMap<String, PropertyDescriptor>(); properties.put(rule.getThresholdName(), new IntegerProperty(rule.getThresholdName(), "", rule.getDefaultThreshold(), properties.size())); return properties; } /** * @return is this rule concerned by the current file */ protected abstract boolean isConcernedByTheCurrentFile(); /** * Called when the rule is started on the current file */ protected void onRuleStart() { } private String computeStrippedLine(final String violatedLine) { final String comment_token = getCurrentFile().isMxml() ? MXML_COMMENT_TOKEN : AS3_COMMENT_TOKEN; String strippedLine = violatedLine; if (violatedLine.indexOf(comment_token + " N") > 0) { strippedLine = StringUtils.strip(violatedLine.substring(violatedLine.indexOf(comment_token + " N"))); } else if (violatedLine.indexOf(comment_token + "N") > 0) { strippedLine = StringUtils.strip(violatedLine.substring(violatedLine.indexOf(comment_token + "N"))); } return strippedLine; } private boolean isFileExcluded(final IFlexFile file) { if (excludes != null) { for (final String exclusion : excludes) { final Pattern pattern = Pattern.compile(exclusion); if (RegexHelper.isMatch(pattern, file.getFilePath())) { return true; } } } return false; } private boolean lineContainsNoPmd(final String violatedLine, final String comment_token) { return violatedLine.contains(comment_token + " No PMD") || violatedLine.contains(comment_token + " NO PMD") || violatedLine.contains(comment_token + " NOPMD") || violatedLine.contains(comment_token + "NOPMD"); } private void prettyPrintMessage(final IFlexViolation violation) { final int nbOfBraces = violation.getRuleMessage().split("\\{").length - 1; if (this instanceof IThresholdedRule) { final IThresholdedRule thresholdeRule = (IThresholdedRule) this; violation.replacePlaceholderInMessage(String.valueOf(thresholdeRule.getThreshold()), nbOfBraces - 2); violation.replacePlaceholderInMessage( String.valueOf(thresholdeRule.getActualValueForTheCurrentViolation()), nbOfBraces - 1); } if (getDescription() != null) { violation.appendToMessage(". "); violation.appendToMessage(getDescription()); } } private void setDefaultPriority() { setPriority(Integer.valueOf(getDefaultPriority().toString())); } private boolean strippedLineContainsNoPmdAndRuleName(final String comment_token, final String ruleName, final String strippedLine) { return strippedLine.endsWith(comment_token + " No PMD") || strippedLine.endsWith(comment_token + " NO PMD") || strippedLine.endsWith(comment_token + " NOPMD") || strippedLine.endsWith(comment_token + "NOPMD") || strippedLine.contains(ruleName); } }