Java tutorial
/* * Copyright 2010 Workplace Systems PLC (http://www.workplacesystems.com/). * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.workplacesystems.queuj; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.lang.reflect.Constructor; import java.util.Locale; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.workplacesystems.queuj.process.BatchProcessServer; import com.workplacesystems.queuj.utils.QueujException; import com.workplacesystems.utilsj.collections.FilterableArrayList; import java.util.Collections; import java.util.HashMap; /** * A Queue object controls how Processes run and are created. A Queue is not persistent except * in the Process that it creates. For example if one of the pre-defined Queue's are changed the * Queue that was previously persisted with a Process will no longer be equal to the new Queue * and will run with the properties defined at the time the Process was created. * * A Queue is imutable. Its properties cannot be changed after the Queue has been created. For * 2 Queue's queue1 and queue2: if queue1.equals(queue2) then queue1 == queue2 may or may not be * true. Also if queue1.equals(queue2) then queue1.toString().equals(queue2.toString()). * * @author dave */ public final class Queue<B extends ProcessBuilder> implements Serializable { // Increase the number when an incompatible change is made private static final long serialVersionUID = Queue.class.getName().hashCode() + 1; /** log instance */ private final static Log log = LogFactory.getLog(Queue.class); /** The parent queue. All queues except ROOT_QUEUE have a parent. */ private final Queue<? extends ProcessBuilder> parent_queue; /** The Queue restriction for Processes owned by this Queue. */ private final QueueRestriction restriction; /** The custom index for this Queue. */ private final Index index; /** The ProcessBuilder class to instantiate for building Processes from this Queue. */ private final Class<B> process_builder_class; /** The BatchProcessServer to instantiate to run the actual Process. */ private final Class<? extends BatchProcessServer> process_server_class; /** The default Occurrence to use for Processes owned by this Queue. */ private final Occurrence default_occurence; /** The default Visibility to use for Processes owned by this Queue. */ private final Visibility default_visibility; /** The default Access to use for Processes owned by this Queue. */ private final Access default_access; /** The default Resilience to use for Processes owned by this Queue. */ private final Resilience default_resilience; /** The default Output to use for Processes owned by this Queue. */ private final Output default_output; private final Map<String, Serializable> implementation_options; private transient String queue_string = null; /** Creates a new instance of QueueBuilder */ Queue(Queue parent_queue, QueueRestriction restriction, Index index, Class<B> process_builder_class, Class<? extends BatchProcessServer> process_server_class, Occurrence default_occurence, Visibility default_visibility, Access default_access, Resilience default_resilience, Output default_output, HashMap<String, Serializable> implementation_options) { this.parent_queue = parent_queue; this.restriction = restriction; this.index = index; this.process_builder_class = process_builder_class; this.process_server_class = process_server_class; this.default_occurence = default_occurence; this.default_visibility = default_visibility; this.default_access = default_access; this.default_resilience = default_resilience; this.default_output = default_output; HashMap<String, Serializable> implementation_options0 = new HashMap<String, Serializable>(); if (parent_queue != null) implementation_options0.putAll(parent_queue.getImplementationOptions()); implementation_options0.putAll(implementation_options); this.implementation_options = Collections.unmodifiableMap(implementation_options0); setId(this); if (log.isDebugEnabled()) log.debug("Creating Queue:" + new_line + toString()); } /** * Get a new ProcessBuilder using the supplied Locale. */ public B newProcessBuilder(Locale locale) { return newProcessBuilder(new Class[] { Queue.class, Locale.class }, new Object[] { this, locale }); } /** * Private method to instantiate the Queues ProcessBuilder. Will ask the parent Queue * to instantiate its ProcessBuilder if this Queue doesn't have one. */ private B newProcessBuilder(Class[] param_types, Object[] params) { if (process_builder_class != null) { try { Constructor<B> constructor = process_builder_class.getDeclaredConstructor(param_types); return constructor.newInstance(params); } catch (Exception e) { throw new QueujException(e); } } if (parent_queue != null) return (B) parent_queue.newProcessBuilder(param_types, params); // else throw new QueujException("No ProcessBuilder exists for Queue"); } /** * Gets a new QueueBuilder using this Queue as the parent. */ public QueueBuilder<B> newQueueBuilder() { return QueueFactory.newQueueBuilder(this, process_builder_class); } /** * Gets a new QueueBuilder using this Queue as the parent. */ public <P extends ProcessBuilder> QueueBuilder<P> newQueueBuilder(Class<P> process_builder_class) { return QueueFactory.newQueueBuilder(this, process_builder_class); } /** * Instantiate the Queues BatchProcessServer. Will ask the parent Queue * to instantiate its BatchProcessServer if this Queue doesn't have one. */ public BatchProcessServer getBatchProcessServer() { if (process_server_class != null) { try { return process_server_class.newInstance(); } catch (Exception e) { throw new QueujException(e); } } if (parent_queue != null) return parent_queue.getBatchProcessServer(); // else throw new QueujException("No BatchProcessServer exists for Queue"); } /** * Gets the Queues default Occurrence. Will ask the parent Queue * to get its default Occurrence if this Queue doesn't have one. */ Occurrence getDefaultOccurrence() { if (default_occurence != null) return default_occurence; if (parent_queue != null) return parent_queue.getDefaultOccurrence(); return null; } /** * Gets the Queues default Visibility. Will ask the parent Queue * to get its default Visibility if this Queue doesn't have one. */ Visibility getDefaultVisibility() { if (default_visibility != null) return default_visibility; if (parent_queue != null) return parent_queue.getDefaultVisibility(); return null; } /** * Gets the Queues default Access. Will ask the parent Queue * to get its default Access if this Queue doesn't have one. */ Access getDefaultAccess() { if (default_access != null) return default_access; if (parent_queue != null) return parent_queue.getDefaultAccess(); return null; } /** * Gets the Queues default Resilience. Will ask the parent Queue * to get its default Resilience if this Queue doesn't have one. */ Resilience getDefaultResilience() { if (default_resilience != null) return default_resilience; if (parent_queue != null) return parent_queue.getDefaultResilience(); return null; } /** * Gets the Queues default Output. Will ask the parent Queue * to get its default Output if this Queue doesn't have one. */ Output getDefaultOutput() { if (default_output != null) return default_output; if (parent_queue != null) return parent_queue.getDefaultOutput(); return null; } public Map<String, Serializable> getImplementationOptions() { return implementation_options; } public boolean hasPredictableRestriction() { boolean isPredictable = restriction == null ? true : restriction.isPredictable(); if (isPredictable && parent_queue != null) return parent_queue.hasPredictableRestriction(); return isPredictable; } /** * Check with this Queue and the parent Queue whether the supplied Process can run. */ public boolean canRun(Process process) { boolean can_run = restriction == null ? true : restriction.canRun(process.getQueue(), process); if (can_run && parent_queue != null) return parent_queue.canRun(process); return can_run; } public boolean hasIndex() { return index != null; } public Object getIndexKey(Process process) { if (index == null) return null; return index.getKey(process); } private final static String new_line = System.getProperty("line.separator"); /** * Generate a unique String for this queue. Used for uniquely identifying * the properties of the Queue. */ @Override public String toString() { if (queue_string != null) return queue_string; queue_string = ""; if (parent_queue != null) queue_string = parent_queue.getParentString(); queue_string += "self" + getSelfString(); return queue_string; } /** * Get a short description of queue for debug (standard toString has many lines) */ public String getShortString() { return super.toString(); } /** * Get the unique Strings for the parent Queues. */ private String getParentString() { if (parent_queue == null) return "parent" + getSelfString(); return parent_queue.getParentString() + "parent" + getSelfString(); } /** * Get the unique String for this Queue. */ private String getSelfString() { String queue_string = " {" + new_line; if (restriction != null) queue_string += " restriction: " + restriction.toString() + new_line; if (index != null) queue_string += " index: " + index.getClass().getName() + new_line; if (!implementation_options.isEmpty()) queue_string += " implementation options: " + implementation_options.toString() + new_line; if (process_builder_class != null) queue_string += " process builder: " + process_builder_class.getName() + new_line; if (process_server_class != null) queue_string += " process server: " + process_server_class.getName() + new_line; if (default_occurence != null) queue_string += " default occurrence: " + default_occurence.toString() + new_line; if (default_visibility != null) queue_string += " default visibility: " + default_visibility.getClass().getName() + new_line; if (default_access != null) queue_string += " default access: " + default_access.getClass().getName() + new_line; if (default_resilience != null) queue_string += " default resilience: " + default_resilience.toString() + new_line; if (default_output != null) queue_string += " default output: " + default_output.getClass().toString() + new_line; return queue_string + "}" + new_line; } /** Private static Collection of queues and their id's. */ private final static FilterableArrayList queues = new FilterableArrayList(); /** * Set the unique id for this Queue. */ private static synchronized int setId(Queue queue) { String queue_string = queue.toString(); if (!queues.contains(queue_string)) queues.add(queue_string); return queues.indexOf(queue_string); } /** * Implement readObject to generate the unique id at deserialization. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); setId(this); } /** * Implement equals to use result of toString. */ @Override public boolean equals(Object object) { if (object == null || !(object instanceof Queue)) return false; Queue another = (Queue) object; return another.toString().equals(toString()); } /** * Implement hashCode to fulfil the contract of Object. */ @Override public int hashCode() { return toString().hashCode(); } }