src.com.ibm.as400.access.PrintObjectList Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PrintObjectList.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.util.Enumeration;
import java.util.Vector;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeSupport;
import java.beans.VetoableChangeListener;
import java.beans.PropertyVetoException;
/**
* Abstract base class for the various types of network print object lists.
*
**/
public abstract class PrintObjectList
implements java.io.Serializable
{
static final long serialVersionUID = 4L;
private static final String SYSTEM = "system";
// These instance variable are persistent.
private NPCPAttributeIDList attrsToRetrieve_ = null;
private NPCPID idFilter_ = null; // for certain lists an idcodepoint may be used to filter
private NPCPSelection selection_ = null; // selection filter
AS400 system_ = null; // The system object
private int typeOfObject_ = 0; // The PrintObject object type
private boolean listOutOfSync_ = false; // Is the list out of sync with the impl list?
private boolean objectAddedEvent_= false; // Has an object been added and event fired?
// These instance variables are not persistent, but private.
private transient boolean open_;
private transient Vector printObjectListListeners_;
private transient Vector theList_;
// These instance variables are not persistent, but are package scope
// to allow subclasses access to them...
transient PrintObjectListImpl impl_;
transient PropertyChangeSupport changes;
transient VetoableChangeSupport vetos;
transient PrintObjectListListener dispatcher_;
boolean useCache_ = true;
/**
* Sets whether or not to internally maintain a cache of objects returned by this list.
* By default, caching is on, so that the Enumeration returned by getObjects() is populated.
* Under normal circumstances, code should not need to call this method.
*
* However, if code wishes to open the list asynchronously and use a PrintObjectListListener to receive
* listObjectAdded() events, the objects in the list are returned on those events. So, in some
* cases, there is no need for this PrintObjectList to maintain a reference to all of the objects
* returned, since they can be processed individually by the listener.
* Calling this method with a value of true will save memory in these cases, but the getObjectList()
* method will return an empty Enumeration, so this method only becomes useful if code has
* registered a PrintObjectListListener with this PrintObjectList.
* @param setting true to enable caching; false to disable caching
* @see #addPrintObjectListListener
* @see #getObjects
* @see com.ibm.as400.access.PrintObjectListEvent#getObject
* @see com.ibm.as400.access.PrintObjectListListener#listObjectAdded
**/
public void setCache(boolean setting)
{
if (impl_ == null) chooseImpl();
useCache_ = setting;
impl_.setCache(setting);
}
/**
* Constructs a PrintObjectList object.
* It is a non-externalized constructor for JavaBeans that allows null system.
*
* @param objectType One of the Network Print Server "objects" listed in
* the NPDataStream class such as NPDataStream.SPOOLED_FILE.
* @param selectionCP A selection codepoint that will be used whenever the
* the list is built.
**/
PrintObjectList(int objectType,
NPCPSelection selectionCP)
{
typeOfObject_ = objectType;
selection_ = selectionCP;
initializeTransient();
}
/**
* Constructs a PrintObjectList object.
* It is a non-externalized constructor.
*
* @param objectType One of the Network Print Server "objects" listed in
* the NPDataStream class such as NPDataStream.SPOOLED_FILE.
* @param selectionCP A selection codepoint that will be used whenever the
* the list is built.
* @param system The system on which the object(s) exists.
**/
PrintObjectList(int objectType,
NPCPSelection selectionCP,
AS400 system)
{
this(objectType, selectionCP);
if( system == null ) {
Trace.log(Trace.ERROR, "printObjectList: Parameter 'system' is null.");
throw new NullPointerException(SYSTEM);
}
system_ = system;
}
/**
*Adds the specified PrintObjectList listener to receive
*PrintObjectList events from this print object list.
*
* @see #removePrintObjectListListener
* @param listener The PrintObjectList listener.
**/
public /* @A5D synchronized*/ void addPrintObjectListListener( PrintObjectListListener listener )
{
printObjectListListeners_.addElement( listener );
// Add the listener to the impl_ for events fired from
// PrintObjectListImplRemote
// @A5D if (impl_ != null)
// @A5D impl_.addPrintObjectListListener(listener);
}
/**
*Adds the specified PropertyChange listener to receive
*PropertyChange events from this print object list.
*
* @see #removePropertyChangeListener
* @param listener The PropertyChange listener.
**/
public void addPropertyChangeListener( PropertyChangeListener listener )
{
changes.addPropertyChangeListener( listener );
}
/**
*Adds the specified VetoableChange listener to receive
*VetoableChange events from this print object list.
*
* @see #removeVetoableChangeListener
* @param listener The VetoableChange listener.
**/
public void addVetoableChangeListener( VetoableChangeListener listener )
{
vetos.addVetoableChangeListener( listener );
}
/*
* Chooses the appropriate implementation (Proxy or Remote).
* Subclasses MUST supply the implementation to this method.
**/
abstract void chooseImpl();
/**
*Closes the list so that objects in the list can be garbage collected.
**/
public void close()
{
synchronized(this)
{
if (open_) {
// ASSERT: if the list has been opened, impl_ has been assigned
impl_.close();
open_ = false;
} else {
// if the list was not open, return to avoid firing closed.
theList_.removeAllElements();
return;
}
}
}
private PrintObjectListEvent createPrintObjectListEvent(int id,
PrintObject printObject,
Exception exception)
{
PrintObjectListEvent event;
// Now that we know we have listeners, we construct
// the event object. We could have passed an event
// object to firePrintObjectList() but that would be
// extra overhead if there were no listeners.
if( exception !=null )
{
event = new PrintObjectListEvent(this, exception);
}
else if( printObject != null )
{
event = new PrintObjectListEvent(this, printObject);
}
else
{
event = new PrintObjectListEvent(this, id);
}
return event;
}
private void firePrintObjectList(PrintObjectListEvent event)
{
event.setSource(this);
// Return if no listeners are registered.
if( printObjectListListeners_.isEmpty() )
{
return;
}
Vector l /* @A5D ;
synchronized(this) { l*/ = (Vector)printObjectListListeners_.clone(); //}
for( int i=0; i < l.size(); i++ )
{
switch( event.getID() )
{
// OBJECT_ADDED is the most frequent case.
case PrintObjectListEvent.OBJECT_ADDED:
PrintObject printObject = event.getObject();
if (useCache_) theList_.addElement(printObject);
objectAddedEvent_ = true;
((PrintObjectListListener)l.elementAt(i)).listObjectAdded(event);
break;
case PrintObjectListEvent.CLOSED:
((PrintObjectListListener)l.elementAt(i)).listClosed(event);
break;
case PrintObjectListEvent.COMPLETED:
((PrintObjectListListener)l.elementAt(i)).listCompleted(event);
break;
case PrintObjectListEvent.ERROR_OCCURRED:
((PrintObjectListListener)l.elementAt(i)).listErrorOccurred(event);
break;
case PrintObjectListEvent.OPENED:
((PrintObjectListListener)l.elementAt(i)).listOpened(event);
break;
}
}
}
// The JavaBeans 1.0 Specification strongly recommends to avoid
// using a synchronized method to fire an event. We use a
// synchronized block to locate the target listeners and then
// call the event listeners from unsynchronized code.
private void firePrintObjectList(int id,
PrintObject printObject,
Exception exception )
{
firePrintObjectList(createPrintObjectListEvent(id, printObject, exception));
}
/**
* Returns one object from the list.
*
* @param index The index of the desired object.
* @return PrintObject
*
* @exception ArrayIndexOutOfBoundsException If an invalid index is given.
**/
public /* @A5D synchronized*/ PrintObject getObject(int index)
{
if (!open_)
{
Trace.log(Trace.ERROR, "getObject: List has not been opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_MUST_BE_OPEN);
}
// ASSERT: if the list has been opened, impl_ has been assigned
// @A5D return impl_.getObject(index);
synchronized(theList_) {
if ((theList_.size() > index) && ((listOutOfSync_ == false)
|| ((listOutOfSync_ == true) && (objectAddedEvent_ == true)
&& (theList_.size() == impl_.size())))) {
objectAddedEvent_ = false;
return (PrintObject) theList_.elementAt(index);
}
else {
PrintObject npobject = null;
if (listOutOfSync_ == true) {
theList_.removeAllElements();
listOutOfSync_ = false;
}
if (useCache_) //@CRS
{
for (int i = theList_.size(); i <= index; ++i) {
NPCPID cpid = impl_.getNPCPID(i);
NPCPAttribute cpattr = impl_.getNPCPAttribute(i);
try {
cpid.setConverter((new Converter(system_.getCcsid(), system_)).impl);
cpattr.setConverter((new Converter(system_.getCcsid(), system_)).impl);
}
catch(UnsupportedEncodingException e) {
if (Trace.isTraceErrorOn())
Trace.log(Trace.ERROR, "Error initializing converter for print object", e);
}
npobject = newNPObject(cpid, cpattr);
theList_.addElement(npobject);
}
return npobject;
}
return null;
}
}
}
/**
* Returns an enumeration of the PrintObjects in the list.
* @return Enumeration
*
**/
public /* @A5D synchronized */ Enumeration getObjects()
{
if (!open_)
{
Trace.log(Trace.ERROR, "getObjects: List has not been opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_MUST_BE_OPEN);
}
// ASSERT: if the list has been opened, impl_ has been assigned
// @A5D Vector v = impl_.getObjects();
// @A5D return v.elements();
// Force retrieval of all objects so far.
getObject(impl_.size() - 1);
return theList_.elements();
}
NPCPSelection getSelectionCP()
{
return selection_;
}
/**
* Returns the system name. This method is primarily provided for visual
* application builders that support JavaBeans.
*
* @return The system on which the objects in the list exist.
**/
final public AS400 getSystem()
{
return system_;
}
private void initializeTransient()
{
impl_ = null;
printObjectListListeners_ = new Vector();
changes = new PropertyChangeSupport(this);
vetos = new VetoableChangeSupport(this);
theList_ = new Vector();
open_ = false;
dispatcher_ = new PrintObjectListListener() {
public void listClosed(PrintObjectListEvent event) { firePrintObjectList(event); }
public void listCompleted(PrintObjectListEvent event) { firePrintObjectList(event); }
public void listErrorOccurred(PrintObjectListEvent event) { firePrintObjectList(event); }
public void listOpened(PrintObjectListEvent event) { firePrintObjectList(event); }
public void listObjectAdded(PrintObjectListEvent event) { firePrintObjectList(event); }
};
}
/**
* Checks if a list that was opened asynchronously has completed.
* If any exception occurred while the list was being retrieved, it will
* be thrown here.
*
* @exception AS400Exception If the system returns an error message.
* @exception AS400SecurityException If a security or authority error occurs.
* @exception ConnectionDroppedException If the connection is dropped unexpectedly.
* @exception ErrorCompletingRequestException If an error occurs before the request is completed.
* @exception InterruptedException If this thread is interrupted.
* @exception IOException If an error occurs while communicating with the system.
* @exception RequestNotSupportedException If the requested function is not supported because
* the system operating system is not at the correct level.
* @return true if the list is completely built; false otherwise.
**/
public boolean isCompleted()
throws AS400Exception,
AS400SecurityException,
ConnectionDroppedException,
ErrorCompletingRequestException,
InterruptedException,
IOException,
RequestNotSupportedException
{
if (!open_) {
Trace.log(Trace.ERROR, "isCompleted: List has not been opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_MUST_BE_OPEN);
}
// ASSERT: if the list has been opened, impl_ has been assigned
return impl_.isCompleted();
}
// Not public!
abstract PrintObject newNPObject(NPCPID cpid, NPCPAttribute cpattr);
/**
* Builds the list asynchronously. This method starts a thread
* to build the list and then returns. The caller may register
* listeners to obtain status about the list, or call isCompleted(),
* waitForItem(), or waitForListToComplete().
**/
public void openAsynchronously()
{
synchronized (this)
{
if (open_) {
// list is already open.
Trace.log(Trace.ERROR, "open: List is already opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_BE_OPEN);
}
if (impl_ == null) {
if (system_ == null) {
// forewarn any listeners an error occurs.
Exception e = new ExtendedIllegalStateException(SYSTEM,
ExtendedIllegalStateException.PROPERTY_NOT_SET);
firePrintObjectList(PrintObjectListEvent.ERROR_OCCURRED, null, e);
}
chooseImpl();
}
if (!getSystem().isThreadUsed()) {
// Our system object says do not start threads.The
// application should be using openSynchronously().
Trace.log(Trace.ERROR, "open: Threads can not be started.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_START_THREADS);
}
open_ = true;
listOutOfSync_ = true;
impl_.openAsynchronously();
}
}
/**
* Builds the list synchronously. This method will not
* return until the list has been built completely.
* The caller may then call the getObjects() method
* to get an enumeration of the list.
*
* @exception AS400Exception If the system returns an error message.
* @exception AS400SecurityException If a security or authority error occurs.
* @exception ConnectionDroppedException If the connection is dropped unexpectedly.
* @exception ErrorCompletingRequestException If an error occurs before the request is completed.
* @exception InterruptedException If this thread is interrupted.
* @exception IOException If an error occurs while communicating with the system.
* @exception RequestNotSupportedException If the requested function is not supported because the
* system operating system is not at the correct level.
**/
public void openSynchronously()
throws AS400Exception,
AS400SecurityException,
ConnectionDroppedException,
ErrorCompletingRequestException,
InterruptedException,
IOException,
RequestNotSupportedException
{
synchronized(this)
{
if( open_ ) {
// list is already open.
Trace.log(Trace.ERROR, "open: List is already opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_BE_OPEN);
}
if (impl_ == null) {
if (system_ == null) {
// forewarn any listeners an error occurs.
Exception e = new ExtendedIllegalStateException(SYSTEM,
ExtendedIllegalStateException.PROPERTY_NOT_SET);
firePrintObjectList(PrintObjectListEvent.ERROR_OCCURRED, null, e);
}
chooseImpl();
} // Bugfix 1551918
open_ = true;
listOutOfSync_ = true;
impl_.openSynchronously();
//} // Bugfix 1551918
}
}
// We need to initialize our transient and static data when
// the object is de-serialized. static final data is OK.
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
initializeTransient();
}
/**
*Removes the specified PrintObjectList listener
*so that it no longer receives PrintObjectList events
*from this print object list.
*
* @see #addPrintObjectListListener
* @param listener The PrintObjectList listener.
**/
public /* @A5D synchronized */ void removePrintObjectListListener( PrintObjectListListener listener )
{
printObjectListListeners_.removeElement(listener);
// Remove the listener from the impl_ - no longer monitoring for events
// fired from PrintObjectListImplRemote
// @A5D if (impl_ != null)
// @A5D impl_.removePrintObjectListListener(listener);
}
/**
*Removes the specified PropertyChange listener
*so that it no longer receives PropertyChange events
*from this print object list.
*
* @see #addPropertyChangeListener
* @param listener The PropertyChange listener.
**/
public void removePropertyChangeListener( PropertyChangeListener listener )
{
changes.removePropertyChangeListener(listener);
}
/**
*Removes the specified VetoableChange listener
*so that it no longer receives VetoableChange events
*from this print object list.
*
* @see #addVetoableChangeListener
* @param listener The VetoableChange listener.
**/
public void removeVetoableChangeListener( VetoableChangeListener listener )
{
vetos.removeVetoableChangeListener(listener);
}
/**
* Resets the list of object attributes to retrieve.
**/
public void resetAttributesToRetrieve()
{
if (open_)
{
Trace.log(Trace.ERROR, "resetAttributesToRetrieve: List is already opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_BE_OPEN);
}
else {
attrsToRetrieve_ = null;
if (impl_ != null)
impl_.resetAttributesToRetrieve();
}
}
/**
* Resets the list filter back to default values.
**/
public void resetFilter()
{
if (open_)
{
Trace.log(Trace.ERROR, "resetFilter: List is already opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_BE_OPEN);
}
else {
selection_.reset();
idFilter_ = null; // effectively resets the id Codepoint filter;
if (impl_ != null)
impl_.resetFilter();
}
}
/**
* Sets the attributes of the object that should be returned in the list.
* This method can be used to speed up the listing if
* only interested in a few attributes for each item in the list.
*
* @param attributes An array of attribute IDs that define which
* object attributes will be retrieved for each item in the list
* when the list is opened.
*
* @see PrintObject
**/
public synchronized void setAttributesToRetrieve(int[] attributes)
{
// check params
if (attributes == null)
{
Trace.log(Trace.ERROR, "setAttributesToRetrieve: Parameter 'attributes' is null.");
throw new NullPointerException("attributes");
}
// check state of list
if (open_)
{
Trace.log(Trace.ERROR, "setAttributesToRetrieve: List is already opened.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.OBJECT_CAN_NOT_BE_OPEN);
}
if (attrsToRetrieve_ != null)
{
attrsToRetrieve_.reset();
}
else {
attrsToRetrieve_ = new NPCPAttributeIDList();
}
for (int i = 0; i