class AnnotationImpl implements Annotation {
	
	private String name;
	private Javadoc javadoc;
	private final List<AnnotationUsage> annotations;
	private final List<Field> fields;
	private final List<Import> imports;
	private final Set<Modifier> modifiers;

    /**
     * Initializes this annotation using a name.
     * <p>
     * <b>Warning!</b> This class should not be instantiated directly but using 
     * the {@link Annotation#of(java.lang.String)} method!
     * 
     * @param name  the name
     */
	public
	AnnotationImpl(String name) {
		this.name        = requireNonNull(name);
		this.javadoc     = null;
		this.annotations = new ArrayList<>();
		this.fields      = new ArrayList<>();
		this.imports	 = new ArrayList<>();
		this.modifiers   = EnumSet.noneOf(Modifier.class);
	}
	
    /**
     * Copy constructor.
     * 
     * @param prototype  the prototype
     */
	protected AnnotationImpl(Annotation prototype) {
        requireNonNull(prototype);
		name        = prototype.getName();
		javadoc     = prototype.getJavadoc().map(Copier::copy).orElse(null);
		annotations = Copier.copy(prototype.getAnnotations());
		fields      = Copier.copy(prototype.getFields());
		imports     = Copier.copy(prototype.getImports());
		modifiers   = Copier.copy(prototype.getModifiers(), Modifier::copy, EnumSet.noneOf(Modifier.class));
	}

	@Override
	public Annotation setName(String name) {
		this.name = requireNonNull(name);
		return this;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public List<Field> getFields() {
		return fields;
	}

	@Override
	public Annotation set(Javadoc doc) {
		this.javadoc = doc.setParent(this);
		return this;
	}

	@Override
	public Optional<Javadoc> getJavadoc() {
		return Optional.ofNullable(javadoc);
	}

	@Override
	public List<Import> getImports() {
		return imports;
	}

	@Override
	public Set<Modifier> getModifiers() {
		return modifiers;
	}

	@Override
	public List<AnnotationUsage> getAnnotations() {
		return annotations;
	}

    @Override
	public AnnotationImpl copy() {
		return new AnnotationImpl(this);
	}

    @Override
    public int hashCode() {<FILL_FUNCTION_BODY>}

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final AnnotationImpl other = (AnnotationImpl) obj;
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.javadoc, other.javadoc)) {
            return false;
        }
        if (!Objects.equals(this.annotations, other.annotations)) {
            return false;
        }
        if (!Objects.equals(this.fields, other.fields)) {
            return false;
        }
        if (!Objects.equals(this.imports, other.imports)) {
            return false;
        }
		return Objects.equals(this.modifiers, other.modifiers);
	}


}

        int hash = 7;
        hash = 41 * hash + Objects.hashCode(this.name);
        hash = 41 * hash + Objects.hashCode(this.javadoc);
        hash = 41 * hash + Objects.hashCode(this.annotations);
        hash = 41 * hash + Objects.hashCode(this.fields);
        hash = 41 * hash + Objects.hashCode(this.imports);
        hash = 41 * hash + Objects.hashCode(this.modifiers);
        return hash;
    
<no_super_class>