RuleContext.java
001 /**
002  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003  */
004 package net.sourceforge.pmd;
005 
006 import java.io.File;
007 import java.util.Map;
008 import java.util.concurrent.ConcurrentHashMap;
009 
010 import net.sourceforge.pmd.lang.LanguageVersion;
011 
012 /**
013  * The RuleContext provides access to Rule processing state.  This information
014  * includes the following global information:
015  <ul>
016  *   <li>The Report to which Rule Violations are sent.</li>
017  *   <li>Named attributes.</li>
018  </ul>
019  * As well as the following source file specific information:
020  <ul>
021  *   <li>A File for the source file.</li>
022  *   <li>A String for the name of the source file.</li>
023  *   <li>The Language Version of the source file.</li>
024  </ul>
025  * It is <strong>required</strong> that all source file specific options
026  * be set between calls to difference source files.  Failure to do so, may
027  * result in undefined behavior.
028  */
029 public class RuleContext {
030 
031     private Report report = new Report();
032     private File sourceCodeFile;
033     private String sourceCodeFilename;
034     private LanguageVersion languageVersion;
035     private final Map<String, Object> attributes;
036 
037     /**
038      * Default constructor.
039      */
040     public RuleContext() {
041   attributes = new ConcurrentHashMap<String, Object>();
042     }
043 
044     /**
045      * Constructor which shares attributes with the given RuleContext.
046      */
047     public RuleContext(RuleContext ruleContext) {
048   this.attributes = ruleContext.attributes;
049     }
050 
051     /**
052      * Get the Report to which Rule Violations are sent.
053      @return The Report.
054      */
055     public Report getReport() {
056   return report;
057     }
058 
059     /**
060      * Set the Report to which Rule Violations are sent.
061      @param report The Report.
062      */
063     public void setReport(Report report) {
064   this.report = report;
065     }
066 
067     /**
068      * Get the File associated with the current source file.
069      @return The File.
070      */
071     public File getSourceCodeFile() {
072   return sourceCodeFile;
073     }
074 
075     /**
076      * Set the File associated with the current source file.
077      * While this may be set to <code>null</code>, the exclude/include
078      * facilities will not work properly without a File.
079      @param sourceCodeFile The File.
080      */
081     public void setSourceCodeFile(File sourceCodeFile) {
082   this.sourceCodeFile = sourceCodeFile;
083     }
084 
085     /**
086      * Get the file name associated with the current source file.
087      @return The file name.
088      */
089     public String getSourceCodeFilename() {
090   return sourceCodeFilename;
091     }
092 
093     /**
094      * Set the file name associated with the current source file.
095      @param filename The file name.
096      */
097     public void setSourceCodeFilename(String filename) {
098   this.sourceCodeFilename = filename;
099     }
100 
101     /**
102      * Get the LanguageVersion associated with the current source file.
103      @return The LanguageVersion, <code>null</code> if unknown.
104      */
105     public LanguageVersion getLanguageVersion() {
106   return this.languageVersion;
107     }
108 
109     /**
110      * Set the LanguageVersion associated with the current source file.
111      * This may be set to <code>null</code> to indicate the version is
112      * unknown and should be automatically determined.
113      *
114      @param languageVersion The LanguageVersion.
115      */
116     public void setLanguageVersion(LanguageVersion languageVersion) {
117   this.languageVersion = languageVersion;
118     }
119 
120     /**
121      * Set an attribute value on the RuleContext, if it does not already exist.
122      <p>
123      * Attributes can be shared between RuleContext instances.  This operation
124      * is thread-safe.
125      <p>
126      * Attribute values should be modified directly via the reference provided.
127      * It is not necessary to call <code>setAttribute(String, Object)</code> to
128      * update an attribute value.  Modifications made to the attribute value
129      * will automatically be seen by other threads.  Because of this, you must
130      * ensure the attribute values are themselves thread safe.
131      *
132      @param name The attribute name.
133      @param value The attribute value.
134      @exception IllegalArgumentException if <code>name</code> or <code> value</code> are <code>null</code>
135      @return <code>true</code> if the attribute was set, <code>false</code> otherwise.
136      */
137     public boolean setAttribute(String name, Object value) {
138   if (name == null) {
139       throw new IllegalArgumentException("Parameter 'name' cannot be null.");
140   }
141   if (value == null) {
142       throw new IllegalArgumentException("Parameter 'value' cannot be null.");
143   }
144   synchronized (this.attributes) {
145       if (!this.attributes.containsKey(name)) {
146     this.attributes.put(name, value);
147     return true;
148       else {
149     return false;
150       }
151   }
152     }
153 
154     /**
155      * Get an attribute value on the RuleContext.
156      <p>
157      * Attributes can be shared between RuleContext instances.  This operation
158      * is thread-safe.
159      <p>
160      * Attribute values should be modified directly via the reference provided.
161      * It is not necessary to call <code>setAttribute(String, Object)</code> to
162      * update an attribute value.  Modifications made to the attribute value
163      * will automatically be seen by other threads.  Because of this, you must
164      * ensure the attribute values are themselves thread safe.
165      *
166      @param name The attribute name.
167      @return The current attribute value, or <code>null</code> if the attribute does not exist.
168      */
169     public Object getAttribute(String name) {
170   return this.attributes.get(name);
171     }
172 
173     /**
174      * Remove an attribute value on the RuleContext.
175      <p>
176      * Attributes can be shared between RuleContext instances.  This operation
177      * is thread-safe.
178      <p>
179      * Attribute values should be modified directly via the reference provided.
180      * It is not necessary to call <code>setAttribute(String, Object)</code> to
181      * update an attribute value.  Modifications made to the attribute value
182      * will automatically be seen by other threads.  Because of this, you must
183      * ensure the attribute values are themselves thread safe.
184      *
185      @param name The attribute name.
186      @return The current attribute value, or <code>null</code> if the attribute does not exist.
187      */
188     public Object removeAttribute(String name) {
189   return this.attributes.remove(name);
190     }
191 }