class BasicVariableDescriptor<Solution_> extends GenuineVariableDescriptor<Solution_> {

    private boolean chained;
    private boolean nullable;

    // ************************************************************************
    // Constructors and simple getters/setters
    // ************************************************************************

    public BasicVariableDescriptor(EntityDescriptor<Solution_> entityDescriptor, MemberAccessor variableMemberAccessor) {
        super(entityDescriptor, variableMemberAccessor);
    }

    // ************************************************************************
    // Lifecycle methods
    // ************************************************************************

    @Override
    protected void processPropertyAnnotations(DescriptorPolicy descriptorPolicy) {
        PlanningVariable planningVariableAnnotation = variableMemberAccessor.getAnnotation(PlanningVariable.class);
        processNullable(planningVariableAnnotation);
        processChained(planningVariableAnnotation);
        processValueRangeRefs(descriptorPolicy, planningVariableAnnotation.valueRangeProviderRefs());
        processStrength(planningVariableAnnotation.strengthComparatorClass(),
                planningVariableAnnotation.strengthWeightFactoryClass());
    }

    private void processNullable(PlanningVariable planningVariableAnnotation) {
        nullable = planningVariableAnnotation.nullable();
        if (nullable && variableMemberAccessor.getType().isPrimitive()) {
            throw new IllegalArgumentException("The entityClass (" + entityDescriptor.getEntityClass()
                    + ") has a @" + PlanningVariable.class.getSimpleName()
                    + " annotated property (" + variableMemberAccessor.getName()
                    + ") with nullable (" + nullable + "), which is not compatible with the primitive propertyType ("
                    + variableMemberAccessor.getType() + ").");
        }
    }

    private void processChained(PlanningVariable planningVariableAnnotation) {<FILL_FUNCTION_BODY>}

    // ************************************************************************
    // Worker methods
    // ************************************************************************

    @Override
    public boolean isListVariable() {
        return false;
    }

    @Override
    public boolean isChained() {
        return chained;
    }

    @Override
    public boolean isNullable() {
        return nullable;
    }

    @Override
    public boolean acceptsValueType(Class<?> valueType) {
        return getVariablePropertyType().isAssignableFrom(valueType);
    }

    // ************************************************************************
    // Extraction methods
    // ************************************************************************

    @Override
    public boolean isInitialized(Object entity) {
        if (isNullable()) {
            return true;
        }
        Object variable = getValue(entity);
        return variable != null;
    }
}

        chained = planningVariableAnnotation.graphType() == PlanningVariableGraphType.CHAINED;
        if (!chained) {
            return;
        }
        if (!acceptsValueType(entityDescriptor.getEntityClass())) {
            throw new IllegalArgumentException("The entityClass (" + entityDescriptor.getEntityClass()
                    + ") has a @" + PlanningVariable.class.getSimpleName()
                    + " annotated property (" + variableMemberAccessor.getName()
                    + ") with chained (" + chained + ") and propertyType (" + getVariablePropertyType()
                    + ") which is not a superclass/interface of or the same as the entityClass ("
                    + entityDescriptor.getEntityClass() + ").\n"
                    + "If an entity's chained planning variable cannot point to another entity of the same class,"
                    + " then it is impossible to make a chain longer than 1 entity and therefore chaining is useless.");
        }
        if (nullable) {
            throw new IllegalArgumentException("The entityClass (" + entityDescriptor.getEntityClass()
                    + ") has a @" + PlanningVariable.class.getSimpleName()
                    + " annotated property (" + variableMemberAccessor.getName()
                    + ") with chained (" + chained + "), which is not compatible with nullable (" + nullable + ").");
        }
    
<methods>public void <init>(EntityDescriptor<Solution_>, org.optaplanner.core.impl.domain.common.accessor.MemberAccessor) ,public abstract boolean acceptsValueType(Class<?>) ,public SelectionSorter<Solution_,java.lang.Object> getDecreasingStrengthSorter() ,public SelectionSorter<Solution_,java.lang.Object> getIncreasingStrengthSorter() ,public SelectionFilter<Solution_,java.lang.Object> getMovableChainedTrailingValueFilter() ,public long getValueCount(Solution_, java.lang.Object) ,public ValueRangeDescriptor<Solution_> getValueRangeDescriptor() ,public boolean hasMovableChainedTrailingValueFilter() ,public abstract boolean isChained() ,public boolean isGenuineAndUninitialized(java.lang.Object) ,public abstract boolean isInitialized(java.lang.Object) ,public abstract boolean isListVariable() ,public abstract boolean isNullable() ,public boolean isReinitializable(java.lang.Object) ,public boolean isValueRangeEntityIndependent() ,public void linkVariableDescriptors(org.optaplanner.core.impl.domain.policy.DescriptorPolicy) ,public void processAnnotations(org.optaplanner.core.impl.domain.policy.DescriptorPolicy) ,public java.lang.String toString() <variables>private SelectionSorter<Solution_,java.lang.Object> decreasingStrengthSorter,private SelectionSorter<Solution_,java.lang.Object> increasingStrengthSorter,private SelectionFilter<Solution_,java.lang.Object> movableChainedTrailingValueFilter,private ValueRangeDescriptor<Solution_> valueRangeDescriptor