/*
* 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.extensions.batching;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WODisplayGroup;
import com.webobjects.appserver.WOResponse;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSNotificationCenter;
import er.extensions.appserver.ERXDisplayGroup;
import er.extensions.components.ERXStatelessComponent;
import er.extensions.components._private.ERXWOForm;
import er.extensions.eof.ERXConstant;
import er.extensions.foundation.ERXThreadStorage;
/**
* Better batch navigation bar to page through display groups.
* <ul>
* <li>User typing null for either number of objects per batch or the page number</li>
* <li>When resetting the number of items per batch the page first page displayed would be the last page.</li>
* <li>Broadcasts a notification when the batch size changes</li>
* <li>Has go first/go last methods</li>
* <li>Has option to not clear the selection when paging, which WODisplayGroup does when calling displayNext()/displayPrevious()</li>
* <li>Broadcasts a notification when the batch size changes</li>
* <li>Can be used inside or outside of a <code>form</code></li>
* <li>Graphics can be easily configured</li>
* <li>Has localization support, both for static texts and the object count.</li>
* </ul>
*
* @binding d2wContext the D2W context that this component is in
* @binding displayGroup the WODisplayGroup that is being controlled
* @binding width the width of the navigation bar table (there is a minimum 500 pixel width if tableClass is not specified)
* @binding objectName the name of the type of object that is contained in the WODisplayGroup
* @binding border the border width of the navigation bar table
* @binding bgcolor the background color of the navigation bar table
* @binding textColor no longer used?
* @binding sortKeyList an NSArray of sort key paths that will be displayed in a popup button
* @binding tableClass the CSS class for the navigation table (overrides minimum 500 pixel width when set)
* @binding imageFramework the name of the framework that contains the navigation arrow images
* @binding leftArrowImage the name of the left navigation arrow image
* @binding rightArrowImage the name of the right navigation arrow image
* @binding clearSelection boolean that indicates if the selection should be reset on paging (default false)
*/
public class ERXBatchNavigationBar extends ERXStatelessComponent {
/**
* 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;
private static final Logger log = LoggerFactory.getLogger(ERXBatchNavigationBar.class);
/** Contains a string that names the notification posted when the batch size changes */
public final static String BatchSizeChanged = "BatchSizeChanged";
public boolean wasInForm;
private String _threadStorageKey;
/** Public constructor */
public ERXBatchNavigationBar(WOContext aContext) {
super(aContext);
}
@Override
public void awake() {
super.awake();
wasInForm = context().isInForm();
_threadStorageKey = "ERXBatchNavigationBar_numberOfObjectsPerBatch_" + context().elementID();
}
@Override
public void reset() {
super.reset();
_displayGroup = null;
_threadStorageKey=null;
}
@Override
public void appendToResponse(WOResponse response, WOContext context) {
// set the numberOfObjectsPerBatch
Number newNumberOfObjectsPerBatch = (Number) ERXThreadStorage.valueForKey(_threadStorageKey);
if (newNumberOfObjectsPerBatch != null && newNumberOfObjectsPerBatch.intValue() != displayGroup().numberOfObjectsPerBatch()) {
if (displayGroup()!=null) {
NSArray selection = selection();
log.debug("Setting db # of objects per batch to {}.", newNumberOfObjectsPerBatch);
displayGroup().setNumberOfObjectsPerBatch(newNumberOfObjectsPerBatch.intValue());
log.debug("The batch index is being set to 1.");
displayGroup().setCurrentBatchIndex(1);
clearSelection(selection);
}
Object d2wcontext=valueForBinding("d2wContext");
if (d2wcontext!=null) {
NSNotificationCenter.defaultCenter().postNotification("BatchSizeChanged",
ERXConstant.integerForInt(newNumberOfObjectsPerBatch.intValue()),
new NSDictionary(d2wcontext,"d2wContext"));
}
ERXThreadStorage.takeValueForKey(null, _threadStorageKey);
}
if (displayGroup() != null && ! displayGroup().hasMultipleBatches()) {
if (currentBatchIndex() != 0)
setCurrentBatchIndex(ERXConstant.ZeroInteger);
}
super.appendToResponse(response, context);
}
private WODisplayGroup _displayGroup;
public WODisplayGroup displayGroup() {
if (_displayGroup == null) {
_displayGroup = (WODisplayGroup)valueForBinding("displayGroup");
}
return _displayGroup;
}
public boolean hasObjectName() { return hasBinding("objectName"); }
public boolean hasSortKeyList() { return hasBinding("sortKeyList"); }
public int numberOfObjectsPerBatch() {
return displayGroup()!=null ? displayGroup().numberOfObjectsPerBatch() : 0;
}
public int currentBatchIndex() {
return displayGroup()!=null ? displayGroup().currentBatchIndex() : 0;
}
public void setCurrentBatchIndex(Number newValue) {
if (newValue!=null) {
if (displayGroup()!=null){
displayGroup().setCurrentBatchIndex(newValue.intValue());
log.debug("The batch index is being set to {}.", newValue.intValue());
}
}
}
public void setNumberOfObjectsPerBatch(Number newValue) {
ERXThreadStorage.takeValueForKey(newValue, _threadStorageKey);
}
public int filteredObjectsCount() {
WODisplayGroup dg=displayGroup();
if (dg instanceof ERXDisplayGroup) {
ERXDisplayGroup erxdg = (ERXDisplayGroup) dg;
return erxdg.filteredObjects().count();
}
int result=0;
EOQualifier q=dg.qualifier();
if (q!=null) {
result=EOQualifier.filteredArrayWithQualifier(dg.allObjects(),q).count();
} else {
result=dg.allObjects().count();
}
return result;
}
public int objectCount() {
return displayGroup().allObjects().count();
}
public String imageFramework() {
String imageFramework;
if (!hasBinding("imageFramework")) {
imageFramework = "JavaWOExtensions";
}
else {
imageFramework = (String)valueForBinding("imageFramework");
}
return imageFramework;
}
public String leftArrowImage() {
String leftArrowImageName;
if (!hasBinding("leftArrowImage")) {
leftArrowImageName = "lft-OSarw.gif";
}
else {
leftArrowImageName = (String)valueForBinding("leftArrowImage");
}
return leftArrowImageName;
}
public String rightArrowImage() {
String rightArrowImageName;
if (!hasBinding("rightArrowImage")) {
rightArrowImageName = "rt-OSarw.gif";
}
else {
rightArrowImageName = (String)valueForBinding("rightArrowImage");
}
return rightArrowImageName;
}
protected NSArray selection() {
return displayGroup().selectedObjects();
}
protected void clearSelection(NSArray selection) {
if(booleanValueForBinding("clearSelection", false)) {
displayGroup().setSelectedObjects(NSArray.EmptyArray);
} else {
// displayGroup().setSelectedObject(selection);
}
}
public WOComponent displayNextBatch() {
if (displayGroup() != null && displayGroup().numberOfObjectsPerBatch() != 0) {
NSArray selection = selection();
displayGroup().setCurrentBatchIndex(displayGroup().currentBatchIndex() + 1);
clearSelection(selection);
}
return context().page();
}
public WOComponent displayPreviousBatch() {
if (displayGroup() != null && displayGroup().numberOfObjectsPerBatch() != 0) {
NSArray selection = selection();
displayGroup().setCurrentBatchIndex(displayGroup().currentBatchIndex() - 1);
clearSelection(selection);
}
return context().page();
}
public WOComponent displayFirstBatch() {
if (displayGroup() != null && displayGroup().numberOfObjectsPerBatch() != 0) {
NSArray selection = selection();
displayGroup().setCurrentBatchIndex(1);
clearSelection(selection);
}
return context().page();
}
public WOComponent displayLastBatch() {
if (displayGroup() != null && displayGroup().numberOfObjectsPerBatch() != 0) {
NSArray selection = selection();
displayGroup().setCurrentBatchIndex(displayGroup().batchCount());
clearSelection(selection);
}
return context().page();
}
public String formTarget() {
if(wasInForm) {
return ERXWOForm.formName(context(), "EditForm") + ".target='_self';";
}
return null;
}
}