Package er.directtoweb.components.relationships

Source Code of er.directtoweb.components.relationships.ERDEditOwnedRelationship$PostSaveDelegate

/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file.  */
package er.directtoweb.components.relationships;

import java.util.Enumeration;

import org.apache.log4j.Logger;

import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.directtoweb.D2W;
import com.webobjects.directtoweb.EditPageInterface;
import com.webobjects.directtoweb.NextPageDelegate;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModelGroup;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eoaccess.EOUtilities;
import com.webobjects.eocontrol.EOArrayDataSource;
import com.webobjects.eocontrol.EOClassDescription;
import com.webobjects.eocontrol.EODataSource;
import com.webobjects.eocontrol.EODetailDataSource;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.eocontrol.EOObjectStoreCoordinator;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSValidation;

import er.directtoweb.ERDirectToWeb;
import er.directtoweb.components.ERDCustomEditComponent;
import er.directtoweb.interfaces.ERDPickPageInterface;
import er.extensions.eof.ERXConstant;
import er.extensions.eof.ERXEC;
import er.extensions.eof.ERXEOControlUtilities;
import er.extensions.eof.ERXEnterpriseObject;

/////////////////////////////////////////////////////////////////////////////////
// Important D2W Keys:
//  showAddButton - boolean to tell component to show the add button
//  entityNamesForNewInstances - array of strings that detail which entities are to be created.
//  explanationComponentName - component that is used in the StringListPicker to explain what it is that they are picking.
//  additionalRelationshipKeys - key-value pairs of additional relationships that need to be set after the eo is created.
//  uiStyle - list style will use a D2WList, popup/radio/browser will use an ERToOneRelationship FIXME: add in ERToManyRelationship
//  listConfigurationName - optional key that is for the list configuration of the D2W component.
//  destinationDisplayKey - key used to denote what to display in the ERToOneRelationship
//  selectionListKey - key that denotes what to use as the dataSource for the ERToOneRelationship.
//  permissionToEdit - key that determines if the add and/or edit button are shown.
//  postCreateNextPageDelegateKey - key that allows you to get your own nextPageDelegate into the fray.
/////////////////////////////////////////////////////////////////////////////////

/**
* Crazy component.  Useful for editing/creating objects in an owned toOne or toMany relationship.  Even works with relationships to abstract entities.
*
* @binding showAddButton defaults=Boolean
* @binding key
* @binding object
* @binding listConfigurationName
* @binding entityNamesForNewInstances
* @binding explanationComponentName
* @binding uiStyle
* @binding destinationSortKey
* @binding destinationDisplayKey
* @binding selectionListKey
* @binding preRelationshipKeys
* @binding permissionToEdit defaults=Boolean
* @binding postRelationshipKeys
* @binding useForms defaults=Boolean
*/

public class ERDEditOwnedRelationship extends ERDCustomEditComponent {
  /**
   * Do I need to update serialVersionUID?
   * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
   * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
   */
  private static final long serialVersionUID = 1L;


    /** logging support */
    public final static Logger log = Logger.getLogger("er.directtoweb.components.ERDEditOwnedRelationship");

    protected EOEditingContext localContext;

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

    public ERDEditOwnedRelationship(WOContext c) {
        super(c);
    }

    @Override
    public void awake() {
        _selectionList = null;
    }

    public NSDictionary preRelationshipKeys() { return (NSDictionary)valueForBinding("preRelationshipKeys"); }
    public NSDictionary postRelationshipKeys() { return (NSDictionary)valueForBinding("postRelationshipKeys"); }
    public NSArray entityNamesForNewInstances() { return (NSArray)valueForBinding("entityNamesForNewInstances"); }
    public String explanationComponentName() { return (String)valueForBinding("explanationComponentName"); }
    public String listConfigurationName() { return (String)valueForBinding("listConfigurationName"); }
    public String selectionListKey() { return (String)valueForBinding("selectionListKey"); }
    public String postCreateNextPageDelegateKey() { return (String)valueForBinding("postCreateNextPageDelegateKey"); }
    public String errorMessage() { return hasBinding("noSelectionErrorMessage") ? (String)valueForBinding("noSelectionErrorMessage") : "";}

