001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.poifs.eventfilesystem;
019:
020: import java.util.*;
021:
022: import org.apache.poi.poifs.filesystem.DocumentDescriptor;
023: import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
024:
025: /**
026: * A registry for POIFSReaderListeners and the DocumentDescriptors of
027: * the documents those listeners are interested in
028: *
029: * @author Marc Johnson (mjohnson at apache dot org)
030: * @version %I%, %G%
031: */
032:
033: class POIFSReaderRegistry {
034:
035: // the POIFSReaderListeners who listen to all POIFSReaderEvents
036: private Set omnivorousListeners;
037:
038: // Each mapping in this Map has a key consisting of a
039: // POIFSReaderListener and a value cosisting of a Set of
040: // DocumentDescriptors for the documents that POIFSReaderListener
041: // is interested in; used to efficiently manage the registry
042: private Map selectiveListeners;
043:
044: // Each mapping in this Map has a key consisting of a
045: // DocumentDescriptor and a value consisting of a Set of
046: // POIFSReaderListeners for the document matching that
047: // DocumentDescriptor; used when a document is found, to quickly
048: // get the listeners interested in that document
049: private Map chosenDocumentDescriptors;
050:
051: /**
052: * Construct the registry
053: */
054:
055: POIFSReaderRegistry() {
056: omnivorousListeners = new HashSet();
057: selectiveListeners = new HashMap();
058: chosenDocumentDescriptors = new HashMap();
059: }
060:
061: /**
062: * register a POIFSReaderListener for a particular document
063: *
064: * @param listener the listener
065: * @param path the path of the document of interest
066: * @param documentName the name of the document of interest
067: */
068:
069: void registerListener(final POIFSReaderListener listener,
070: final POIFSDocumentPath path, final String documentName) {
071: if (!omnivorousListeners.contains(listener)) {
072:
073: // not an omnivorous listener (if it was, this method is a
074: // no-op)
075: Set descriptors = (Set) selectiveListeners.get(listener);
076:
077: if (descriptors == null) {
078:
079: // this listener has not registered before
080: descriptors = new HashSet();
081: selectiveListeners.put(listener, descriptors);
082: }
083: DocumentDescriptor descriptor = new DocumentDescriptor(
084: path, documentName);
085:
086: if (descriptors.add(descriptor)) {
087:
088: // this listener wasn't already listening for this
089: // document -- add the listener to the set of
090: // listeners for this document
091: Set listeners = (Set) chosenDocumentDescriptors
092: .get(descriptor);
093:
094: if (listeners == null) {
095:
096: // nobody was listening for this document before
097: listeners = new HashSet();
098: chosenDocumentDescriptors
099: .put(descriptor, listeners);
100: }
101: listeners.add(listener);
102: }
103: }
104: }
105:
106: /**
107: * register for all documents
108: *
109: * @param listener the listener who wants to get all documents
110: */
111:
112: void registerListener(final POIFSReaderListener listener) {
113: if (!omnivorousListeners.contains(listener)) {
114:
115: // wasn't already listening for everything, so drop
116: // anything listener might have been listening for and
117: // then add the listener to the set of omnivorous
118: // listeners
119: removeSelectiveListener(listener);
120: omnivorousListeners.add(listener);
121: }
122: }
123:
124: /**
125: * get am iterator of listeners for a particular document
126: *
127: * @param path the document path
128: * @param name the name of the document
129: *
130: * @return an Iterator POIFSReaderListeners; may be empty
131: */
132:
133: Iterator getListeners(final POIFSDocumentPath path,
134: final String name) {
135: Set rval = new HashSet(omnivorousListeners);
136: Set selectiveListeners = (Set) chosenDocumentDescriptors
137: .get(new DocumentDescriptor(path, name));
138:
139: if (selectiveListeners != null) {
140: rval.addAll(selectiveListeners);
141: }
142: return rval.iterator();
143: }
144:
145: private void removeSelectiveListener(
146: final POIFSReaderListener listener) {
147: Set selectedDescriptors = (Set) selectiveListeners
148: .remove(listener);
149:
150: if (selectedDescriptors != null) {
151: Iterator iter = selectedDescriptors.iterator();
152:
153: while (iter.hasNext()) {
154: dropDocument(listener, (DocumentDescriptor) iter.next());
155: }
156: }
157: }
158:
159: private void dropDocument(final POIFSReaderListener listener,
160: final DocumentDescriptor descriptor) {
161: Set listeners = (Set) chosenDocumentDescriptors.get(descriptor);
162:
163: listeners.remove(listener);
164: if (listeners.size() == 0) {
165: chosenDocumentDescriptors.remove(descriptor);
166: }
167: }
168: } // end package scope class POIFSReaderRegistry
|