blob: 2afd4abd920168da79a1aaf0697e53594ba81562 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.drill.exec.store.easy.json.parser;
/**
* Represents one level within array. The first time the parser sees the array element,
* it will call the {@link #element(ValueDef)} method with the
* look-ahead values visible to the parser. Since JSON is flexible, later
* data shapes may not necessarily follow the first shape. The implementation
* must handle this or throw an error if not supported.
* <p>
* When creating a multi-dimensional array, each array level is built one
* by one. each will receive the same type information (decreased by one
* array level.)
* <p>
* Then, while parsing, the parser calls events on the start and end of the
* array, as well as on each element.
* <p>
* The array listener is an attribute of a value listener, represent the
* "arrayness" of that value, if the value allows an array.
*
* <h4>Elements</h4>
*
* The array listener has a child listener that represents each element
* in the array. The structure parser asks this listener to create that
* child on the first element seen for the array. The structure parser
* provides "look-ahead" type information for that element, when available.
* <p>
* Three JSON-specific cases warrant attention:
* <ol>
* <li>The first occurrence of the array is empty: {@code [ ]}. In this case,
* the structure parser will defer asking for an element parser (and listener)
* until an actual value appears. The array listener is responsible for
* implementing some kind of "deferred type" logic to wait and see what
* kind of element appears later.</li>
* <li>The first occurrence of the array has, as its first element, a
* {@code null} value. The structure parser will ask this listener to create
* an array child for the {@code null} value, but the listener has no type
* information. Since null values must be recorded (so we know how many
* appear in each array), the listener is forced to choose a type. Choose
* wisely as there is no way to know what type will appear in the future.</li>
* <li>A generalized form of the above is that the structure parser only
* knows what it sees on the first element when it asks for an element
* child. In a well-formed file, that first token will predict the type
* of all future tokens. But, JSON allows anything. The first element
* might be {@code null}, an empty array, or a String. The second element
* could be anything else (a number or an object). The listener, as always
* is responsible for deciding how to handle type changes.</li>
* </ol>
*
* <h4>Multi-Dimensional Arrays</h4>
*
* A multi-dimensional array is one of the form {@code [ [ ... }, that is,
* the parser returns multiple levels of array start tokens. In this case,
* listeners are structured as:
* <ul>
* <li>{@code ObjectListener} for the enclosing object which has a</li>
* <li>{@code FieldListener} for the array value which has a</li>
* <li>{@code ArrayListener} for the array, which has a</li>
* <li>{@code ValueListener} for the elements. If the array is 1D,
* the nesting stops here. But if it is 2+D, then the value has a</li>
* <li>{@code ArrayListener} for the inner array, which has a</li>
* <li>{@code ValueListener} for the elements. And so on recursively
* for as many levels as needed or the array.</li>
* </ul>
*/
public interface ArrayListener {
/**
* Called at the entrance to each level (dimension) of an array.
* That is, called when the structure parser accepts the {@code [}
* token.
*/
void onStart();
/**
* Called for each element of the array. The array element is represented
* by its own listener which receives the value of the element (if
* scalar) or element events (if structured.)
*/
void onElementStart();
/**
* Called after each element of the array.
*/
void onElementEnd();
/**
* Called at the end of a set of values for an array. That is, called
* when the structure parser accepts the {@code ]} token.
*/
void onEnd();
}