    public NSArray list() {
        // we need to put the list in a peer (for add/delete ops) or in a child if it's a new object
        NSArray initialArray = (NSArray) (selectionListKey()!=null ? object().valueForKeyPath(selectionListKey()) :
                                          objectKeyPathValue());
        NSArray result = null;
        if (initialArray != null) {
            localContext=((ERXEnterpriseObject)object()).isNewObject() ?
            ERXEC.newEditingContext(object().editingContext(), false) :
            ERXEC.newEditingContext(object().editingContext().parentObjectStore());
            result = EOUtilities.localInstancesOfObjects(localContext, initialArray);
        }
        return result != null ? result : ERXConstant.EmptyArray;
    }

    private EODetailDataSource _detailDataSource;
    public EODataSource detailDataSource() {
        if (_detailDataSource==null) {
            String relationshipKey=selectionListKey()!=null ? selectionListKey() : key();
            _detailDataSource=new EODetailDataSource(object().classDescription(), relationshipKey);
            _detailDataSource.qualifyWithRelationshipKey(relationshipKey, object());
        }
        return _detailDataSource;
    }

    public EORelationship entityRelationship() {
        EOEntity e = EOModelGroup.defaultGroup().entityNamed(object().entityName());
        EORelationship result=e.relationshipNamed(key());
        if (result==null)
            throw new RuntimeException("Could not find relationship for entity "+object().entityName()+" - "+key());
        return result;
    }

    public String relationshipEntityName() { return entityRelationship().destinationEntity().name(); }
    public boolean relationshipIsManditory() {return hasBinding("isMandatory") ? booleanValueForBinding("isMandatory") : entityRelationship().isMandatory(); }

    public EOEnterpriseObject item;

    private NSArray _selectionList;
    public NSArray selectionList() {
        if (_selectionList == null) {
            // Test if we have a binding for selectionListKey
            if (selectionListKey() != null)
                _selectionList = (NSArray)object().valueForKeyPath(selectionListKey());
            else
                _selectionList = ERXConstant.EmptyArray;
        }
        return _selectionList;
    }

    public EOArrayDataSource selectionDataSource() {
        EOArrayDataSource dataSource = new EOArrayDataSource(EOClassDescription.classDescriptionForEntityName(relationshipEntityName()), object().editingContext());
        dataSource.setArray(selectionList());
        return dataSource;
    }

    public CreateEOWithChoicesDelegate createEODelegate() {
        return new CreateEOWithChoicesDelegate();
    }

    public WOComponent add() {
        WOComponent result = null;
        clearValidationFailed();
        CreateEOWithChoicesDelegate createEOWithChoices = createEODelegate();
        createEOWithChoices.object=object();
        createEOWithChoices.key=key();
        createEOWithChoices.followPage=context().page();
        createEOWithChoices.preRelationshipKeys=preRelationshipKeys();
        createEOWithChoices.postRelationshipKeys=postRelationshipKeys();
        createEOWithChoices.postCreateNextPageDelegateKey = postCreateNextPageDelegateKey();
        if (entityNamesForNewInstances() == null || entityNamesForNewInstances().count() == 0) {
            createEOWithChoices.entityNameForNewInstances=relationshipEntityName();
        } else if (entityNamesForNewInstances().count() == 1) {
            createEOWithChoices.entityNameForNewInstances=(String)entityNamesForNewInstances().objectAtIndex(0);
        } else {
            String pickTypePageConfiguration = null;
            if (hasBinding("pickTypePageConfiguration"))
                pickTypePageConfiguration = (String)valueForBinding("pickTypePageConfiguration");
            else
                pickTypePageConfiguration = "SelectPickType" + relationshipEntityName();
            ERDPickPageInterface ppi = (ERDPickPageInterface)D2W.factory().pageForConfigurationNamed(pickTypePageConfiguration, session());
            ppi.setNextPageDelegate(createEOWithChoices);
            ppi.setCancelPage(context().page());
            NSMutableArray choices = new NSMutableArray();
            for (Enumeration e = entityNamesForNewInstances().objectEnumerator(); e.hasMoreElements();) {
                String entityName = (String)e.nextElement();
                String displayNameForEntity = (String)ERDirectToWeb.d2wContextValueForKey("displayNameForEntity", entityName, null);
                if (entityName != null && displayNameForEntity != null) {
                    choices.addObject(new EOCreationMultipleChoice(displayNameForEntity, entityName));
                }
            }
            ppi.setChoices(choices);
            result = (WOComponent)ppi;
        }
        return result != null ? result : createEOWithChoices.nextPage();
    }

