001    /*
002    // $Id: CellSetListener.java 482 2012-01-05 23:27:27Z jhyde $
003    //
004    // Licensed to Julian Hyde under one or more contributor license
005    // agreements. See the NOTICE file distributed with this work for
006    // additional information regarding copyright ownership.
007    //
008    // Julian Hyde licenses this file to you under the Apache License,
009    // Version 2.0 (the "License"); you may not use this file except in
010    // compliance with the License. You may obtain a copy of the License at:
011    //
012    // http://www.apache.org/licenses/LICENSE-2.0
013    //
014    // Unless required by applicable law or agreed to in writing, software
015    // distributed under the License is distributed on an "AS IS" BASIS,
016    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017    // See the License for the specific language governing permissions and
018    // limitations under the License.
019    */
020    package org.olap4j;
021    
022    import java.util.List;
023    
024    /**
025     * Listener interface for receiving events when the contents of a
026     * {@link CellSet} have changed.
027     *
028     * <p>NOTE: This functionality is experimental and is subject to change or
029     * removal without notice.
030     *
031     * <p>The client can ask the server to provide the listener with a specific
032     * {@link Granularity granularity} of events, but the server can decline to
033     * provide that granularity.
034     *
035     * <p>Fine granularity deals with changes such as cell values changing (and
036     * reports the before and after value, before and after formatted value),
037     * positions being deleted, positions being changed.
038     *
039     * <p>When an atomic change happens on the server (say a cache flush, if the
040     * server is mondrian) then an event will arrive on the client containing all of
041     * those changes. Although {@link CellSetChange#getCellChanges} and
042     * {@link CellSetChange#getAxisChanges} return lists, the client should assume
043     * that all of the events in these lists simultaneously.
044     *
045     * <p>At any point, the server is free to throw up its hands and say 'there are
046     * too many changes' by sending null values for {@code getCellChanges} or
047     * {@code getAxisChanges}. This prevents situations where there are huge numbers
048     * of changes that might overwhelm the server, the network link, or the client,
049     * such as might happen if a large axis is re-sorted.
050     *
051     * <p>The client should always be ready for that to happen (even for providers
052     * that claim to provide fine granularity events), and should re-execute the
053     * query to get the cell set. In fact, we recommend that clients re-execute the
054     * query to get a new cellset whenever they get an event. Then the client can
055     * use the details in the event to highlight cells that have changed.
056     *
057     * <h3>Notes for implementors</h3>
058     *
059     * <p>The purpose of registering a listener before creating a cell set is to
060     * ensure that no events "leak out" between creating a cell set and registering
061     * a listener, or while a statement is being re-executed to produce a new cell
062     * set.
063     *
064     * <p>The {@link #cellSetOpened(CellSet)} and {@link #cellSetClosed(CellSet)}
065     * methods are provided so that the listener knows what is going on when a
066     * statement is re-executed. In particular, suppose a statement receives an
067     * change event decides to re-execute. The listener is attached to the
068     * statement, so receives notifications about both old and new cell sets. The
069     * driver implicitls closes the previous cell set and calls
070     * {@code cellSetClosed}, then calls {@code cellSetOpened} with the new cell
071     * set.
072     *
073     * <p>If changes are occurring regularly on the server, there will soon be a
074     * call to {@link #cellSetChanged}. It is important to note that this event
075     * contains only changes that have occurred since the new cell set was opened.
076     *
077     * <p>The granularity parameter is provided to {@link OlapStatement#addListener}
078     * for the server's benefit. If granularity is only {@link Granularity#COARSE},
079     * the server may be able to store less information in order to track the cell
080     * set.
081     *
082     * @version $Id: CellSetListener.java 482 2012-01-05 23:27:27Z jhyde $
083     */
084    public interface CellSetListener {
085    
086        /**
087         * Invoked when a cell set is opened.
088         *
089         * @param cellSet Cell set
090         */
091        void cellSetOpened(CellSet cellSet);
092    
093        /**
094         * Invoked when a cell set is closed.
095         *
096         * @param cellSet Cell set
097         */
098        void cellSetClosed(CellSet cellSet);
099    
100        /**
101         * Invoked when a cell set has changed.
102         *
103         * @param cellSetChange Change descriptor
104         */
105        void cellSetChanged(CellSetChange cellSetChange);
106    
107        /**
108         * Granularity of notifications that should be sent to a cellset listener.
109         */
110        enum Granularity {
111            FINE,
112            COARSE
113        }
114    
115        /**
116         * Description of changes that have occurred to the cell set.
117         */
118        interface CellSetChange {
119            /**
120             * Returns the cell set affected by this change.
121             *
122             * @return Cell set affected by this change.
123             */
124            CellSet getCellSet();
125    
126            /**
127             * Returns a list of cells that have changed, or null if the server
128             * cannot provide detailed changes.
129             *
130             * <p>The server is always at liberty to provide a {@code CellSetChange}
131             * without a detailed list of changes, even if
132             * {@link Granularity#COARSE} was specified when the listener was
133             * attached. Here are some typical reasons:<ul>
134             *
135             * <li>If there are very many changes. (Transmitting these changes over
136             * the network would be costly, and the user interface also might
137             * struggle to redisplay so many cells.)
138             *
139             * <li>If the axes have changed significantly. (If an axis position has
140             * changed, all of the cells at that position will necssarily have
141             * changed.)
142             *
143             * <li>If the client did not ask for detailed changes
144             *
145             * <li>If the the provider is not capable of giving detailed changes.
146             * </ul>
147             */
148            List<CellChange> getCellChanges();
149    
150            /**
151             * Returns a list of axis changes, or null if server cannot provide
152             * detailed changes.
153             *
154             * <p>The reasons why this method returns null are similar to the
155             * reasons why {@link #getCellChanges()} returns null.
156             *
157             * @return List of changes to positions on axes, or null if the server
158             * cannot provide detailed changes.
159             */
160            List<AxisChange> getAxisChanges();
161        }
162    
163        /**
164         * Description of a change to a particular {@link Cell}; part of a
165         * {@link CellSetChange}.
166         */
167        interface CellChange {
168            /**
169             * Returns the cell before the change.
170             */
171            Cell getBeforeCell();
172    
173            /**
174             * Returns the cell after the change.
175             */
176            Cell getAfterCell();
177        }
178    
179        /**
180         * Description of a change to a particular {@link CellSetAxis}; part of a
181         * {@link CellSetChange}.
182         */
183        interface AxisChange {
184            /**
185             * Returns the axis affected by this change.
186             *
187             * @return Axis affected by this change
188             */
189            CellSetAxis getAxis();
190    
191            /**
192             * Returns the position before the change. Null if the change created a
193             * new position.
194             *
195             * @return Position before the change, or null if the position is newly
196             * created
197             */
198            Position getBeforePosition();
199    
200            /**
201             * Returns the position after the change. Null if the change deleted
202             * this position.
203             *
204             * @return Position after the change, or null if the position is deleted
205             */
206            Position getAfterPosition();
207        }
208    }
209    
210    // End CellSetListener.java