001/*
002 * Copyright 2023 the original author or authors.
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * https://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.test.valueobjects.api.contracts;
017
018import java.lang.annotation.ElementType;
019import java.lang.annotation.Retention;
020import java.lang.annotation.RetentionPolicy;
021import java.lang.annotation.Target;
022import java.util.Collection;
023
024import de.cuioss.test.valueobjects.api.property.PropertyBuilderConfig;
025import de.cuioss.test.valueobjects.api.property.PropertyConfig;
026import de.cuioss.test.valueobjects.contract.BuilderContractImpl;
027import de.cuioss.test.valueobjects.property.PropertyMetadata;
028import de.cuioss.test.valueobjects.property.impl.PropertyMetadataImpl;
029import de.cuioss.test.valueobjects.property.impl.PropertyMetadataImpl.PropertyMetadataBuilder;
030import de.cuioss.test.valueobjects.property.util.AssertionStrategy;
031import de.cuioss.tools.property.PropertyMemberInfo;
032import de.cuioss.tools.property.PropertyReadWrite;
033
034/**
035 * If used on ValueObjectTest this test checks / tests builder of value objects.
036 * <p>
037 * As default the test assumes a static factory method with the name "builder",
038 * e.g. {@link PropertyMetadataImpl#builder()} being present on the type to be
039 * tested. This can be controlled using {@link #builderFactoryMethodName()},
040 * {@link #builderFactoryProvidingClass()} and {@link #builderMethodName()}. In
041 * case you have a builder that can be instantiated directly by using a no-args
042 * public constructor directly you can use {@link #builderClass()} instead.
043 * </p>
044 * <p>
045 * The builder methods for the individual properties are assumed to use the
046 * property-name only as method-name, e.g.
047 * {@link PropertyMetadataBuilder#propertyClass(Class)}. In case you prefer a
048 * prefix you can either configure it using {@link #methodPrefix()} or can do
049 * some more fine grained configuration with {@link PropertyBuilderConfig}
050 * </p>
051 *
052 * @author Oliver Wolff
053 */
054@Retention(RetentionPolicy.RUNTIME)
055@Target({ ElementType.TYPE })
056public @interface VerifyBuilder {
057
058    /**
059     * @return the name of the factory method for creating the builder instances. It
060     *         is assumed that it is parameter-free static method. If not set it
061     *         defaults to
062     *         {@value BuilderContractImpl#DEFAULT_BUILDER_FACTORY_METHOD_NAME}
063     */
064    String builderFactoryMethodName() default BuilderContractImpl.DEFAULT_BUILDER_FACTORY_METHOD_NAME;
065
066    /**
067     * @return the name of the build method on the {@link #builderClass()}. It is
068     *         assumed that it is parameter-free method on the builderType and
069     *         returns instances of the type on unit class level of ValueObjectTest.
070     *         Defaults to {@value BuilderContractImpl#DEFAULT_BUILD_METHOD_NAME}
071     */
072    String builderMethodName() default BuilderContractImpl.DEFAULT_BUILD_METHOD_NAME;
073
074    /**
075     * This attribute defines the actual type of the concrete builder. The default
076     * value {@link VerifyBuilder} acts as {@code null} value. If it is set it will
077     * be used instead of any factory. It is assumed to have a no args public
078     * constructor.
079     *
080     * @return the builder-class
081     */
082    Class<?> builderClass() default VerifyBuilder.class;
083
084    /**
085     * Optional attribute. The default assumes that the factory method for creating
086     * the concrete builder is located at the object under test. This method is only
087     * necessary if it is located on another type, e.g the actual unit-test-class.
088     * The default value {@link VerifyBuilder} acts as null value
089     *
090     * @return the type where the builderFactoryMethod is defined, the name of this
091     *         method is defined within {@link #builderFactoryMethodName()}
092     */
093    Class<?> builderFactoryProvidingClass() default VerifyBuilder.class;
094
095    /**
096     * @return an array of properties, identified by their names that are not to be
097     *         considered for this test: black-list
098     */
099    String[] exclude() default {};
100
101    /**
102     * @return an array of properties, identified by their names that are to be
103     *         considered for this test: white-list
104     */
105    String[] of() default {};
106
107    /**
108     * @return an array of properties, identified by their names that are to be
109     *         treated as required properties, see
110     *         {@link PropertyMetadata#isRequired()}
111     */
112    String[] required() default {};
113
114    /**
115     * @return an array of properties, identified by their names that are to be
116     *         treated as transient properties, see
117     *         {@link PropertyMemberInfo#TRANSIENT}
118     */
119    String[] transientProperties() default {};
120
121    /**
122     * @return an array of properties, identified by their names that are to be
123     *         treated as having a default values, see
124     *         {@link PropertyMetadata#isDefaultValue()}
125     */
126    String[] defaultValued() default {};
127
128    /**
129     * @return an array of properties, identified by their names that are to be
130     *         treated as being read-only, see {@link PropertyReadWrite#READ_ONLY},
131     *         usually used in conjunction with {@link #defaultValued()}
132     */
133    String[] readOnly() default {};
134
135    /**
136     * @return an array of properties, identified by their names that are to be
137     *         treated as being write-only, see
138     *         {@link PropertyReadWrite#WRITE_ONLY}, usually used in cases where a
139     *         property to be written will result in other properties but itself can
140     *         not be accessed directly
141     */
142    String[] writeOnly() default {};
143
144    /**
145     * @return an array of properties, identified by their names representing at
146     *         least a {@link Collection} that are to be asserted ignoring the
147     *         concrete order, see {@link PropertyConfig#assertionStrategy()} and
148     *         {@link AssertionStrategy#COLLECTION_IGNORE_ORDER}. The default
149     *         implementation will always respect / assert the same order of
150     *         elements.
151     */
152    String[] assertUnorderedCollection() default {};
153
154    /**
155     * In case methodPrefix is not set the corresponding build method to be accessed
156     * for setting the value is the name of the attribute: propertyName(), in case
157     * it is a concrete value, e.g. 'with' it will taken into account:
158     * withPropertName().
159     *
160     * @return the method prefix, defaults to empty string
161     */
162    String methodPrefix() default "";
163
164}