//
// ERDDefaultsEmbeddedAssignment.java
// Project ERDirectToWeb
//
// Created by ak on Tue Apr 23 2002
//
package er.directtoweb.assignments.defaults;
import org.apache.log4j.Logger;
import com.webobjects.directtoweb.D2WContext;
import com.webobjects.directtoweb.KeyValuePath;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModelGroup;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.eocontrol.EOKeyValueUnarchiver;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import er.directtoweb.assignments.ERDAssignment;
import er.extensions.foundation.ERXStringUtilities;
import er.extensions.localization.ERXLocalizer;
/**
* This assignment calculates default values for
* embedded page configurations.
*/
// CHECKME ak I'm not sure that this is a value add anymore
// A better way to create embedded page configurations is to create a rule like:
// propertyKey = "studios" => listPageConfiguration = "ListEmbeddedStudios"
// propertyKey = "studios" => componentName = "ERDList"
// pageConfiguration = "ListEmbeddedStudios" => displayPropertyKeys = (name, @sum.movies.revenue)
public class ERDDefaultsEmbeddedAssignment extends ERDAssignment {
/**
* 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 */
static final Logger log = Logger.getLogger(ERDDefaultsEmbeddedAssignment.class);
/** holds the array of dependent keys */
public static final NSArray _DEPENDENT_KEYS=new NSArray(new String[] {"embeddedEntityName", "object.entityName", "propertyKey", "pageConfiguration"});
/**
* Static constructor required by the EOKeyValueUnarchiver
* interface. If this isn't implemented then the default
* behavior is to construct the first super class that does
* implement this method. Very lame.
* @param eokeyvalueunarchiver to be unarchived
* @return decoded assignment of this class
*/
// ENHANCEME: Only need one of these per value()
public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver eokeyvalueunarchiver) {
ERDAssignment.logDeprecatedMessage(ERDDefaultsEmbeddedAssignment.class, ERDDefaultConfigurationNameAssignment.class);
return new ERDDefaultsEmbeddedAssignment (eokeyvalueunarchiver);
}
/**
* Public constructor
* @param u key-value unarchiver used when unarchiving
* from rule files.
*/
public ERDDefaultsEmbeddedAssignment (EOKeyValueUnarchiver u) { super(u); }
/**
* Public constructor
* @param key context key
* @param value of the assignment
*/
public ERDDefaultsEmbeddedAssignment (String key, Object value) { super(key,value); }
/**
* Implementation of the {@link er.directtoweb.assignments.ERDComputingAssignmentInterface}. This
* assignment depends upon the context keys: "propertyKey", "object.entityName",
* and "embeddedEntityName". This array of keys is used when constructing the
* significant keys for the passed in keyPath.
* @param keyPath to compute significant keys for.
* @return array of context keys this assignment depends upon.
*/
public NSArray dependentKeys(String keyPath) {
return _DEPENDENT_KEYS;
}
/**
* Gets the localizer for the current context. Implementation
* wise all this method does is get the current session from
* the context and then calls <code>localizerForSession</code>
* off of {@link ERXLocalizer}.
* @param c a D2W context
* @return localizer for the session stored in the context.
*/
@Override
public ERXLocalizer localizerForContext(D2WContext c) {
return ERXLocalizer.currentLocalizer();
}
/**
* Calculates and returns the default embedded entity
* display name. The results are localized.
* @param c current context
* @return default localized embedded entity name.
*/
public String defaultEmbeddedEntityDisplayName(D2WContext c) {
String value = ERXStringUtilities.displayNameForKey((String)c.valueForKey("embeddedEntityName"));
String result = (String)ERXLocalizer.currentLocalizer().valueForKey(value);
if(result == null) {
result = value;
}
return result;
}
/**
* Calculates the default embedded display property keys for a
* given context. Implementation wise this method uses the
* embedded entity to determine what all of the class properties
* are minus all of the relationship keys.
* @param c current D2W context
* @return array of display keys for the current embedded entity.
*/
public NSArray defaultEmbeddedDisplayPropertyKeys(D2WContext c) {
String entityName = (String)c.valueForKey("embeddedEntityName");
if(entityName != null) {
// FIXME: Should try for the 'object' in the context and use the
// model group from the object's ec.
EOEntity e = EOModelGroup.defaultGroup().entityNamed(entityName);
log.debug("embeddedEntityName = " + entityName);
NSMutableArray classProperties = e.classPropertyNames().mutableClone();
NSArray relationships = (NSArray)e.relationships().valueForKey("name");
classProperties.removeObjectsInArray(relationships);
return classProperties.immutableClone();
}
return NSArray.EmptyArray;
}
/**
* Calculates the default embedded entity name using the
* current object and propertyKey.
* @param c current context
* @return name of the entity pointed to by the propertyKey
* off of the object in the context.
*/
// CHECKME: Should just be able to use 'smartRelationship.destinationEntity.name'
public Object defaultEmbeddedEntityName(D2WContext c) {
if(c.valueForKeyPath("propertyKey") == null && c.entity() != null) {
return c.entity().name();
}
Object result = c.valueForKeyPath("smartRelationship.destinationEntity.name");
if(result == null) {
Object rawObject=c.valueForKey("object");
String propertyKey=c.propertyKey();
if (rawObject!=null && rawObject instanceof EOEnterpriseObject && propertyKey != null) {
EOEnterpriseObject object=(EOEnterpriseObject)rawObject;
EOEnterpriseObject lastEO=object;
if (propertyKey.indexOf(".")!=-1) {
String partialKeyPath=KeyValuePath.keyPathWithoutLastProperty(propertyKey);
Object rawLastEO=object.valueForKeyPath(partialKeyPath);
lastEO=rawLastEO instanceof EOEnterpriseObject ? (EOEnterpriseObject)rawLastEO : null;
}
if (lastEO!=null) {
// FIXME: Should be using the model group from the ec of the lastEO.
EOEntity entity=EOModelGroup.defaultGroup().entityNamed(lastEO.entityName());
String lastKey=KeyValuePath.lastPropertyKeyInKeyPath(propertyKey);
result=entity.relationshipNamed(lastKey);
}
}
if (result==null) {
result=c.relationship();
log.warn(propertyKey + "-" + rawObject);
}
if (result != null)
result = ((EORelationship)result).destinationEntity().name();
}
return result;
}
/**
* Calculates and returns the default embedded list page
* configuration to be used for embedded list pages.
* @param c current context
* @return page configuration of the form: "ListEmbedded" + the
* the value of the current embeddedEntityname.
*/
public String defaultEmbeddedListPageConfiguration(D2WContext c) {
String result = "ListEmbedded" + c.valueForKey("embeddedEntityName");
return result;
}
/**
* Calculates and returns the default embedded inspect page
* configuration to be used for embedded inspect pages.
* @param c current context
* @return page configuration of the form: "InspectEmbedded" + the
* the value of the current embeddedEntityname.
*/
public String defaultEmbeddedInspectPageConfiguration(D2WContext c) {
return "InspectEmbedded" + c.valueForKey("embeddedEntityName");
}
/**
* Calculates and returns the default embedded edit page
* configuration to be used for embedded edit pages.
* @param c current context
* @return page configuration of the form: "EditEmbedded" + the
* the value of the current embeddedEntityname.
*/
public String defaultEmbeddedEditPageConfiguration(D2WContext c) {
return "EditEmbedded" + c.valueForKey("embeddedEntityName");
}
/**
* By default the key path being requested is used
* as the key to lookup the method to call on the
* ERDAssignment subclass. However in the case of this
* assignment we want to use the string value of the
* <code>value</code> of the assignment as the key to
* lookup the method. For example if value of this
* assignment is "foo", then when this assignment is
* fired the method <code>foo(D2WContext)</code> will
* be called.
* @param c current context
* @return key for method lookup, in this case the
* <code>value</code> of the assignment is returned.
*/
@Override
public String keyForMethodLookup(D2WContext c) {
return (String)value();
}
}