/* *****************************************************************************
* 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://www.gnu.org/copyleft/lesser.html *
* *
* *
******************************************************************************/
package org.nightlabs.jfire.scripting.ui;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jdo.FetchPlan;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ListenerList;
import org.nightlabs.jdo.NLJDOHelper;
import org.nightlabs.jfire.base.JFireEjb3Factory;
import org.nightlabs.jfire.base.jdo.cache.Cache;
import org.nightlabs.jfire.base.login.ui.Login;
import org.nightlabs.jfire.base.ui.jdo.JDOObjectDAO;
import org.nightlabs.jfire.scripting.Script;
import org.nightlabs.jfire.scripting.ScriptManagerRemote;
import org.nightlabs.jfire.scripting.ScriptRegistryItem;
import org.nightlabs.jfire.scripting.ScriptRegistryItemCarrier;
import org.nightlabs.jfire.scripting.id.ScriptRegistryItemID;
/**
* Provides accesses to cached versions of
* <code>ReportRegistryItem</code>s and holds a representation
* of the ReportRegistry structure. Register a {@link ScriptRegistryListener}
* to be notified on changes to the structure.
*
*
* TODO: Implement correctly and move to server project
*
* @author Alexander Bieber <alex[AT]nightlabs[DOT]de>
*
*/
public class ScriptRegistryItemProvider
extends JDOObjectDAO<ScriptRegistryItemID, ScriptRegistryItem>
{
/**
* holds all top level nodes by their type
*/
private Map<String,ScriptRegistryItemNode> topLevelNodesByType;
/**
* The root node holding the actual top level nodes as children
*/
private ScriptRegistryItemNode registryItemRootNode;
/**
* A Map of all nodes in the structure with their IDs
*/
private Map<ScriptRegistryItemID, ScriptRegistryItemNode> allNodes;
// /**
// * The controller for the registry, changes when the structrue was changed
// */
// private JDOObjectController registryController;
/**
* Listeners to structure change
*/
private ListenerList registryListeners = new ListenerList();
// TODO: Change fetch group when recursion-depth is available
/**
* Fetch groups used when fetching single items that where
* removed from the cache
*/
public static final String[] DEFAULT_FETCH_GROUPS = new String[] {
FetchPlan.DEFAULT,
ScriptRegistryItem.FETCH_GROUP_NAME
};
public static final String[] SCRIPT_FETCH_GROUPS = DEFAULT_FETCH_GROUPS;
/**
* Constructs a new ScriptRegistryItemProvider
* @see #sharedInstance()
*/
public ScriptRegistryItemProvider() {
super();
}
private boolean wasLoaded() {
return registryItemRootNode != null;
}
// /**
// * Updates the structrue tree and notifies all listeners
// * when the registry changed on the server.
// */
// // TODO replace NotificationListener with JDOLifeCycleListener
// private NotificationListener registryChangeListener = new NotificationListenerWorkerThreadAsync()
// {
// public void notify(NotificationEvent evt) {
// logger.info("registryChangeListener got notified with event "+evt);
// for (Object subject : evt.getSubjects()) {
// Object o =( (DirtyObjectID)subject).getObjectID();
// logger.info("registryChangeListener with subject "+o);
// if (o instanceof JDOObjectControllerID) {
// if (registryController == null) {
// loadAllRegistryItems();
// break;
// }
// JDOManager jdoManager = null;
// try {
// jdoManager = JDOManagerUtil.getHome(Login.getLogin().getInitialContextProperties()).create();
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// JDOObjectSyncResult syncResult = null;
// try {
// syncResult = jdoManager.syncJDOObjectChanges(
// ScriptRegistry.SINGLETON_ID,
// registryController.getControllerVersion(),
// null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT
// );
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// registryController = syncResult.getJdoObjectController();
// boolean changed = false;
// for (JDOObjectChangeEvent event : syncResult.getChangeEvents()) {
//// if (event instanceof ScriptRegistryItemChangeEvent) {
//// ScriptRegistryItemChangeEvent registryEvent = (ScriptRegistryItemChangeEvent)event;
//// if (ScriptRegistryItemChangeEvent.EVENT_TYPE_ITEM_ADDED.equals(registryEvent.getEventType())) {
//// changed = true;
//// ScriptRegistryItemNode node = null;
//// if (registryEvent.getRelatedItemCarrier() == null) {
//// // added to the root -> new root category
//// node = new ScriptRegistryItemNode(null, registryEvent.getItemCarrier(), false, allNodes);
//// ScriptRegistryItemID itemID;
//// try {
//// itemID = new ScriptRegistryItemID(registryEvent.getItemID());
//// } catch (Exception e) {
//// throw new RuntimeException(e);
//// }
//// topLevelNodesByType.put(itemID.scriptRegistryItemType, node);
//// }
//// else {
//// // added something to a parent
//// ScriptRegistryItemNode parentNode = allNodes.get(registryEvent.getRelatedItemCarrier().getRegistryItemID());
//// if (parentNode == null)
//// throw new IllegalStateException("Have change event: itemAdded, but could not find its parent in the local tree.");
//// node = new ScriptRegistryItemNode(
//// parentNode,
//// registryEvent.getItemCarrier(),
//// false,
//// allNodes
//// );
//// parentNode.addChildCarrier(node);
//// }
//// }
//// }
// }
// if (changed)
// notifyRegistryListeners();
// }
// }
// }
// };
/**
* Initially loads the structure from the server and puts all items into cache
*
*/
private void loadAllRegistryItems()
{
Login login = null;
try {
login = Login.getLogin();
} catch (Exception e) {
throw new RuntimeException(e);
}
// // TODO replace ChangeManager with JDOLifecycleManager
// JDOLifecycleManager.sharedInstance().removeNotificationListener(JDOObjectController.class, registryChangeListener);
// Get the registry structure
ScriptManagerRemote scriptManager;
try {
scriptManager = JFireEjb3Factory.getRemoteBean(ScriptManagerRemote.class, login.getInitialContextProperties());
} catch (Exception e) {
throw new RuntimeException(e);
}
Collection<ScriptRegistryItemCarrier> topLevelItems = null;
try {
topLevelItems = scriptManager.getTopLevelScriptRegistryItemCarriers(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
registryItemRootNode = new ScriptRegistryItemNode();
topLevelNodesByType = new HashMap<String,ScriptRegistryItemNode>();
List<ScriptRegistryItemID> allItemIDs = new ArrayList<ScriptRegistryItemID>();
allNodes = new HashMap<ScriptRegistryItemID, ScriptRegistryItemNode>();
for (ScriptRegistryItemCarrier carrier : topLevelItems) {
ScriptRegistryItemNode node = new ScriptRegistryItemNode(registryItemRootNode, carrier, true, allNodes);
topLevelNodesByType.put(carrier.getRegistryItemType(), node);
registryItemRootNode.addChildCarrier(node);
insertItemIDs(node, allItemIDs);
}
// // Get the registry controller keeping
// // track of all changes
// JDOManager jdoManager = null;
// try {
// jdoManager = JDOManagerUtil.getHome(Login.getLogin().getInitialContextProperties()).create();
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// try {
// registryController = jdoManager.getJDOObjectController(
// ScriptRegistry.SINGLETON_ID, JDOObjectController.DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// Cache.sharedInstance().put(null, registryController, JDOObjectController.DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
// JDOLifecycleManager.sharedInstance().addNotificationListener(JDOObjectController.class, registryChangeListener);
List<ScriptRegistryItem> allItems = null;
try {
allItems = scriptManager.getScriptRegistryItems(
allItemIDs, DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
} catch (Exception e) {
throw new RuntimeException(e);
}
for (Iterator<ScriptRegistryItem> iter = allItems.iterator(); iter.hasNext();) {
ScriptRegistryItem item = iter.next();
Cache.sharedInstance().put(null, item, DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
}
}
private void insertItemIDs(ScriptRegistryItemNode node, List<ScriptRegistryItemID> itemIDs) {
itemIDs.add(node.getRegistryItemID());
for (ScriptRegistryItemNode childNode : node.getChildNodes()) {
insertItemIDs(childNode, itemIDs);
}
}
private static Collection<ScriptRegistryItemNode> EMPTY_COLLECTION;
/**
* Returns the top level nodes of the ReportRegistry structure.
* In fact this returns the whole structure as the top level
* nodes know their children and so on ...
*/
public Collection<ScriptRegistryItemNode> getTopLevelNodes() {
if (!wasLoaded())
loadAllRegistryItems();
if (topLevelNodesByType == null)
return EMPTY_COLLECTION;
return topLevelNodesByType.values();
}
public ScriptRegistryItemNode getTopLevelNodeForType(String scriptRegistryItemType) {
if (!wasLoaded())
loadAllRegistryItems();
if (topLevelNodesByType == null)
return null;
return topLevelNodesByType.get(scriptRegistryItemType);
}
/**
* Returns the top level nodes for the given set of ScriptRegistryItemIDs
*/
public Collection<ScriptRegistryItemNode> getNodes(Set<ScriptRegistryItemID> itemIDs)
{
if (!wasLoaded())
loadAllRegistryItems();
if (topLevelNodesByType == null)
return EMPTY_COLLECTION;
Collection<ScriptRegistryItemNode> topLevelNodes = new LinkedList<ScriptRegistryItemNode>();
for (ScriptRegistryItemID itemID : itemIDs) {
topLevelNodes.add(allNodes.get(itemID));
}
return topLevelNodes;
}
private static ScriptRegistryItemProvider sharedInstance;
/**
* Access <code>ScriptRegistryItem</code>s via this static
* instance of ScriptRegistryItemProvider.
*/
public static ScriptRegistryItemProvider sharedInstance() {
if (sharedInstance == null)
sharedInstance = new ScriptRegistryItemProvider();
return sharedInstance;
}
@Override
protected ScriptRegistryItem retrieveJDOObject(ScriptRegistryItemID scriptID, String[] fetchGroups, int maxFetchDepth, IProgressMonitor monitor)
throws Exception
{
if (scriptID == null)
throw new IllegalArgumentException("Param scriptID must not be null!"); //$NON-NLS-1$
ScriptManagerRemote scriptManager = JFireEjb3Factory.getRemoteBean(ScriptManagerRemote.class, Login.getLogin().getInitialContextProperties());
ScriptRegistryItem registryItem = scriptManager.getScriptRegistryItem(
scriptID, fetchGroups, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
return registryItem;
}
@Override
protected Collection<ScriptRegistryItem> retrieveJDOObjects(Set<ScriptRegistryItemID> scriptIDs, String[] fetchGroups, int maxFetchDepth, IProgressMonitor monitor)
throws Exception
{
if (scriptIDs == null)
throw new IllegalArgumentException("Param scriptIDs must not be null!"); //$NON-NLS-1$
List<ScriptRegistryItemID> ids = new ArrayList<ScriptRegistryItemID>(scriptIDs);
ScriptManagerRemote scriptManager = JFireEjb3Factory.getRemoteBean(ScriptManagerRemote.class, Login.getLogin().getInitialContextProperties());
List<ScriptRegistryItem> registryItems = scriptManager.getScriptRegistryItems(
ids, fetchGroups, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT);
return registryItems;
}
/**
* Get the <code>ScriptRegistryItem</code> with the given itemID and
* {@link #DEFAULT_FETCH_GROUPS}.
*/
public ScriptRegistryItem getScriptRegistryItem(ScriptRegistryItemID itemID, IProgressMonitor monitor) {
return getJDOObject(null, itemID, DEFAULT_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor);
}
/**
* Get the <code>ScriptRegistryItem</code> with the given itemID and fetchGroups.
*/
public ScriptRegistryItem getScriptRegistryItem(ScriptRegistryItemID itemID, String[] fetchGroups, IProgressMonitor monitor) {
return getJDOObject(null, itemID, fetchGroups, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor);
}
/**
* Get the <code>ScriptRegistryItem</code> with the given id and
* cast it to a Script.
* @throws ClassCastException
*/
public Script getScript(ScriptRegistryItemID scriptLayoutID, IProgressMonitor monitor) {
return (Script)getScriptRegistryItem(scriptLayoutID, SCRIPT_FETCH_GROUPS, monitor);
}
/**
* Add a listener to changes of the ScriptRegistry structure
* @param registryListener The listener to add
*/
public void addScriptRegistryListener(ScriptRegistryListener registryListener) {
registryListeners.add(registryListener);
}
/**
* Removes the given listener
*/
public void removeScriptRegistryListener(ScriptRegistryListener registryListener) {
registryListeners.remove(registryListener);
}
// private void notifyRegistryListeners()
// {
// for (int i=0; i<registryListeners.size(); i++)
// {
// ScriptRegistryListener listener =
// (ScriptRegistryListener) registryListeners.getListeners()[i];
// try {
// listener.scriptRegistryChanged();
// } catch (Exception e) {
// logger.error(e);
// }
// }
// }
}