001    package serp.bytecode;
002    
003    /**
004     * An annotated entity.
005     *
006     * @author Abe White
007     */
008    public abstract class Annotated extends Attributes {
009        /**
010         * Return runtime <b>invisible</b> annotation information for the entity.
011         * Acts internally through the {@link Attributes} interface.
012         *
013         * @param add if true, a new annotations attribute will be added if not 
014         * already present
015         * @return the annotation information, or null if none and the
016         * <code>add</code> param is set to false
017         */
018        public Annotations getDeclaredAnnotations(boolean add) {
019            Annotations ann = (Annotations) getAttribute
020                (Constants.ATTR_ANNOTATIONS);
021            if (!add || ann != null)
022                return ann;
023            ensureBytecodeVersion();
024            return (Annotations) addAttribute(Constants.ATTR_ANNOTATIONS);
025        }
026    
027        /**
028         * Remove the runtime <b>invisible</b> annotations attribute for the entity.
029         * Acts internally through the {@link Attributes} interface.
030         *
031         * @return true if there was an attribute to remove
032         */
033        public boolean removeDeclaredAnnotations() {
034            return removeAttribute(Constants.ATTR_ANNOTATIONS);
035        }
036    
037        /**
038         * Return runtime visible annotation information for the entity.
039         * Acts internally through the {@link Attributes} interface.
040         *
041         * @param add if true, a new runtime annotations attribute will be
042         * added if not already present
043         * @return the annotation information, or null if none and the
044         * <code>add</code> param is set to false
045         */
046        public Annotations getDeclaredRuntimeAnnotations(boolean add) {
047            Annotations ann = (Annotations) getAttribute
048                (Constants.ATTR_RUNTIME_ANNOTATIONS);
049            if (!add || ann != null)
050                return ann;
051            ensureBytecodeVersion();
052            return (Annotations) addAttribute(Constants.ATTR_RUNTIME_ANNOTATIONS);
053        }
054    
055        /**
056         * Remove the runtime visible annotations attribute for the entity.
057         * Acts internally through the {@link Attributes} interface.
058         *
059         * @return true if there was an attribute to remove
060         */
061        public boolean removeDeclaredRuntimeAnnotations() {
062            return removeAttribute(Constants.ATTR_RUNTIME_ANNOTATIONS);
063        }
064    
065        /**
066         * When adding annotations, make sure the bytecode spec supports them.
067         */
068        private void ensureBytecodeVersion() {
069            BCClass bc = getBCClass();
070            if (bc.getMajorVersion() < Constants.MAJOR_VERSION_JAVA5) {
071                bc.setMajorVersion(Constants.MAJOR_VERSION_JAVA5);
072                bc.setMinorVersion(Constants.MINOR_VERSION_JAVA5);
073            }
074        }
075     
076        /**
077         * Internal access to the owning class.
078         */
079        abstract BCClass getBCClass();
080    }