All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nakedobjects.plugins.dnd.viewer.builder.ObjectFieldBuilder Maven / Gradle / Ivy

The newest version!
package org.nakedobjects.plugins.dnd.viewer.builder;

import org.apache.log4j.Logger;
import org.nakedobjects.metamodel.adapter.NakedObject;
import org.nakedobjects.metamodel.commons.ensure.Assert;
import org.nakedobjects.metamodel.commons.exceptions.UnknownTypeException;
import org.nakedobjects.metamodel.commons.filters.Filter;
import org.nakedobjects.metamodel.spec.NakedObjectSpecification;
import org.nakedobjects.metamodel.spec.feature.NakedObjectAssociation;
import org.nakedobjects.metamodel.spec.feature.NakedObjectAssociationFilters;
import org.nakedobjects.metamodel.util.NakedObjectUtils;
import org.nakedobjects.plugins.dnd.CompositeViewSpecification;
import org.nakedobjects.plugins.dnd.Content;
import org.nakedobjects.plugins.dnd.FieldContent;
import org.nakedobjects.plugins.dnd.ObjectContent;
import org.nakedobjects.plugins.dnd.SubviewSpec;
import org.nakedobjects.plugins.dnd.Toolkit;
import org.nakedobjects.plugins.dnd.View;
import org.nakedobjects.plugins.dnd.ViewAxis;
import org.nakedobjects.plugins.dnd.viewer.view.simple.CompositeViewUsingBuilder;
import org.nakedobjects.plugins.dnd.viewer.view.simple.FieldErrorView;
import org.nakedobjects.runtime.context.NakedObjectsContext;


public class ObjectFieldBuilder extends AbstractViewBuilder {
    private static final Logger LOG = Logger.getLogger(ObjectFieldBuilder.class);
    private final SubviewSpec subviewDesign;

    public ObjectFieldBuilder(final SubviewSpec subviewDesign) {
        this.subviewDesign = subviewDesign;
    }

    @Override
    public void build(final View view) {
        Assert.assertEquals("ensure the view is the complete decorated view", view.getView(), view);

        final Content content = view.getContent();
        final NakedObject object = ((ObjectContent) content).getObject();

        LOG.debug("build view " + view + " for " + object);

        NakedObjectSpecification spec = object.getSpecification();
        Filter filter = NakedObjectAssociationFilters.dynamicallyVisible(
                NakedObjectsContext.getAuthenticationSession(), object);
        final NakedObjectAssociation[] flds = spec.getAssociations(filter);

        if (view.getSubviews().length == 0) {
            newBuild(view, object, flds);
        } else {
            updateBuild(view, object, flds);
        }
    }

    public View createCompositeView(final Content content, final CompositeViewSpecification specification, final ViewAxis axis) {
        return new CompositeViewUsingBuilder(content, specification, axis);
    }

    @Override
    public View decorateSubview(final View subview) {
        return subviewDesign.decorateSubview(subview);
    }

    private void newBuild(final View view, final NakedObject object, final NakedObjectAssociation[] flds) {
        LOG.debug("  as new build");
        for (int f = 0; f < flds.length; f++) {
            final NakedObjectAssociation field = flds[f];
            addField(view, object, field, f);
        }
    }

    private void addField(final View view, final NakedObject object, final NakedObjectAssociation field, int fieldNumber) {
        final View fieldView = createFieldView(view, object, fieldNumber, field);
        if (fieldView != null) {
            view.addView(decorateSubview(fieldView));
        }
    }

    private void updateBuild(final View view, final NakedObject object, final NakedObjectAssociation[] flds) {
        LOG.debug("  as update build");
        /*
         * 1/ To remove fields: look through views and remove any that don't exists in visible fields
         * 
         * 2/ From remaining views, check for changes as already being done, and replace if needed
         * 
         * 3/ Finally look through fields to see if there is no existing subview; and add one
         */

        View[] subviews = view.getSubviews();

        // remove views for fields that no longer exist
        outer: for (int i = 0; i < subviews.length; i++) {
            final FieldContent fieldContent = ((FieldContent) subviews[i].getContent());

            for (int j = 0; j < flds.length; j++) {
                final NakedObjectAssociation field = flds[j];
                if (fieldContent.getField() == field) {
                    continue outer;
                }
            }
            view.removeView(subviews[i]);
        }

        // update existing fields if needed
        subviews = view.getSubviews();
        for (int i = 0; i < subviews.length; i++) {
            final View subview = subviews[i];
            final NakedObjectAssociation field = ((FieldContent) subview.getContent()).getField();
            final NakedObject value = field.get(object);

            if (field.isOneToManyAssociation()) {
                subview.update(value);
            } else if (field.isOneToOneAssociation()) {
                final NakedObject existing = subview.getContent().getNaked();

                // if the field is parseable then it may have been modified; we need to replace what was
                // typed in with the actual title.
                if (!field.getSpecification().isParseable()) {
                    final boolean changedValue = value != existing;
                    final boolean isDestroyed = existing != null && existing.getResolveState().isDestroyed();
                    if (changedValue || isDestroyed) {
                        View fieldView;
                        fieldView = createFieldView(view, object, i, field);
                        if (fieldView != null) {
                            view.replaceView(subview, decorateSubview(fieldView));
                        } else {
                            view.addView(new FieldErrorView("No field for " + value));
                        }
                    }
                } else {
                    if (NakedObjectUtils.exists(value) && !NakedObjectUtils.wrappedEqual(value, existing)) {
                        final View fieldView = createFieldView(view, object, i, field);
                        view.replaceView(subview, decorateSubview(fieldView));
                    } else {
                        subview.refresh();
                    }
                }
            } else {
                throw new UnknownTypeException(field.getName());
            }
        }

        // add new fields
        outer2: for (int j = 0; j < flds.length; j++) {
            final NakedObjectAssociation field = flds[j];
            for (int i = 0; i < subviews.length; i++) {
                final FieldContent fieldContent = ((FieldContent) subviews[i].getContent());
                if (fieldContent.getField() == field) {
                    continue outer2;
                }
            }
            addField(view, object, field, j);
        }
    }

    private View createFieldView(
            final View view,
            final NakedObject object,
            final int fieldNumber,
            final NakedObjectAssociation field) {
        if (field == null) {
            throw new NullPointerException();
        }

        if (field.isOneToOneAssociation()) {
            NakedObjectsContext.getPersistenceSession().resolveField(object, field);
        }

        final Content content1 = Toolkit.getContentFactory().createFieldContent(field, object);
        final View fieldView = subviewDesign.createSubview(content1, view.getViewAxis(), fieldNumber);
        return fieldView;
    }

}
// Copyright (c) Naked Objects Group Ltd.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy