Package org.apache.isis.viewer.bdd.common.fixtures

Source Code of org.apache.isis.viewer.bdd.common.fixtures.SetUpObjectsPeer$AssociationVisitor

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*/
package org.apache.isis.viewer.bdd.common.fixtures;

import java.util.ArrayList;
import java.util.List;

import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.lang.StringUtils;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.viewer.bdd.common.AliasRegistry;
import org.apache.isis.viewer.bdd.common.CellBinding;
import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;

public class SetUpObjectsPeer extends AbstractFixturePeer {

    public static enum Mode {
        PERSIST, DO_NOT_PERSIST;

        public boolean isPersist() {
            return this == PERSIST;
        }
    }

    public static enum PropertyResult {
        ALIAS, NO_SUCH_PROPERTY, NOT_A_PROPERTY, OK;
        public boolean isOk() {
            return this == OK;
        }
    }

    public static enum SetUpObjectResult {
        OK, NO_ASSOCIATION, CLEARED, CANNOT_CLEAR("(cannot clear)"), CANNOT_SET("(cannot set"), CANNOT_PARSE("(cannot parse)"), UNKNOWN_REFERENCE("(unknown reference)");
        private String errorMessage;

        private SetUpObjectResult() {
            this(null);
        }

        private SetUpObjectResult(final String errorMessage) {
            this.errorMessage = errorMessage;
        }

        public boolean isHandled() {
            return !isError();
        }

        public boolean isError() {
            return errorMessage != null;
        }

        public String getErrorMessage() {
            return errorMessage;
        }
    }

    public interface AssociationVisitor {
        void visit(OneToOneAssociation association, int colNum);
    }

    private final ObjectSpecification spec;

    private final List<OneToOneAssociation> properties = new ArrayList<OneToOneAssociation>();
    private final CellBinding aliasBinding;
    private final SetUpObjectsPeer.Mode mode;

    private final List<String> cellTextList = new ArrayList<String>();
    private String alias;

    // ///////////////////////////////////////////////////////////////////////
    // constructor
    // ///////////////////////////////////////////////////////////////////////

    public SetUpObjectsPeer(final AliasRegistry aliasRegistry, final String className, final SetUpObjectsPeer.Mode mode, final CellBinding aliasBinding) {
        super(aliasRegistry, aliasBinding);

        this.spec = loadSpecIfValid(className);

        this.mode = mode;
        this.aliasBinding = aliasBinding;
    }

    private ObjectSpecification loadSpecIfValid(final String className) {
        try {
            return getSpecificationLoader().loadSpecification(className);
        } catch (final IsisException ex) {
            return null;
        }
    }

    public boolean isSpecOk() {
        return spec != null;
    }

    public List<OneToOneAssociation> getProperties() {
        return properties;
    }

    public CellBinding getAliasBinding() {
        return aliasBinding;
    }

    // ///////////////////////////////////////////////////////////////////////
    // header
    // ///////////////////////////////////////////////////////////////////////

    public PropertyResult definePropertyOrAlias(final String heading, final int colNum) {

        OneToOneAssociation otoa = null;

        try {
            final int aliasColumn = getAliasBinding().getColumn();
            if (colNum == aliasColumn) {
                return PropertyResult.ALIAS;
            }

            ObjectAssociation association = null;
            try {
                final String memberName = StringUtils.memberIdFor(heading);
                association = spec.getAssociation(memberName);
            } catch (final Exception ex) {
                return PropertyResult.NO_SUCH_PROPERTY;
            }

            if (!association.isOneToOneAssociation()) {
                return PropertyResult.NOT_A_PROPERTY;
            }

            otoa = (OneToOneAssociation) association;

            return PropertyResult.OK;
        } finally {
            // add an association if OK, add null otherwise
            getProperties().add(otoa);
        }
    }

    // ///////////////////////////////////////////////////////////////////////
    // each row
    // ///////////////////////////////////////////////////////////////////////

    /**
     * Used by Concordion only.
     *
     * <p>
     * FitNesse, on the other hand, uses a more fine-grained approach, calling
     * the underlying methods.
     */
    public void createObject() throws ScenarioBoundValueException {
        final ObjectAdapter adapter = createInstance();

        for (int colNum = 0; colNum < getProperties().size(); colNum++) {
            final SetUpObjectResult result = setUpProperty(adapter, colNum);

            if (!result.isHandled()) {
                final CellBinding cellBinding = getCellBindings().get(colNum);
                throw ScenarioBoundValueException.current(cellBinding, result.getErrorMessage());
            }
        }

        persistIfNecessary(adapter);
        alias(adapter);
        resetForNextObject();
    }

    public void resetForNextObject() {
        cellTextList.clear();
        this.alias = null;
    }

    public ObjectAdapter createInstance() {
        if (spec == null) {
            return null;
        }
        return getPersistenceSession().createTransientInstance(spec);
    }

    public SetUpObjectResult setUpProperty(final ObjectAdapter adapter, final int colNum) {

        final OneToOneAssociation association = getProperties().get(colNum);
        if (association == null) {
            return SetUpObjectResult.NO_ASSOCIATION;
        }

        final String cellText = cellTextList.get(colNum);

        // handle empty cell as null
        if (cellText == null || cellText.length() == 0) {

            // use clear facet if available
            final PropertyClearFacet clearFacet = association.getFacet(PropertyClearFacet.class);

            if (clearFacet != null) {
                clearFacet.clearProperty(adapter);
                return SetUpObjectResult.CLEARED;
            }

            // use setter facet otherwise
            final PropertySetterFacet setterFacet = association.getFacet(PropertySetterFacet.class);

            if (setterFacet != null) {
                setterFacet.setProperty(adapter, null);
                return SetUpObjectResult.CLEARED;
            }

            return SetUpObjectResult.CANNOT_CLEAR;
        }

        // non-empty, will need a setter
        final PropertySetterFacet setterFacet = association.getFacet(PropertySetterFacet.class);
        if (setterFacet == null) {
            return SetUpObjectResult.CANNOT_SET;
        }

        final ObjectSpecification fieldSpecification = association.getSpecification();
        final ParseableFacet parseableFacet = fieldSpecification.getFacet(ParseableFacet.class);

        ObjectAdapter referencedAdapter = null;
        if (parseableFacet != null) {
            // handle as parseable value
            try {
                referencedAdapter = parseableFacet.parseTextEntry(adapter, cellText, null);
            } catch (final IllegalArgumentException ex) {
                return SetUpObjectResult.CANNOT_PARSE;
            }

        } else {
            // handle as reference to known object
            referencedAdapter = getAliasRegistry().getAliased(cellText);
            if (referencedAdapter == null) {
                return SetUpObjectResult.UNKNOWN_REFERENCE;
            }
        }

        setterFacet.setProperty(adapter, referencedAdapter);
        return SetUpObjectResult.OK;
    }

    public void persistIfNecessary(final ObjectAdapter adapter) {
        if (mode.isPersist()) {
            // xactn mgmt now done by PersistenceSession#makePersistent()
            // getTransactionManager().startTransaction();
            getPersistenceSession().makePersistent(adapter);
            // getTransactionManager().endTransaction();
        }
    }

    public void alias(final ObjectAdapter adapter) {
        final String alias = aliasFor(adapter);
        getAliasRegistry().aliasAs(alias, adapter);
    }

    public String aliasFor(final ObjectAdapter adapter) {
        if (alias != null) {
            return alias;
        } else {
            final String specShortName = StringUtils.lowerLeading(spec.getShortIdentifier());
            return getAliasRegistry().aliasPrefixedAs(specShortName, adapter);
        }
    }

    public void forEachAssociation(final AssociationVisitor visitor) {
        for (int colNum = 0; colNum < getProperties().size(); colNum++) {
            final OneToOneAssociation association = getProperties().get(colNum);
            if (association != null) {
                visitor.visit(association, colNum);
            }
        }
    }

    public boolean addPropertyValueOrAlias(final String propertyValue) {
        cellTextList.add(propertyValue);

        // capture alias if just added
        final int aliasColumn1based = getAliasBinding().getColumn() + 1;
        if (cellTextList.size() == aliasColumn1based) {
            alias = propertyValue;
        }

        return true;
    }

}
TOP

Related Classes of org.apache.isis.viewer.bdd.common.fixtures.SetUpObjectsPeer$AssociationVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.