package er.reporting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOResponse;
import com.webobjects.eocontrol.EODataSource;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSNotification;
import com.webobjects.foundation.NSNotificationCenter;
import com.webobjects.foundation.NSPropertyListSerialization;
import com.webobjects.foundation.NSSelector;
import er.extensions.eof.ERXConstant;
import er.extensions.foundation.ERXAssert;
import er.extensions.foundation.ERXStringUtilities;
import er.extensions.foundation.ERXValueUtilities;
import er.grouping.DRReportModel;
/**
* Provides a quick way to set up a {@link WRReport}. Instead of binding all those keys,
* you can simply set up the components via a dictionary.
* There are several modes you can supply the data:
* <dl>
* <dt>Via a model dictionary, a path to a model dictionary or a string defining a model dictionary</dt>
* <dd>A model dictionary is defined by the keys <code>GroupDef</code> and <code>AttributeDef</code>.</dd>
* <dt>Via a report dictionary.</dt>
* <dd>A report dictionary is a dictionary with the key <code>model</code> defining
* a model dictionary, and a key <code>settings</code>, defining the values normally bound
* to the report, like <code>shouldShowNavigation</code> and the like.</dd>
* </dl>
* Additionally, you can bind all values defining the report to the component itself, overriding
* the values in the dictionary.
*/
public class WRQuickReport extends WOComponent {
private static final Logger log = LoggerFactory.getLogger(WRQuickReport.class);
protected DRReportModel _model;
protected NSDictionary _modelDictionary;
protected NSDictionary _reportDictionary;
protected NSDictionary _settingsDictionary;
protected NSArray _objects;
protected NSArray _attributeArray;
protected NSArray _criteriaArray;
protected String _componentName;
public WRQuickReport(WOContext c){
super(c);
NSSelector synchModelSelector = new NSSelector("synchModel", ERXConstant.NotificationClassArray);
NSNotificationCenter.defaultCenter().addObserver(this, synchModelSelector, DRReportModel.DRReportModelUpdateNotification, null);
NSNotificationCenter.defaultCenter().addObserver(this, synchModelSelector, DRReportModel.DRReportModelRebuildNotification, null);
}
public String reportComponentName() {
String name = (String) valueForBinding("reportComponentName");
if(name == null) {
name = "WRReport";
}
return name;
}
public void synchModel(NSNotification notification) {
if(_model == notification.object() && !dontSyncModel()) {
DRReportModel model = _model;
reset();
if(model != null) {
model.initWithRawRecords(objects(), criteriaArray(), attributeArray());
}
log.info("Model was re-set.");
//reset();
}
}
public String componentName() {
if(_componentName == null) {
_componentName = (String)valueForBinding("reportComponentName");
if(_componentName == null) {
_componentName = "WRRecordGroup";
}
}
return _componentName;
}
@Override
public void finalize() throws Throwable {
NSNotificationCenter.defaultCenter().removeObserver(this);
super.finalize();
}
@Override
public void awake() {
super.awake();
_objects = null;
if(false) {
_model = null;
_modelDictionary = null;
_componentName = null;
_reportDictionary = null;
_settingsDictionary = null;
_attributeArray = null;
_criteriaArray = null;
_objects = null;
}
}
@Override
public void reset() {
super.reset();
_model = null;
_modelDictionary = null;
_reportDictionary = null;
_settingsDictionary = null;
_attributeArray = null;
_criteriaArray = null;
_objects = null;
_componentName = null;
}
@Override
public boolean synchronizesVariablesWithBindings() {
return false;
}
public String plistString() {
if (super.hasBinding("plistString")) {
return (String)super.valueForBinding("plistString");
} else {
if (hasBinding("pathString")) {
String p = (String)super.valueForBinding("pathString");
log.debug("p: {}", p);
String plist = ERXStringUtilities.stringWithContentsOfFile(p);
log.debug("plist: {}", plist);
return plist;
}
}
return null;
}
public NSDictionary modelDictionary() {
if(_modelDictionary == null) {
if (super.hasBinding("modelDictionary")) {
_modelDictionary = (NSDictionary)super.valueForBinding("modelDictionary");
} else {
String plistString = plistString();
if (plistString != null) {
_modelDictionary = (NSDictionary)NSPropertyListSerialization.propertyListFromString(plistString);
} else {
_modelDictionary = (NSDictionary)reportDictionary().objectForKey("model");
if(_modelDictionary == null) {
log.warn("No modelDictionary found!");
_modelDictionary = NSDictionary.EmptyDictionary;
}
}
log.debug("plistString: {}", plistString);
log.debug( "modelDict: {}", _modelDictionary);
}
}
return _modelDictionary;
}
public NSDictionary reportDictionary() {
if(_reportDictionary == null) {
if (super.hasBinding("reportDictionary")) {
_reportDictionary = (NSDictionary)super.valueForBinding("reportDictionary");
} else {
_reportDictionary = NSDictionary.EmptyDictionary;
}
}
return _reportDictionary;
}
public NSDictionary settingsDictionary() {
if(_settingsDictionary == null) {
_settingsDictionary = (NSDictionary)reportDictionary().objectForKey("settings");
if(_settingsDictionary == null) {
_settingsDictionary = NSDictionary.EmptyDictionary;
}
}
return _settingsDictionary;
}
public NSArray criteriaArray() {
if(_criteriaArray == null) {
if (super.hasBinding("criteriaArray")) {
_criteriaArray = (NSArray)super.valueForBinding("criteriaArray");
} else {
NSArray rawArray = (NSArray)modelDictionary().objectForKey("GroupDef");
_criteriaArray = DRReportModel.masterCriteriaList(rawArray);
}
ERXAssert.DURING.notNull("criteriaArray", _criteriaArray);
}
return _criteriaArray;
}
public NSArray attributeArray() {
if(_attributeArray == null) {
if (super.hasBinding("attributeArray")) {
_attributeArray = (NSArray)super.valueForBinding("attributeArray");
} else {
NSArray rawArray = (NSArray)modelDictionary().objectForKey("AttributeDef");
_attributeArray = DRReportModel.attributeList(rawArray);
}
ERXAssert.DURING.notNull("attributeArray", _attributeArray);
}
return _attributeArray;
}
public DRReportModel model() {
if (_model == null) {
if(super.hasBinding("model")) {
log.info("pulling model from bindings");
_model = (DRReportModel)super.valueForBinding("model");
}
if(_model == null) {
log.info("creating model from definition");
_model = DRReportModel.withRawRecordsCriteriaListAttributeList(objects(), criteriaArray(), attributeArray());
}
if(super.hasBinding("model")) {
if(super.canSetValueForBinding("model")) {
log.info("setValueForBinding model: DRReportModel@{}", _model.hashCode());
super.setValueForBinding(_model, "model");
}
}
if(log.isDebugEnabled()) {
log.debug( "model(): DRReportModel@{}", _model.hashCode());
log.debug( "model().records(): {}", _model.records().count());
}
}
return _model;
}
public NSArray objects() {
if(_objects == null) {
if(super.hasBinding("objects")) {
_objects = (NSArray)super.valueForBinding("objects");
} else {
if(super.hasBinding("dataSource")) {
EODataSource ds = (EODataSource)super.valueForBinding("dataSource");
ERXAssert.DURING.notNull("dataSource", ds);
_objects = ds.fetchObjects();
}
}
}
return _objects;
}
@Override
public boolean hasBinding(String name) {
boolean result = super.hasBinding(name) || settingsDictionary().objectForKey(name) != null;
log.debug("hasBinding: {} : {}", name, result);
return result;
}
@Override
public Object valueForBinding(String name) {
Object result;
if(super.hasBinding(name)) {
result = super.valueForBinding(name);
} else {
result = settingsDictionary().objectForKey(name);
}
log.debug("valueForBinding: {} : {}", name, result);
return result;
}
public boolean dontSyncModel() {
return ERXValueUtilities.booleanValue(valueForBinding("dontSyncModel"));
}
@Override
public void appendToResponse(WOResponse r, WOContext c) {
super.appendToResponse(r, c);
//reset();
}
}