/* *****************************************************************************
* JFire - it's hot - Free ERP System - http://jfire.org *
* Copyright (C) 2004-2005 NightLabs - http://NightLabs.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
* Or get it online : *
* http://opensource.org/licenses/lgpl-license.php *
* *
* *
******************************************************************************/
package org.nightlabs.jfire.trade.admin.ui.moneyflow;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.jdo.FetchPlan;
import javax.jdo.JDOHelper;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.nightlabs.base.ui.job.Job;
import org.nightlabs.base.ui.layout.WeightedTableLayout;
import org.nightlabs.base.ui.table.TableLabelProvider;
import org.nightlabs.base.ui.tree.AbstractTreeComposite;
import org.nightlabs.base.ui.tree.TreeContentProvider;
import org.nightlabs.jdo.NLJDOHelper;
import org.nightlabs.jfire.accounting.Account;
import org.nightlabs.jfire.accounting.book.LocalAccountantDelegate;
import org.nightlabs.jfire.accounting.book.id.LocalAccountantDelegateID;
import org.nightlabs.jfire.accounting.book.mappingbased.MoneyFlowMapping;
import org.nightlabs.jfire.accounting.book.mappingbased.MappingBasedAccountantDelegate.ResolvedMapEntry;
import org.nightlabs.jfire.accounting.book.mappingbased.MappingBasedAccountantDelegate.ResolvedMapKey;
import org.nightlabs.jfire.store.NestedProductTypeLocal;
import org.nightlabs.jfire.store.ProductType;
import org.nightlabs.jfire.store.dao.ProductTypeDAO;
import org.nightlabs.jfire.store.id.ProductTypeID;
import org.nightlabs.jfire.trade.admin.ui.resource.Messages;
import org.nightlabs.jfire.trade.ui.accounting.AccountingUtil;
import org.nightlabs.jfire.trade.ui.store.ProductTypePackageTree;
import org.nightlabs.progress.NullProgressMonitor;
import org.nightlabs.progress.ProgressMonitor;
import org.nightlabs.util.NLLocale;
/**
* @author Alexander Bieber <alex[AT]nightlabs[DOT]de>
*
*/
public class ResolvedMappingTree
extends AbstractTreeComposite
{
/**
* Instances of Node are the elements of the ProductTypePackageTree
*/
public static class Node {
private Node parent;
private MoneyFlowMapping mapping;
private ProductTypeID productTypeID;
private ProductType productType;
private List<Node> children;
private int productTypeDelegationLevel;
public Node(Node parent, MoneyFlowMapping mapping, ProductTypeID productTypeID, Map resolvedMappings) {
this.mapping = mapping;
this.productTypeID = productTypeID;
children = new LinkedList<Node>();
if (productTypeID == null)
return;
productType = ProductTypeDAO.sharedInstance().getProductType(
productTypeID, ProductTypePackageTree.DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT,
new NullProgressMonitor());
String packageType = MoneyFlowMapping.PACKAGE_TYPE_INNER;
if (parent == null)
packageType = MoneyFlowMapping.PACKAGE_TYPE_PACKAGE;
ResolvedMapKey key = new ResolvedMapKey(productTypeID, packageType);
ResolvedMapEntry entry = (ResolvedMapEntry) resolvedMappings.get(key);
if (entry == null)
return;
productTypeDelegationLevel = entry.getDelegationLevel();
for (Iterator iter = entry.getResolvedMappings().values().iterator(); iter.hasNext();) {
MoneyFlowMapping entryMapping = (MoneyFlowMapping) iter.next();
children.add(
new Node(
this,
entryMapping,
null,
resolvedMappings
)
);
}
for (Iterator iter = productType.getProductTypeLocal().getNestedProductTypeLocals().iterator(); iter.hasNext();) {
NestedProductTypeLocal nestedProductTypeLocal = (NestedProductTypeLocal) iter.next();
children.add(
new Node(
this,
null,
ProductTypeID.create(
nestedProductTypeLocal.getInnerProductTypeOrganisationID(),
nestedProductTypeLocal.getInnerProductTypeProductTypeID()
),
resolvedMappings
)
);
}
}
/**
* @return Returns the children.
*/
public List getChildren() {
return children;
}
public boolean hasChildren() {
return children != null && children.size()>0;
}
/**
* @return Returns the nodeProductType.
*/
public ProductTypeID getProductTypeID() {
return productTypeID;
}
/**
* @return Returns the parent.
*/
public Node getParent() {
return parent;
}
public ProductType getProductType() {
return productType;
}
public MoneyFlowMapping getMapping() {
return mapping;
}
}
private ProductTypeID currentProductTypeID = null;
/**
* The root Node for the current ProductTypeID
*/
private Node rootNode = null;
/**
* Map to find all Nodes fast.
* key: ProductTypeID nodeProductTypeID
* value: Node node
*/
private Map nodesByProductTypeID = new HashMap();
/**
* ContentProvider that holds a tree of Nodes.
*
*/
private static class ContentProvider
extends TreeContentProvider
{
/**
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
if (inputElement instanceof Node)
return getChildren(inputElement);
else
return new Object[] {};
}
/**
* @see org.nightlabs.base.ui.tree.TreeContentProvider#getChildren(java.lang.Object)
*/
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof Node && parentElement != null)
return ((Node)parentElement).getChildren().toArray();
return super.getChildren(parentElement);
}
/**
* @see org.nightlabs.base.ui.tree.TreeContentProvider#getParent(java.lang.Object)
*/
@Override
public Object getParent(Object element) {
if (element instanceof Node)
return ((Node)element).getParent();
return super.getParent(element);
}
/**
* @see org.nightlabs.base.ui.tree.TreeContentProvider#hasChildren(java.lang.Object)
*/
@Override
public boolean hasChildren(Object element) {
if (element instanceof Node)
return ((Node)element).hasChildren();
return super.hasChildren(element);
}
@Override
public void dispose() {
}
}
public static final String[] FETCH_GROUP_RESOLVED_MONEY_FLOW_MAPPING = new String[] {
FetchPlan.DEFAULT,
MoneyFlowMapping.FETCH_GROUP_LOCAL_ACCOUNTANT_DELEGATE,
MoneyFlowMapping.FETCH_GROUP_ALL_DIMENSIONS,
Account.FETCH_GROUP_NAME,
LocalAccountantDelegate.FETCH_GROUP_NAME
};
protected void buildTree(ProductTypeID productTypeID, LocalAccountantDelegateID delegateID, ProgressMonitor monitor)
{
monitor.beginTask(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.loadMoneyFlowMappingMonitor.task.name"), 2); //$NON-NLS-1$
monitor.worked(1);
if ((currentProductTypeID == null) || (!productTypeID.equals(currentProductTypeID)))
{
nodesByProductTypeID.clear();
Map resolvedMappings = null;
currentProductTypeID = productTypeID;
try {
resolvedMappings = AccountingUtil.getAccountingManager().getResolvedMoneyFlowMappings(
currentProductTypeID,
delegateID,
FETCH_GROUP_RESOLVED_MONEY_FLOW_MAPPING,
NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT
);
} catch (Exception e) {
throw new RuntimeException(e);
}
rootNode = new Node(null, null, productTypeID, resolvedMappings);
}
if (currentProductTypeID == null) {
rootNode = null;
}
monitor.worked(1);
}
/**
* Simple LabelProvider accessing Nodes
*/
private static class LabelProvider
extends TableLabelProvider
{
public String getColumnText(Object element, int columnIndex) {
if (element instanceof Node) {
Node node = (Node)element;
if (node.getProductType() != null) {
switch (columnIndex) {
case 0: return node.getProductType().getName().getText(NLLocale.getDefault().getLanguage());
}
}
else {
switch (columnIndex) {
case 0:
LocalAccountantDelegateType delegateType = LocalAccountantDelegateRegistry.sharedInstance().getTypeForMapping(node.getMapping().getClass());
return delegateType.getMappingDescription(node.getMapping());
case 1:
// Account account = AccountDAO.sharedInstance().getAccount(
// Account.primaryKeyToAnchorID(node.getMapping().getAccountPK()),
// AccountCellEditor.DEFAULT_FETCH_GROUPS,
// NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT,
// new NullProgressMonitor()
// );
// return account.getName().getText(NLLocale.getDefault().getLanguage());
return getAccountName(node.getMapping().getRevenueAccount());
case 2:
return getAccountName(node.getMapping().getExpenseAccount());
case 3:
return getAccountName(node.getMapping().getReverseRevenueAccount());
case 4:
return getAccountName(node.getMapping().getReverseExpenseAccount());
case 5:
return node.getMapping().getLocalAccountantDelegate().getName().getText();
}
}
}
return ""; //$NON-NLS-1$
}
private String getAccountName(Account account) {
return account == null ? "" : account.getName().getText(); //$NON-NLS-1$
}
/**
* @see org.nightlabs.base.ui.table.TableLabelProvider#getText(java.lang.Object)
*/
@Override
public String getText(Object element) {
return getColumnText(element, 0);
}
}
/**
* @param parent
*/
public ResolvedMappingTree(Composite parent) {
this(parent, DEFAULT_STYLE_SINGLE | SWT.FULL_SELECTION, true, true, true);
}
/**
* @param parent
* @param style
* @param setLayoutData
* @param init
* @param headerVisible
*/
public ResolvedMappingTree(Composite parent, int style,
boolean setLayoutData, boolean init, boolean headerVisible) {
super(parent, style, setLayoutData, init, headerVisible);
}
/**
* @see org.nightlabs.base.ui.tree.AbstractTreeComposite#setTreeProvider(org.eclipse.jface.viewers.TreeViewer)
*/
@Override
public void setTreeProvider(TreeViewer treeViewer) {
treeViewer.setContentProvider(new ContentProvider());
treeViewer.setLabelProvider(new LabelProvider());
}
/**
* @see org.nightlabs.base.ui.tree.AbstractTreeComposite#createTreeColumns(org.eclipse.swt.widgets.Tree)
*/
@Override
public void createTreeColumns(Tree tree) {
TreeColumn column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.ProductTypeMappingTreeColumn.text")); //$NON-NLS-1$
column.setResizable(true);
column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.revenueAccount.name")); //$NON-NLS-1$
column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.revenueAccount.tooltip")); //$NON-NLS-1$
column.setResizable(true);
column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.expenseAccount.name")); //$NON-NLS-1$
column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.expenseAccount.tooltip")); //$NON-NLS-1$
column.setResizable(true);
column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.reverseRevenueAccount.name")); //$NON-NLS-1$
column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.reverseRevenueAccount.tooltip")); //$NON-NLS-1$
column.setResizable(true);
column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.reverseExpenseAccount.name")); //$NON-NLS-1$
column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.column.reverseExpenseAccount.tooltip")); //$NON-NLS-1$
column.setResizable(true);
column = new TreeColumn(getTree(), SWT.LEFT);
column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.contributingDelegateTreeColumn.text")); //$NON-NLS-1$
column.setResizable(true);
tree.setLayout(new WeightedTableLayout(new int[] {20, 10, 10, 10, 10, 20}));
}
protected ContentProvider getContentProvider() {
return (ContentProvider)getTreeViewer().getContentProvider();
}
/**
* @deprecated use {@link #setProductType(ProductType)} instead
*
* @param productTypeID the id of the {@link ProductType} to load
* @param monitor the monitor to display the progress of fetching the ProductType
*/
@Deprecated
public void setProductTypeID(final ProductTypeID productTypeID, ProgressMonitor monitor) {
if (productTypeID == null)
return;
ProductType productType = ProductTypeDAO.sharedInstance().getProductType(
productTypeID, MoneyFlowMappingTree.DEFAULT_PTYPE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT,
monitor);
if (!(productType != null && productType.getProductTypeLocal().getLocalAccountantDelegate() != null))
return;
final LocalAccountantDelegateID delegateID = (LocalAccountantDelegateID) JDOHelper.getObjectId(productType.getProductTypeLocal().getLocalAccountantDelegate());
Job job = new Job(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.loadMoneyFlowMappingJob.name")){ //$NON-NLS-1$
@Override
protected IStatus run(ProgressMonitor monitor) throws Exception
{
buildTree(productTypeID, delegateID, monitor);
Display.getDefault().syncExec(new Runnable(){
public void run() {
getTreeViewer().setInput(rootNode);
getTreeViewer().expandAll();
}
});
return Status.OK_STATUS;
}
};
job.setUser(true);
job.schedule();
}
/**
* sets the ProductType
* @param productType the productType to set
*/
public void setProductType(final ProductType productType) {
if (productType == null)
return;
if (!(productType != null && productType.getProductTypeLocal().getLocalAccountantDelegate() != null))
return;
if (!productType.isSaleable())
return;
final ProductTypeID productTypeID = (ProductTypeID) JDOHelper.getObjectId(productType);
final LocalAccountantDelegateID delegateID = (LocalAccountantDelegateID) JDOHelper.getObjectId(productType.getProductTypeLocal().getLocalAccountantDelegate());
Job job = new Job(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.ResolvedMappingTree.loadMoneyFlowMappingJob.name")){ //$NON-NLS-1$
@Override
protected IStatus run(ProgressMonitor monitor) throws Exception
{
buildTree(productTypeID, delegateID, monitor);
Display.getDefault().syncExec(new Runnable(){
public void run() {
getTreeViewer().setInput(rootNode);
getTreeViewer().expandAll();
}
});
return Status.OK_STATUS;
}
};
job.setUser(true);
job.schedule();
}
public void clear()
{
Display.getDefault().syncExec(new Runnable(){
public void run() {
setInput(null);
}
});
}
}