/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package monitoring.web.model.integration; import ilog.cpl.datasource.DataSourceEvent; import ilog.cpl.datasource.DataSourceListener; import ilog.cpl.datasource.DataSourceObjectEvent; import ilog.cpl.datasource.IlpDefaultDataSource; import ilog.cpl.model.IlpObject; import ilog.cpl.util.IlpFilter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import monitoring.web.model.integration.beans.TGOObject; /** * Base class for implementations of <code>IntegratedDataModelProvider</code> * that is used in this sample to integrated the TGO data model with MyFaces' * data models. */ abstract public class AbstractIntegratedDataModelProvider implements IntegratedDataModelProvider { /** * The TGO data source. */ protected IlpDefaultDataSource dataSource; /** * The integrated data model. */ protected Object dataModel; /** * The filter used to prevent objects from being integrated. */ protected IlpFilter filter; /** * Listener used to be notified of changes in the data source so that we can * have a "live" integrated model. */ protected DataSourceChangeListener dataSourceChangeListener; /** * Map used to store the mapping between TGO model objects and * integrated model objects. */ protected Map<IlpObject,TGOObject> tgoToModelObjectMap; /** * Comparator used to sort business objects (IlpObject) */ private Comparator<IlpObject> compareIlp = new Comparator<IlpObject>() { Override public int compare(IlpObject object1, IlpObject object2) { // Compare IlpObject's 'name' attribute, which is a String if (null == object1) { return null == object2 ? 0 : -1; } else { Object name1 = object1.getAttributeValue("name"); Object name2 = object2.getAttributeValue("name"); if (null == name1) { return null == name2 ? 0 : -1; } else if (null == name2) { return 1; } else { return name1.toString().compareTo(name2.toString()); } } } }; /** * Creates internal structures. */ public AbstractIntegratedDataModelProvider() { dataSourceChangeListener = new DataSourceChangeListener(); tgoToModelObjectMap = new HashMap<IlpObject,TGOObject>(); } ////////////////////////////////////////////////////////////////////////////// //IntegratedDataModelProvider Implementation ////////////////////////////////////////////////////////////////////////////// /** * Implementation that attaches the appropriate listeners on the provided * data source. Calling this method automatically refreshes the integrated model. * <p> * <code>null</code> is valid value. * * @see monitoring.web.model.integration.IntegratedDataModelProvider#setDataSource(ilog.cpl.datasource.IlpDefaultDataSource) */ Override public void setDataSource(IlpDefaultDataSource dataSource) { if (this.dataSource != null) { //Remove our current listener dataSource.removeDataSourceListener(dataSourceChangeListener); //Clear old data source this.dataSource.clear(); } //Save the new datasource this.dataSource = dataSource; if (this.dataSource != null) { //Start listening on the new datasource this.dataSource.addDataSourceListener(dataSourceChangeListener); //refresh the data model refreshModel(); } else { //simply empty the model emptyModel(); } } /** * @see monitoring.web.model.integration.IntegratedDataModelProvider#getDataSource() */ Override public IlpDefaultDataSource getDataSource() { return dataSource; } /** * Automatically refreshes the integrated model. * <p> * <code>null</code> is a valid value and indicates that no filtering should be done. * * @see monitoring.web.model.integration.IntegratedDataModelProvider#setFilter(ilog.cpl.util.IlpFilter) */ Override public void setFilter(IlpFilter filter) { if (this.filter != filter) { //Save the new filter this.filter = filter; //Refresh the data model regardeless if the filter is null //filter == null => all objects are shown refreshModel(); } } /** * @see monitoring.web.model.integration.IntegratedDataModelProvider#getFilter() */ Override public IlpFilter getFilter() { return filter; } /** * @see monitoring.web.model.integration.IntegratedDataModelProvider#getDataModel() */ Override public Object getDataModel() { return dataModel; } /** * @see monitoring.web.model.integration.IntegratedDataModelProvider#getModelObject(ilog.cpl.model.IlpObject) */ Override public TGOObject getModelObject(IlpObject tgoObject) { return tgoToModelObjectMap.get(tgoObject); } ////////////////////////////////////////////////////////////////////////////// //Subclass Methods ////////////////////////////////////////////////////////////////////////////// /** * Filters the provided collection of objects using the current filter. It * returns a list of objects that excludes the objects that were filtered out. */ protected List<IlpObject> filterObjects(Collection<IlpObject> objects) { List<IlpObject> filteredObjects = new ArrayList<IlpObject>(); if (getFilter() == null) { filteredObjects.addAll(objects); } else if (objects != null) { for (IlpObject object : objects) { if (filter.accept(object)) { filteredObjects.add(object); } } } // Sort list Collections.sort(filteredObjects, compareIlp); return filteredObjects; } /** * Empties the internal structures that map the TGO model objects to the * integrated model objects. * <p> * It does not modify the actual integrated model. */ protected void emptyModel() { tgoToModelObjectMap.clear(); } /** * Stores the mapping between the TGO model object and the integrated * model object. */ protected void setTGOObjectForModelObject(IlpObject tgoObject, TGOObject modelObject) { tgoToModelObjectMap.put(tgoObject, modelObject); } /** * Listens on changes in the underlying datasource so that the model can be * maintained in synch with the datasource. * <p> * This implementation is for the purposes of a demo, therefore not optimal. */ class DataSourceChangeListener implements DataSourceListener { /** * Refresh the model. */ Override public void batchEnded(DataSourceEvent e) { refreshModel(); } /** * Do nothing. */ Override public void batchStarted(DataSourceEvent e) { } /** * Do nothing. The integrated model objects in this sample are simply wrappers * of the TGO model objects. So attribute changes are made visible instantly. */ Override public void objectAttributeChanged(DataSourceObjectEvent e) { } /** * Refresh the model. */ Override public void objectsAdded(DataSourceEvent e) { refreshModel(); } /** * Refresh the model. */ Override public void objectsRemoved(DataSourceEvent e) { refreshModel(); } /** * Refresh the model. */ Override public void objectStructureChanged(DataSourceObjectEvent e) { refreshModel(); } } }