org.lunarray.model.descriptor.accessor.reference.ReferenceBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.lunarray.model.descriptor.accessor.reference.ReferenceBuilder.java

Source

/* 
 * Model Tools.
 * Copyright (C) 2013 Pal Hargitai (pal@lunarray.org)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.lunarray.model.descriptor.accessor.reference;

import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;

import org.apache.commons.lang.Validate;
import org.lunarray.model.descriptor.accessor.operation.DescribedOperation;
import org.lunarray.model.descriptor.accessor.operation.PersistentOperation;
import org.lunarray.model.descriptor.accessor.property.DescribedProperty;
import org.lunarray.model.descriptor.accessor.property.PersistentProperty;
import org.lunarray.model.descriptor.accessor.property.Property;
import org.lunarray.model.descriptor.accessor.property.PropertyBuilder;
import org.lunarray.model.descriptor.accessor.reference.operation.OperationReference;
import org.lunarray.model.descriptor.accessor.reference.operation.impl.DirectOperationReference;
import org.lunarray.model.descriptor.accessor.reference.operation.impl.PropertyOperationReference;
import org.lunarray.model.descriptor.accessor.reference.property.PropertyValueReference;
import org.lunarray.model.descriptor.accessor.reference.property.impl.DeferredPropertyValueReference;
import org.lunarray.model.descriptor.accessor.reference.property.impl.DirectPropertyValueReference;
import org.lunarray.model.descriptor.accessor.reference.property.impl.PropertyReference;
import org.lunarray.model.descriptor.accessor.reference.property.impl.PropertyReference.Builder;
import org.lunarray.model.descriptor.builder.Configuration;
import org.lunarray.model.descriptor.model.extension.ExtensionRef;
import org.lunarray.model.descriptor.objectfactory.ObjectFactory;

/**
 * A context for accessors.
 * 
 * @author Pal Hargitai (pal@lunarray.org)
 * @param <T>
 *            The to type.
 * @param <F>
 *            The from type.
 */
public final class ReferenceBuilder<T, F> {

    /** The accessor deque. */
    private final transient Deque<PropertyReference<T, F>> accessors;
    /** The configuration. */
    private final transient Configuration configuration;
    /** The embedding deque. */
    private final transient Deque<String> embedded;
    /** Optional object factory. */
    private transient ExtensionRef<ObjectFactory> objectFactory;
    /** The properties deque. */
    private final transient Deque<PropertyBuilder<?>> properties;

    /**
     * Constructs the context.
     * 
     * @param configuration
     *            The configuration.
     */
    public ReferenceBuilder(final Configuration configuration) {
        this.configuration = configuration;
        this.accessors = new LinkedList<PropertyReference<T, F>>();
        this.embedded = new LinkedList<String>();
        this.properties = new LinkedList<PropertyBuilder<?>>();
    }

    /**
     * Gets the current reference.
     * 
     * @return The reference.
     */
    @SuppressWarnings("unchecked")
    // We know it's an object factory.
    public PropertyValueReference<T, F> getCurrentReference() {
        final PropertyReference<T, F> accessor = this.accessors.pop();
        PropertyValueReference<T, F> valueReference = null;
        valueReference = new DirectPropertyValueReference<T, F>(accessor);
        for (final PropertyReference<T, F> accessorParent : this.accessors) {
            final PropertyReference<F, F> accessorFrom = (PropertyReference<F, F>) accessorParent;
            org.lunarray.model.descriptor.accessor.reference.property.impl.DeferredPropertyValueReference.Builder<T, F, F> builder;
            builder = DeferredPropertyValueReference.createBuilder();
            builder.objectFactoryReference(this.objectFactory);
            builder.valueReference(valueReference).propertyAccessor(accessorFrom);
            valueReference = builder.build();
        }
        this.accessors.push(accessor);
        return valueReference;
    }

    /**
     * Gets the current reference.
     * 
     * @param operation
     *            The operation to get the reference for.
     * @return The reference.
     */
    @SuppressWarnings("unchecked")
    // We know it's an object factory.
    public OperationReference<F> getCurrentReference(final PersistentOperation operation) {
        final OperationReference<F> reference;
        final DirectOperationReference<T> directReference = new DirectOperationReference<T>(operation);
        if (this.accessors.isEmpty()) {
            reference = (OperationReference<F>) directReference;
        } else {
            reference = new PropertyOperationReference<F, T>(directReference, this.getCurrentReference());
        }
        return reference;
    }

    /**
     * Gets the properties.
     * 
     * @return The properties.
     */
    public Deque<DescribedProperty<?>> getDescribedProperties() {
        final Deque<DescribedProperty<?>> result = new LinkedList<DescribedProperty<?>>();
        for (final PropertyBuilder<?> property : this.properties) {
            result.add(property.buildDescribed());
        }
        return result;
    }

    /**
     * Gets the properties.
     * 
     * @return The properties.
     */
    public Deque<Property<?>> getProperties() {
        final Deque<Property<?>> result = new LinkedList<Property<?>>();
        for (final PropertyBuilder<?> property : this.properties) {
            result.add(property.build());
        }
        return result;
    }

    /**
     * Sets a new value for the objectFactoryRef field.
     * 
     * @param objectFactoryRef
     *            The new value for the objectFactoryRef field.
     * @return The context.
     */
    public ReferenceBuilder<T, F> objectFactoryRef(final ExtensionRef<ObjectFactory> objectFactoryRef) {
        this.objectFactory = objectFactoryRef;
        return this;
    }

    /**
     * Pop a property.
     */
    public void popProperty() {
        this.accessors.poll();
        this.embedded.poll();
        this.properties.poll();
    }

    /**
     * Add a property.
     * 
     * @param propertyBuilder
     *            The property to add. May not be null.
     * @param name
     *            The property name.
     */
    @SuppressWarnings("unchecked")
    // We know this is the correct type.
    public void pushProperty(final PropertyBuilder<?> propertyBuilder, final String name) {
        Validate.notNull(propertyBuilder, "Property may not be null.");
        final PersistentProperty<T> property = (PersistentProperty<T>) propertyBuilder.build();
        final Builder<T> builder = PropertyReference.createBuilder();
        builder.property(property);
        final PropertyReference<T, F> accessor = builder.build();
        this.accessors.push(accessor);
        this.embedded.push(name);
        this.properties.push(propertyBuilder);
    }

    /**
     * Resolve the property name.
     * 
     * @return The name.
     */
    public String resolveName() {
        return this.resolveNameBuilder().toString();
    }

    /**
     * Resolve the operation name.
     * 
     * @param operationDescriptor
     *            The operation.
     * @param name
     *            The name.
     * @return The name.
     */
    public String resolveName(final DescribedOperation operationDescriptor, final String name) {
        final StringBuilder nameBuilder = this.resolveNameBuilder();
        if (!this.embedded.isEmpty()) {
            nameBuilder.append(this.configuration.embeddedIndicator());
        }
        nameBuilder.append(name);
        return nameBuilder.toString();
    }

    /**
     * Resolves the name and returns the builder.
     * 
     * @return The name builder.
     */
    private StringBuilder resolveNameBuilder() {
        final StringBuilder nameBuilder = new StringBuilder();
        final Iterator<String> iterator = this.embedded.descendingIterator();
        if (iterator.hasNext()) {
            nameBuilder.append(iterator.next());
        }
        while (iterator.hasNext()) {
            nameBuilder.append(this.configuration.embeddedIndicator());
            nameBuilder.append(iterator.next());
        }
        return nameBuilder;
    }
}