001package serp.bytecode;
002
003/**
004 * An annotated entity.
005 *
006 * @author Abe White
007 */
008public 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}