    public WOComponent edit() {
        EOEnterpriseObject eo = (EOEnterpriseObject)objectKeyPathValue();
        EditPageInterface epi = null;
        if (eo == null) {
            parent().validationFailedWithException(new NSValidation.ValidationException(errorMessage()),objectPropertyValue(), key());
        } else {
            String editConfigurationName = (String)ERDirectToWeb.d2wContextValueForKey("editConfigurationName", eo.entityName());
            epi = (EditPageInterface)D2W.factory().pageForConfigurationNamed(editConfigurationName, session());
            epi.setNextPage(context().page());
            if (((ERXEnterpriseObject)eo).isNewObject())
                localContext = ERXEC.newEditingContext(object().editingContext(), false);
            else
                localContext = ERXEC.newEditingContext(object().editingContext().parentObjectStore());
            epi.setObject(EOUtilities.localInstanceOfObject(localContext, eo));
            localContext.hasChanges();
        }
        return (WOComponent)epi;
    }

    static class CreateEOWithChoicesDelegate implements NextPageDelegate {
        protected String entityNameForNewInstances;
        protected String currentPageConfiguration;
        protected String postCreateNextPageDelegateKey = null;
        protected String key;
        protected EOEnterpriseObject object;
        protected EOEditingContext localContext;
        protected NSDictionary preRelationshipKeys, postRelationshipKeys;
        protected WOComponent followPage;
        protected NextPageDelegate postCreateNextPageDelegate = null;

        public WOComponent nextPage(WOComponent sender) {
            //entityNameForNewInstances = (String)sender.valueForKey("entityNameForNewInstances");
            entityNameForNewInstances =
            ((EOCreationMultipleChoice)((ERDPickPageInterface)sender).selectedObjects().objectAtIndex(0)).entityName;
            if (log.isDebugEnabled())
                log.debug("Creating "+entityNameForNewInstances);
            if (postCreateNextPageDelegateKey != null) {
                postCreateNextPageDelegate = (NextPageDelegate)sender.valueForKeyPath(postCreateNextPageDelegateKey);
            }
            return nextPage();
        }

        public WOComponent nextPage() {
            EOEnterpriseObject newEO = createEO();
            NSDictionary extraValues=currentPageConfiguration!=null ? new NSDictionary(currentPageConfiguration, "pageConfiguration") : null;
            String createPageConfigurationName = (String)ERDirectToWeb.d2wContextValueForKey("createConfigurationName",
                                                                                             entityNameForNewInstances,
                                                                                             extraValues);
            if (log.isDebugEnabled())
                log.debug("Create Page Config: " + createPageConfigurationName + " for entity: " + entityNameForNewInstances+" - "+extraValues);
            EditPageInterface epi = (EditPageInterface)D2W.factory().pageForConfigurationNamed(createPageConfigurationName,followPage.session());
            epi.setObject(newEO);
            if (postCreateNextPageDelegate == null) {
                ERDEditOwnedRelationship.PostSaveDelegate postSaveDelegate = new PostSaveDelegate();
                postSaveDelegate.postRelationshipKeys=postRelationshipKeys;
                postSaveDelegate.object=object;
                postSaveDelegate.key=key;
                postSaveDelegate.savedObject=newEO;
                postSaveDelegate.localContext=localContext;
                postSaveDelegate.followPage=followPage;
                epi.setNextPageDelegate(postSaveDelegate);
            } else {
                epi.setNextPageDelegate(postCreateNextPageDelegate);
            }
            return (WOComponent)epi;
        }

