/*
* 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;
import org.apache.log4j.Logger;
import com.webobjects.appserver.WOContext;
import com.webobjects.directtoweb.D2WContext;
import com.webobjects.directtoweb.ERD2WContext;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOUtilities;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.eocontrol.EOSortOrdering;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import er.extensions.foundation.ERXArrayUtilities;
/**
* <span class="en">Superclass for most of the custom edit components.</span>
* <span class="ja">カスタム編集可能コンポーネントのスーパークラス</span>
*/
public abstract class ERDCustomEditComponent extends ERDCustomComponent {
/**
* 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 = 2L;
/** logging support */
public final static Logger log = Logger.getLogger(ERDCustomEditComponent.class);
/**
* <span class="en">interface for all the keys used in this pages code</span>
* <span class="ja">このページで使用する全キーのインタフェース</span>
*/
public static interface Keys {
public static final String object = "object";
public static final String localContext = "localContext";
public static final String permissionToEdit = "permissionToEdit";
}
private NSArray _defaultSortOrderingsForDestinationEntity;
/**
* Public constructor
* @param context current context
*/
public ERDCustomEditComponent(WOContext context) {
super(context);
}
//////////////////////////////////////// Instance Methods ////////////////////////////////////////////////////////////
private EOEnterpriseObject object;
protected EOEditingContext editingContext;
public Object objectPropertyValue() {
return objectKeyPathValue();
}
public void setObjectPropertyValue(Object newValue) {
setObjectKeyPathValue(newValue);
}
public Object objectKeyPathValue() {
return key() != null && object() != null ? object().valueForKeyPath(key()) : null;
}
public void setObjectKeyPathValue(Object newValue) {
if (key() != null && object() != null) object().takeValueForKeyPath(newValue,key());
}
/**
* <span class="ja">
* オブジェクトをセットします
*
* @param newObject - 新オブジェクト
* </span>
*/
public void setObject(EOEnterpriseObject newObject) {
object=newObject;
if (object!=null) {
// making sure the editing context stays alive
editingContext=object.editingContext();
}
}
/**
* <span class="ja">
* エンタプライス・オブジェクトを戻します。
*
* @return エンタプライス・オブジェクト
* </span>
*/
public EOEnterpriseObject object() {
if (object==null && !synchronizesVariablesWithBindings()) {
object=(EOEnterpriseObject)valueForBinding(Keys.object);
if (object!=null) {
/*
* making sure the editing context stays alive
* ...
* I don't think this is really necessary, but doing
* it to be consistent.
*/
editingContext=object.editingContext();
}
}
return object;
}
@Override
public boolean isStateless() { return false; }
@Override
public boolean synchronizesVariablesWithBindings() { return true; }
/** Used by stateful but non-synching subclasses */
@Override
public void resetCachedBindingsInStatefulComponent() {
super.resetCachedBindingsInStatefulComponent();
object = null;
editingContext = null;
_defaultSortOrderingsForDestinationEntity = null;
}
// Used by stateless subclasses
@Override
public void reset() {
super.reset();
object = null;
editingContext = null;
_defaultSortOrderingsForDestinationEntity = null;
}
// Defaults to true when not used in a D2W component. In the rules the default is false.
public boolean permissionToEdit() {
return hasBinding(Keys.permissionToEdit) ? booleanValueForBinding(Keys.permissionToEdit) : true;
}
/**
* Computes the destination entity that we're editing. Hits the "destinationEntityName"
* rule.
*
* @return destination entity
*/
public EOEntity destinationEntity() {
final String destinationEntityName = (String)valueForBinding("destinationEntityName");
return destinationEntityName != null ? EOUtilities.entityNamed(object().editingContext(), destinationEntityName) : null;
}
/**
* Hits the destinationEntityName rule to get the destination entity. Grabs a private D2WContext, sets the
* destination entity and asks for the defaultSortOrdering rule.
*
* @return an array of sort orderings for the destination entity.
*/
public NSArray defaultSortOrderingsForDestinationEntity() {
if (_defaultSortOrderingsForDestinationEntity == null) {
final D2WContext context = ERD2WContext.newContext();
final NSArray sortOrderingDefinition;
final int sortOrderingDefinitionCount;
NSMutableArray sortOrderings = null;
int i = 0;
context.setEntity(destinationEntity());
sortOrderingDefinition = (NSArray)context.valueForKey("defaultSortOrdering");
sortOrderingDefinitionCount = sortOrderingDefinition != null ? sortOrderingDefinition.count() : 0;
while (i < sortOrderingDefinitionCount) {
final String key = (String)sortOrderingDefinition.objectAtIndex(i++);
final String selectorKey = (String)sortOrderingDefinition.objectAtIndex(i++);
final EOSortOrdering sortOrdering = new EOSortOrdering(key, ERXArrayUtilities.sortSelectorWithKey(selectorKey));
(sortOrderings != null ? sortOrderings : (sortOrderings = new NSMutableArray())).addObject(sortOrdering);
}
_defaultSortOrderingsForDestinationEntity = sortOrderings != null ? sortOrderings.immutableClone() : NSArray.EmptyArray;
}
return _defaultSortOrderingsForDestinationEntity;
}
}