.. Copyright 2023 NWChemEx-Project
..
.. Licensed 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.

.. _field_design:

#############################
Designing the Field Component
#############################

:ref:`property_type_design` and :ref:`module_design` both called for a
mechanism to handle fields.

****************************
What is the Field Component?
****************************

Modules are meant to be black-box functions which take all the input (inputs
and callbacks) they will need to compute their results. The inputs and
results are the fields. Since callbacks are passed as inputs we consider how
they are passed to be part of the field component, while the actual callback
mechanism falls to the call graph component (see :ref:`call_graph_design`).

******************************
Field Component Considerations
******************************

#. Work with arbitrary types.

   - Downstream users of PluginPlay should be able to use their native types.

#. Recognize differences between inputs and results.

   - Inputs can be by value or by read-only reference.
   - Results are always by value.
   - Note can move into a value argument.

#. Record provenance of inputs/results.

   - The inputs/results should hold metadata to sufficiently describe them.
   - Metadata can conceivably be used by callers of the module as a "tooltip"

#. Verify inputs satisfy bound constraints.

   - Associating checks with the field avoids waiting until the module runs to
     ensure the field's value is valid.
   - Used to prevent users from setting a field to an incorrect value (before
     the module tries to unwrap the input).

#. Leverage metadata to generate documentation.

   - Keeping documentation up to date with :ref:`api` changes can be tedious.
   - Generating documentation from metadata keeps code and documentation
     synched.

**********************
Field Component Design
**********************

.. _fig_field_design:

.. figure:: assets/field_design.png
   :align: center

   The three major components of PluginPlay's field component. ModuleInput/
   ModuleResult are responsible for respectively managing the inputs/results
   to/from a module and SubmoduleRequest is used to manage callback hooks.

:numref:`fig_field_design` shows the architecture of the field component.
The three major components, ``ModuleInput``, ``ModuleResult``, and
``SubmoduleRequest`` correspond to three major items passed into/from modules.
``ModuleInput``  manages an input to a module (the set of inputs passed to a
module will be a container of ``ModuleInput`` objects). In addition to the
type-erased input, which lives in the ``AnyField`` object, the ``ModuleInput``
also holds metadata (*e.g.*, a description, if the user set the value, is
the value :ref:`opaque`) and any bounds checks (*e.g.*, can the value be null,
is there a maximum/minimum for the value, what are the allowed strings). The
``ModuleResult`` is similar except it does not have bounds checks (the
module developer presumably is not trying to return invalid results). The
``SubmoduleRequest`` class is designed to hold a callback hook, and the callback
once it is set.

Summary
=======

#. Work with arbitrary types.

   - ``AnyField`` uses type-erasure to wrap whatever type the module developer
     and/or property type developer wants.
   - Types live in the module implementation or in the property type, both of
     which live downstream from PluginPlay.

#. Recognize differences between inputs and results.

   - ``ModuleInput`` and ``ModuleResult`` are different classes to better
     capture this point.

#. Record provenance of inputs/results.

   - All classes have metadata to record provenance.

#. Verify inputs satisfy bound constraints.

   - ``ModuleInput`` has the ability to store bounds checks the input values
     must satisfy.

#. Leverage metadata to generate documentation.

   - Not strictly part of the field component, but the field component exposes
     enough information for another component to generate the documentation.