        public EOEnterpriseObject createEO() {
            // The relationship will be set in the PostSaveDelegate if object is a new eo, ie ok to use a peer context.
            if (object!=null && !(object.editingContext().parentObjectStore() instanceof EOObjectStoreCoordinator)) {
                log.warn("Newly created object is in an editing context that will not save to the database");
            }
            localContext = ERXEC.newEditingContext(object.editingContext().parentObjectStore());
            if (log.isDebugEnabled()) log.debug("Creating "+entityNameForNewInstances);
            EOEnterpriseObject newEO = ERXEOControlUtilities.createAndInsertObject(localContext, entityNameForNewInstances);
            // If the object already exists, then hookup the relationship, if not do it after the object is saved.
            if (!((ERXEnterpriseObject)object).isNewObject()) {
                EOEnterpriseObject localEO = EOUtilities.localInstanceOfObject(localContext, object);
                if (localEO != null)
                    localEO.addObjectToBothSidesOfRelationshipWithKey(newEO, key);
            }
            if (preRelationshipKeys != null) {
                for(Enumeration e = preRelationshipKeys.allKeys().objectEnumerator(); e.hasMoreElements();) {
                    String relationshipKey = (String)e.nextElement();
                    String objectKeyPath = (String)preRelationshipKeys.objectForKey(relationshipKey);
                    EOEnterpriseObject localObject = EOUtilities.localInstanceOfObject(localContext, (EOEnterpriseObject)object.valueForKeyPath(objectKeyPath));
                    localObject.addObjectToBothSidesOfRelationshipWithKey(newEO, relationshipKey);
                }
            }
            localContext.hasChanges(); // Make sure the EC survives.
            return newEO;
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Delegate Explanation:
    // This delegate is used to make sure that the object makes it to the database, ie if the user was in a childEC when they
    // hit the edit button or add button, then the change would only be propogated to the session's ec not to the db
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static class PostSaveDelegate implements NextPageDelegate {
        NSDictionary postRelationshipKeys;
        EOEnterpriseObject object;
        EOEnterpriseObject savedObject;
        EOEditingContext localContext;
        WOComponent followPage;
        String key;

        public WOComponent nextPage(WOComponent sender) {
            // If cancel is clicked the ec will be reverted which will set the ec on the inserted object to null
            if (savedObject.editingContext() != null)
                postProcessing();
            return followPage;
        }

        public void postProcessing() {
            if (object != null && savedObject != null && key != null) {
                EOEnterpriseObject localEO = EOUtilities.localInstanceOfObject(object.editingContext(), savedObject), localObject;
                // because this might be null, an array, or an EO
                if ((object.valueForKey(key) != null)&&(object.valueForKey(key) instanceof NSArray)&&(!((NSArray)object.valueForKey(key)).containsObject(localEO)))
                    object.addObjectToBothSidesOfRelationshipWithKey(localEO, key);
                if (object.valueForKey(key) == null)
                    object.addObjectToBothSidesOfRelationshipWithKey(localEO, key);
                if (postRelationshipKeys != null) {
                    for(Enumeration e = postRelationshipKeys.allKeys().objectEnumerator(); e.hasMoreElements();) {
                        String relationshipKey = (String)e.nextElement();
                        String objectKeyPath = (String)postRelationshipKeys.objectForKey(relationshipKey);
                        if (objectKeyPath.equals("this")) {
                            localObject = localEO;
                        } else {
                            localObject = (EOEnterpriseObject)localEO.valueForKeyPath(objectKeyPath);
                        }
                        localObject.addObjectToBothSidesOfRelationshipWithKey(savedObject, relationshipKey);
                    }
                }
            }
        }
    }

    public String noSelectionString() {
        return hasBinding("noSelectionString") ? (String)valueForBinding("noSelectionString"):"- none -";
    }

    public static class EOCreationMultipleChoice {

        public String displayName, entityName;

        public EOCreationMultipleChoice(String displayName, String entityName) {
            this.displayName = displayName;
            this.entityName = entityName;
        }
        @Override
        public String toString() { return displayName; }
    }

    public boolean useForms() { return booleanValueForBinding("useForms"); }
    public boolean doNotUseForm() { return !useForms(); }
}
TOP

Related Classes of er.directtoweb.components.relationships.ERDEditOwnedRelationship$PostSaveDelegate

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.