001    /* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil -*-
002     *
003     * $Id$
004     *
005     * Copyright (c) 2011 Edugility LLC.
006     *
007     * Permission is hereby granted, free of charge, to any person
008     * obtaining a copy of this software and associated documentation
009     * files (the "Software"), to deal in the Software without
010     * restriction, including without limitation the rights to use, copy,
011     * modify, merge, publish, distribute, sublicense and/or sell copies
012     * of the Software, and to permit persons to whom the Software is
013     * furnished to do so, subject to the following conditions:
014     * 
015     * The above copyright notice and this permission notice shall be
016     * included in all copies or substantial portions of the Software.
017     * 
018     * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
021     * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
022     * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
023     * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
024     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
025     * DEALINGS IN THE SOFTWARE.
026     *
027     * The original copy of this license is available at
028     * http://www.opensource.org/license/mit-license.html.
029     */
030    package com.edugility.jpa.maven.plugin;
031    
032    import java.lang.annotation.ElementType; // for javadoc only
033    
034    import java.util.HashMap;
035    import java.util.Set;
036    
037    /**
038     * An {@link org.scannotation.AnnotationDB} subclass that adds {@link
039     * Cloneable} support and the ability to {@linkplain #clear() clear
040     * state}.
041     *
042     * @author <a href="mailto:ljnelson@gmail.com">Laird Nelson</a>
043     *
044     * @version 1.0-SNAPSHOT
045     *
046     * @since 1.0-SNAPSHOT
047     */
048    public class AnnotationDB extends org.scannotation.AnnotationDB implements Cloneable {
049      
050      /**
051       * A serial version identifier uniquely identifying the version of
052       * this class.  See the <a
053       * href="http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html">documentation
054       * for the {@code Serializable} class</a> for details.
055       */
056      private static final long serialVersionUID = 1L;
057    
058      /**
059       * Creates a new {@link AnnotationDB}.
060       */
061      public AnnotationDB() {
062        super();
063      }
064      
065      /**
066       * Creates a new {@link AnnotationDB}, performing a deep copy of the
067       * state of the supplied {@link AnnotationDB}.
068       *
069       * @param db the {@link AnnotationDB} whose state should be copied;
070       * may be {@code null}
071       */
072      public AnnotationDB(final AnnotationDB db) {
073        super();
074        this.copyState(db);
075      }
076      
077      /**
078       * Deeply copies all known state from the supplied {@link
079       * AnnotationDB} to this one.
080       *
081       * <p>Specifically, this method copies the {@link
082       * #getAnnotationIndex() annotationIndex}, {@link #getClassIndex()
083       * classIndex} and {@link
084       * org.scannotation.AnnotationDB#implementsIndex} properties into
085       * new data structures.  The elements within these data structures
086       * are not cloned.</p>
087       *
088       * <p>This method also copies the {@code boolean} properties ({@link
089       * #getScanClassAnnotations scanClassAnnotations} and the like).</p>
090       *
091       * @param db the {@link AnnotationDB} whose state should be copied;
092       * may be {@code null} in which case no operation takes place
093       */
094      private final void copyState(final AnnotationDB db) {
095        if (db != null) {
096          this.annotationIndex = new HashMap<String, Set<String>>(db.getAnnotationIndex());
097          this.implementsIndex = new HashMap<String, Set<String>>(db.implementsIndex);
098          this.classIndex = new HashMap<String, Set<String>>(db.getClassIndex());
099          
100          this.setScanClassAnnotations(db.getScanClassAnnotations());
101          this.setScanMethodAnnotations(db.getScanMethodAnnotations());
102          this.setScanParameterAnnotations(db.getScanParameterAnnotations());
103          this.setScanFieldAnnotations(db.getScanFieldAnnotations());
104          
105          this.setIgnoredPackages(db.getIgnoredPackages().clone());
106        }
107      }
108    
109      /**
110       * Returns a deep copy of this {@link AnnotationDB}.
111       *
112       * <p>This method never returns {@code null}.</p>
113       *
114       * @return a deep copy of this {@link AnnotationDB}; never {@code null}
115       */
116      @Override
117      public AnnotationDB clone() {
118        final AnnotationDB copy;
119        AnnotationDB temp = null;
120        try {
121          temp = (AnnotationDB)super.clone();
122        } catch (final CloneNotSupportedException error) {
123          throw (InternalError)new InternalError().initCause(error);
124        } finally {
125          copy = temp;
126        }
127        copy.copyState(this);
128        return copy;
129      }
130    
131      /**
132       * Clears all transient state from this {@link AnnotationDB}.
133       */
134      public void clear() {
135        this.annotationIndex.clear();
136        this.implementsIndex.clear();
137        this.classIndex.clear();
138      }
139    
140      /**
141       * Returns whether this {@link AnnotationDB} should scan field
142       * annotations.
143       *
144       * @return {@code true} if this {@link AnnotationDB} should scan
145       * {@linkplain ElementType#FIELD field annotations}; {@code false}
146       * otherwise
147       */
148      public boolean getScanFieldAnnotations() {
149        return this.scanFieldAnnotations;
150      }
151    
152      /**
153       * {@inheritDoc}
154       */
155      @Override
156      public void setScanFieldAnnotations(final boolean scan) {
157        super.setScanFieldAnnotations(scan);
158      }
159    
160      /**
161       * Returns whether this {@link AnnotationDB} should scan method
162       * annotations.
163       *
164       * @return {@code true} if this {@link AnnotationDB} should scan
165       * {@linkplain ElementType#METHOD method annotations}; {@code false}
166       * otherwise
167       */
168      public boolean getScanMethodAnnotations() {
169        return this.scanMethodAnnotations;
170      }
171    
172      /**
173       * Sets whether this {@link AnnotationDB} should scan {@linkplain
174       * ElementType#METHOD method annotations}.
175       *
176       * @param scan whether to scan {@linkplain ElementType#METHOD method
177       * annotations}
178       */
179      @Override
180      public void setScanMethodAnnotations(final boolean scan) {
181        super.setScanMethodAnnotations(scan);
182      }
183    
184      /**
185       * Returns whether this {@link AnnotationDB} should scan parameter
186       * annotations.
187       *
188       * @return {@code true} if this {@link AnnotationDB} should scan
189       * {@linkplain ElementType#PARAMETER parameter annotations}; {@code false}
190       * otherwise
191       */
192      public boolean getScanParameterAnnotations() {
193        return this.scanParameterAnnotations;
194      }
195    
196      /**
197       * Sets whether this {@link AnnotationDB} should scan {@linkplain
198       * ElementType#PARAMETER parameter annotations}.
199       *
200       * @param scan whether to scan {@linkplain ElementType#PARAMETER
201       * parameter annotations}
202       */
203      @Override
204      public void setScanParameterAnnotations(final boolean scan) {
205        super.setScanParameterAnnotations(scan);
206      }
207    
208      /**
209       * Returns whether this {@link AnnotationDB} should scan class annotations.
210       *
211       * @return {@code true} if this {@link AnnotationDB} should scan
212       * {@linkplain ElementType#TYPE class annotations}; {@code false}
213       * otherwise
214       */
215      public boolean getScanClassAnnotations() {
216        return this.scanClassAnnotations;
217      }
218    
219      /**
220       * Sets whether this {@link AnnotationDB} should scan {@linkplain
221       * ElementType#TYPE class annotations}.
222       *
223       * @param scan whether to scan {@linkplain ElementType#TYPE class
224       * annotations}
225       */
226      @Override
227      public void setScanClassAnnotations(final boolean scan) {
228        super.setScanClassAnnotations(scan);
229      }
230    
231    }