package org.nightlabs.jfire.trade.admin.ui.editor;
import javax.jdo.FetchPlan;
import javax.jdo.JDOHelper;
import org.nightlabs.base.ui.entity.editor.EntityEditor;
import org.nightlabs.base.ui.entity.editor.EntityEditorPageController;
import org.nightlabs.jdo.NLJDOHelper;
import org.nightlabs.jfire.accounting.gridpriceconfig.FormulaPriceConfig;
import org.nightlabs.jfire.base.JFireEjb3Factory;
import org.nightlabs.jfire.base.login.ui.Login;
import org.nightlabs.jfire.store.NestedProductTypeLocal;
import org.nightlabs.jfire.store.ProductType;
import org.nightlabs.jfire.store.ProductTypeLocal;
import org.nightlabs.jfire.store.StoreManagerRemote;
import org.nightlabs.jfire.store.id.ProductTypeID;
import org.nightlabs.jfire.trade.LegalEntity;
import org.nightlabs.jfire.trade.admin.ui.resource.Messages;
import org.nightlabs.progress.ProgressMonitor;
import org.nightlabs.progress.SubProgressMonitor;
/**
* A base {@link EntityEditorPageController} for ProductType detail pages.
* It provides default fetch-groups and delegates its work to the methods:
* {@link #retrieveProductType(ProgressMonitor)} and {@link #storeProductType(ProductType, ProgressMonitor)}.
* Additionally it manages the retrieval and storage of the sale-access-control properties
* of the given ProductType directly with the {@link StoreManager}.
*
* @author Daniel.Mazurek [at] NightLabs [dot] de
* @author Alexander Bieber <!-- alex [AT] nightlabs [DOT] de -->
*/
public abstract class AbstractProductTypeDetailPageController<ProductTypeType extends ProductType>
extends AbstractProductTypePageController<ProductTypeType>
implements IProductTypeDetailPageController<ProductTypeType>
{
/**
* Create a new {@link AbstractProductTypeDetailPageController}.
* @param editor The editor.
*/
public AbstractProductTypeDetailPageController(EntityEditor editor) {
super(editor);
}
/**
* Create a new {@link AbstractProductTypeDetailPageController}.
* @param editor The editor.
* @param startBackgroundLoading Whether to start background loading.
*/
public AbstractProductTypeDetailPageController(EntityEditor editor,
boolean startBackgroundLoading) {
super(editor, startBackgroundLoading);
}
/**
* The default fetch-groups to detach a ProductType for a ProductType detail page.
* This can be used or should be extended by subclasses.
*/
public static final String[] FETCH_GROUPS_DEFAULT = new String[] {
FetchPlan.DEFAULT,
ProductType.FETCH_GROUP_NAME,
ProductType.FETCH_GROUP_FIELD_METADATA_MAP,
ProductType.FETCH_GROUP_PRODUCT_TYPE_LOCAL,
ProductTypeLocal.FETCH_GROUP_NESTED_PRODUCT_TYPE_LOCALS,
ProductTypeLocal.FETCH_GROUP_FIELD_METADATA_MAP,
NestedProductTypeLocal.FETCH_GROUP_INNER_PRODUCT_TYPE,
NestedProductTypeLocal.FETCH_GROUP_PACKAGE_PRODUCT_TYPE,
ProductType.FETCH_GROUP_INNER_PRICE_CONFIG,
ProductType.FETCH_GROUP_PACKAGE_PRICE_CONFIG,
FormulaPriceConfig.FETCH_GROUP_PACKAGING_RESULT_PRICE_CONFIGS,
ProductType.FETCH_GROUP_OWNER,
ProductType.FETCH_GROUP_VENDOR,
LegalEntity.FETCH_GROUP_PERSON,
ProductType.FETCH_GROUP_EXTENDED_PRODUCT_TYPE,
ProductType.FETCH_GROUP_EXTENDED_PRODUCT_TYPE_ID,
ProductType.FETCH_GROUP_PRODUCT_TYPE_LOCAL,
ProductTypeLocal.FETCH_GROUP_LOCAL_ACCOUNTANT_DELEGATE,
ProductType.FETCH_GROUP_DELIVERY_CONFIGURATION
};
@Override
protected ProductTypeType retrieveEntity(ProgressMonitor monitor) {
monitor.beginTask(Messages.getString("org.nightlabs.jfire.trade.admin.ui.editor.AbstractProductTypeDetailPageController.loadProductTypeDetailMonitor.task.name"), 3); //$NON-NLS-1$
monitor.worked(1);
ProductTypeType productType = retrieveProductType(new SubProgressMonitor(monitor, 2));
saleAccessStatus = null;
monitor.done();
return productType;
}
@Override
protected ProductTypeType storeEntity(ProductTypeType productType, ProgressMonitor monitor) {
monitor.beginTask(Messages.getString("org.nightlabs.jfire.trade.admin.ui.editor.AbstractProductTypeDetailPageController.storeProductTypeDetailMonitor.task.name"), 5); //$NON-NLS-1$
monitor.worked(1);
// It is important that the two following lines are executed in this order.
// This way, the sale access is first modified, then the ProductType is stored *and* *retrieved*.
// This way the second call returns the correct newProductType and not one
// which is already outdated when storeSaleAccessControl(...) has been called. Marco.
storeSaleAccessControl(new SubProgressMonitor(monitor, 2));
ProductTypeType newProductType = storeProductType(productType, new SubProgressMonitor(monitor, 2));
monitor.done();
return newProductType;
}
/**
* Stores the given saleStatus properties to the actual ProductType using the {@link StoreManager}.
* @param saleStatus The status to apply.
*/
protected void storeSaleAccessControlProperties(ProductTypeSaleAccessStatus saleStatus)
{
try {
ProductType productType = getProductType();
ProductTypeID productTypeID = (ProductTypeID) JDOHelper.getObjectId(productType);
if (saleStatus == null)
return; // Not changed, nothing to save
boolean make_published = saleStatus.isPublished() && !productType.isPublished();
boolean make_confirmed = saleStatus.isConfirmed() && !productType.isConfirmed();
boolean make_saleable_true = saleStatus.isSaleable() && !productType.isSaleable();
boolean make_saleable_false = !saleStatus.isSaleable() && productType.isSaleable();;
boolean make_closed = saleStatus.isClosed() && !productType.isClosed();
StoreManagerRemote storeManager = JFireEjb3Factory.getRemoteBean(StoreManagerRemote.class, Login.getLogin().getInitialContextProperties());
if (make_published)
storeManager.setProductTypeStatus_published(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
if (make_confirmed)
storeManager.setProductTypeStatus_confirmed(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
if (make_saleable_true || make_saleable_false)
storeManager.setProductTypeStatus_saleable(productTypeID, make_saleable_true, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
if (make_closed)
storeManager.setProductTypeStatus_closed(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected void storeSaleAccessControl(ProgressMonitor monitor)
{
storeSaleAccessControlProperties(saleAccessStatus);
}
private ProductTypeSaleAccessStatus saleAccessStatus;
public ProductTypeSaleAccessStatus getProductTypeSaleAccessStatus() {
if (saleAccessStatus == null && getProductType() != null) {
return new ProductTypeSaleAccessStatus(getProductType());
}
return saleAccessStatus;
}
public void setProductTypeSaleAccessStatus(ProductTypeSaleAccessStatus saleAccessStatus) {
this.saleAccessStatus = saleAccessStatus;
}
/**
* Retrieve the ProductType using the appropriate DAO for the actual ProductType-type.
* @param monitor The monitor to use
* @return The ProductType of this controller.
*/
protected abstract ProductTypeType retrieveProductType(ProgressMonitor monitor);
/**
* Store the given ProductType using the appropriate DAO/Bean for the actual ProductType-type.
* @param productType The ProductType to store.
* @param monitor The monitor to use.
* @return The stored and newly-detached ProductType.
*/
protected abstract ProductTypeType storeProductType(ProductTypeType productType, ProgressMonitor monitor);
}