mbeckerle commented on code in PR #1246:
URL: https://github.com/apache/daffodil/pull/1246#discussion_r1618988571


##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/layers/api/Layer.java:
##########
@@ -27,51 +27,231 @@
 /**
  * This is the primary API class for writing layers.
  * <p>
- * All layers are derived from this class, and must have no-args default 
constructors.
+ * All layers are derived from this class.
  * <p>
- * Derived classes will be dynamically loaded by Java's SPI system.
- * The names of concrete classes derived from Layer are listed in a 
resources/META-INF/services file
- * so that they can be found and dynamically loaded.
+ * This class is used directly as a base class to define <i>transforming</i> 
layers.
+ * To simplify the
+ * definition of <i>checksum</i> layers, a specialized sub-class
+ * {@link org.apache.daffodil.runtime1.layers.api.ChecksumLayer}
+ * is also available.
+ * Many of the requirements for layers, such as the naming conventions for 
layer variables,
+ * are described here, but they apply equally to checksum layers.
+ * <p>
+ * Derived classes will be dynamically loaded by Java's Service Provider 
Interface (SPI) system.
+ * The names of concrete classes derived from Layer are listed in
+ * a metadata resource file
+ * named for this class (that is, the file name is the fully-qualified class 
name of this class:
+ * {@code 
resources/META-INF/services/org.apache.daffodil.runtime1.layers.api.Layer}).
+ * This file contains lines where each line contains one fully qualified class 
name of a derived
+ * layer class.
+ * More than one line in the file denotes that the Jar file contains the 
definitions of more than one derived layer
+ * class.
+ * This file is incorporated in the compiled jar file for the derived {@code 
Layer} class
+ * so that the class path can be searched and Jars containing layer classes 
can be dynamically loaded.
  * <p>
  * The SPI creates an instance the class by calling a default (no-arg) 
constructor, which should be
  * the only constructor.
  * <p>
- * Instances of derived layer classes can be stateful. They are private to 
threads, and each time a layer
+ * Instances of derived layer classes can be stateful.
+ * They are private to threads, and each time a layer
  * is encountered during parse/unparse, an instance is created for that 
situation.
  * <p>
- * Layer instances should not share mutable state (such as via singleton 
objects)
+ * Layer instances should not share mutable state (such as via singleton 
objects).
  * <p>
- * The rest of the Layer class implements the
- * layer decode/encode logic, which is done as part of deriving one's Layer 
class from the
- * Layer base class.
+ * <h2>About Layer Variables</h2>
  * <p>
- * About variables: Layer logic may read and write DFDL variables.
+ * Layer logic may read and write DFDL variables.
+ * These variables are associated with the layer implementation class by using
+ * Java/Scala reflection to find matches (case-sensitive) between the names of 
DFDL variables and method
+ * names and method arguments of the layer's Java/Scala code.
+ * Hence, the layer's DFDL variables must have names suitable for use as 
Java/Scala
+ * identifiers.
  * <p>
- * Every DFDL Variable in the layer's targetNamespace is used either at the 
start of the
- * layer algorithm as a parameter to the layer or at the end of the layer 
algorithm it is
- * assigned as a return value (such as a checksum) from the layer.
+ * The layer namespace is used only for its layer.
+ * All DFDL variables defined in that namespace are either used to pass 
parameters to the
+ * layer code, or receive results (such as a checksum) back from the layer 
code.
+ * This is enforced.
+ * If a layer namespace contains a DFDL variable and there is no corresponding
+ * usage of that variable name in the layer code (following the conventions 
below), then
+ * it is a Schema Definition Error when the layer code is loaded.
  * <p>
- * Variables being written must be undefined, since variables in DFDL are 
single-assignment.
+ * A layer that does not define any DFDL variables does
+ * not have to define a DFDL schema that defines the layer's target
+ * namespace, but any layer that uses DFDL variables *must* define a
+ * schema with the layer's namespace as its target namespace, and with the
+ * variables declared in it (using {@code dfdl:defineVariable}).
+ * </p>
+ * Every DFDL Variable in the layer's target namespace is used either at the 
start of the
+ * layer algorithm as a parameter to the layer or at the end of the layer 
algorithm where it is
+ * assigned a return value (such as a checksum or flag) from the layer.
  * <p>
- * Variables being read must be defined before being read by the layer, and 
this is true for both
- * parsing and unparsing. When unparsing, variables being read cannot be 
forward-referencing to parts
+ * Variables being read must have values before being read by the layer, and 
this is true for both
+ * parsing and unparsing.
+ * This happens when the Daffodil processor begins parsing/unparsing the 
layered sequence.
+ * When unparsing, variables being read cannot be forward-referencing to parts
  * of the DFDL infoset that have not yet been unparsed.
  * <p>
- * A layer that wants to read parameters declares special setter named 
'setLayerVariableParameters'
- * which has args such that each has a name and type that match a corresponding
- * dfdl:defineVariable in the layer's namespace.
+ * A layer that wants to read parameters declares a special setter named
+ * {@code setLayerVariableParameters}
+ * which has arguments where each has a name and type that match a 
corresponding
+ * {@code dfdl:defineVariable} in the layer's target namespace.
+ * <p>
+ * For example, if the layer logic has a DFDL variable for a parameter named 
{@code direction}
+ * of type {@code xs:string} and another DFDL variable for a parameter named 
{@code wordCount}
+ * of type {@code xs:unsignedShort}
+ * then the derived Layer class must have a {@code setLayerVariableParameters} 
with
+ * arguments corresponding in name and type to these two variables.
+ * This setter will be called passing the value of the variables immediately 
after the layer
+ * instance is constructed.
+ * The arguments to {@code setLayerVariableParameters} can be in any order:
+ * <pre>
+ *     void setLayerVariableParameters(String direction, int wordCount) {
+ *         // usually this setter will assign the values to data members
+ *         this.direction = direction;
+ *         this.wordCount = wordCount;
+ *     }
+ * </pre>
+ * Beside initializing local members, this setter is also an initializer for 
the layer class instance.
+ * Any exception thrown becomes a Schema Definition Error.
+ * <p>
+ * If there are no parameter variables, then this setter, with no arguments, 
can be used purely for initialization.
  * <p>
- * A layer that wants to return a value after the layer algorithm completes 
defines a special recognizable
- * getter method. The name of the getter is formed from prefixing the DFDL 
variable name with the string
- * 'getLayerVariableResult_'. The return type of the getter must match the 
type of the variable.
+ * A DFDL variable used to return a result from a layer must be undefined, 
since variables in DFDL are single-assignment.
+ * Usually this means the use of the layer must be surrounded by a {@code 
dfdl:newVariableInstance}
+ * annotation which creates a new instance of the layer result variable, over 
a limited scope
+ * of use.
+ * The variable is assigned by the layer, and it is then available for reading 
by the DFDL schema until
+ * the end of the {@code dfdl:newVariableInstance} scope.
  * <p>
- * For example, a result value getter for a DFDL variable named 'checksum' of 
type xs:unsignedShort would be:
+ * To return a value into a DFDL variable, the layer implementation defines a 
special recognizable
+ * getter method.
+ * The name of the getter is formed from prefixing the DFDL variable name with 
the string
+ * "{@code getLayerVariableResult_}".
+ * The return type of the getter must correspond to the type of the variable.
+ * <p>
+ * For example, a result value getter for a DFDL variable named {@code total} 
of type {@code xs:unsignedShort} would be:
  * <pre>
- *      int getLayerVariableResult_checksum() {
- *          // returns the value created by the checksum algorithm.
+ * {@code
+ *      int getLayerVariableResult_total() {
+ *          // returns the value created by the layer's algorithm.
+ *          // commonly this returns the value of a data member.
+ *          return this.total;
  *      }
+ * }
  * </pre>
+ * Layers could have multiple result variables, but a single variable is most 
common, generally for returning checksums.
+ * See the {@link ChecksumLayer} class, which is designed to facilitate 
creation of checksum/CRC/hash/digest layers.
+ * <p>
+ * The Java types to use for the setter arguments and getter return types 
correspond to the DFDL variable types
+ * according to this table:
+ * <table border="1">
+ *     <tr>
+ *         <th>DFDL Schema Type</th>
+ *         <th>Java Type</th>
+ *     </tr>
+ *     <tr>
+ *         <td>xs:byte</td>
+ *         <td>byte</td>
+ *     </tr>
+ *     <tr>
+ *         <td>xs:short</td>
+ *         <td>short</td>
+ *     </tr>
+ *     <tr>
+ *         <td>xs:long</td>
+ *         <td>long</td>
+ *     </tr>
+ *     <tr>
+ *         <td>xs:int</td>
+ *         <td>java.math.BigInteger</td>

Review Comment:
   Hmmm. I will check the code and/or fix this doc. xs:integer should have a 
mapping to java.lang.BigInteger and xs:int to int. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to