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*/ 020package org.olap4j; 021 022import 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 */ 084public 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