MIC-HTML 3.0 Programming Interface
Copyright (c) 1999 FundsXpress Financial Network, Inc.
This draft is confidential property of FundsXpress, Inc.
Sam Hartman
Charles Lowell
Zane Rockenbaugh
Abstract:
MIC, or Mesa Interface Compiler, is a tool meant to simplify Web
interface design. MIC allows the embedding of Perl code and special
MIC tags into an otherwise normal HTML document. The MIC code is then
(com)piled by MIC to produce what is known as a pile (a partial CGI
script) which is run via a pile driver.1
One central idea of MIC is to take the awkward HTML out of CGI and put
the power of CGI into HTML. This is accomplished by providing
HTML-like tags, which controls page look and data presentation, and the full functionality of CGI scripting in a simpler, more familiar
environment. MIC can be thought of as a tool for creating dynamic HTML
pages. In fact, MIC pages (i.e., HTML pages with MIC code) can be viewed
directly in a standard HTML browser and will produce sensible,
though probably not very pretty, results.
There are many other advantages that MIC has over standard CGI
scripting, such as automation of security, field propagation and
other features that are built into MIC.
Using This Document
This document is both a reference guide and a tutorial. If you are
just learning MIC, you might find many of the concepts in this document a bit unclear at first.
It is recommended that new users of the system first skim through the examples
found at the end, read the Overview chapter, then skim
through the Conceptual MIC chapter and the Using MIC chapter2. Skimming the Suggested MIC-Compliant
Datatype and FieldSpace Specification chapter (Appendix
C) is also a good idea, as long as the
new user takes note of the introduction to this section. Then, one
should familiarize themselves with the various MIC tags, and then return for a more in-depth reading of the document.
Experienced users will find the document more helpful as a reference
manual. The MIC Tags chapter has the syntax and description of
each tag. The Cross Interface Requirements chapter might
be useful to the experienced developer, but it is meant primarily as
an implementation guide for the subsystems utilized by MIC. It is not
really a user interface spec as it is a MIC interface spec.
- 1
- The pile is a partial
CGI script because it is not runnable by itself and requires a
piledriver for execution.
- 2
- The MIC Style Guidlines provide much useful
insights into using MIC.
Table of Contents
1.1 What MIC Does
Much of any Web interface is going to be a lot of HTML. If one is
using traditional CGI programing, this means an endless repetition of
print statements, here docs, or function calls punctuated by
code. With MIC, the HTML portions of your page become simple, you
write them just as you would any other. It is also trivial to take a
concept or template page and make it into a fully functional
interface. You need only embed the logic; the HTML will work just as
it is. In fact, the completed MIC site source is logically laid out,
as the user would think of it, in pages.
Though MIC is certainly useful on any size site or project, it is most
useful in producing large interfaces which span many logical
pages. MIC allows the programmers to treat the interface on a page per
page basis; thus, site design and CGI programming are brought closer
together. Besides this, however, MIC natively provides many useful
features that enhance productivity and security.
Security
With MIC, one is able to associate user data with
arbitrary1
datatypes and perform arbitrary verification on the user supplied
data. A good datatype will implement standard checks to further ease this process.
Furthermore, MIC will take note of what data is being asked for and
only allow that data to be changed. Thus, MIC coders know what to
expect and when to expect it. And since verification has been done by
the time it gets to the developer's code, they can trust that the data
is atleast as good as the verification procedures.
Productivity
One of the biggest advantages of MIC is native support for data
propagation. So that data is not lost, all data entered into the
fields of that fieldspace will be automatically propagated along an
unbroken chain of pages which all use a given fieldspace2. This allows
the generation of multiple page forms without worry about manual
propagation.
Another important feature in MIC3 is its native support for robust error
reporting and tracking. This allows a MIC-coded interface to easily
resolve, report and prompt users to fix error conditions in user supplied data.
Finally, MIC has native support for dynamically generated
fields. This allows users to enter as many logically-connected
clusters of data as the MIC coder desires. That is, given a
field template and rule, MIC will generate the necessary data fields
as necessary. For example, we might use MIC to create a Web-based phone
book, which could handle the addition and display of new entries. We
define two fields, name and number, in a dynamic context (covered
later). We tell MIC to display as many such clusters as are requested.
In this example, we decide to display ten clusters at a time. The user would
then get a page of ten name/number field clusters. They can enter
data, then page on to the next set of ten clusters. Thus, users could
enter 1, 100 or 1,000,000 bits of data, all using the same code.
1.2 Components of MIC
1.2.1 The `Site': MIC-HTML
To create a MIC pile, one creates a series of MIC-HTML pages, which
may or may not have MIC-specific tags. All these pages must be under
an arbitrary directory which we will call the Root-pile
directory. When it is time to compile, the path to the Root-pile
directory is given to the MIC-compliant piler, and it will then
recursively process all pages under this directory which have a .html,
.HTML, .mic, .MIC, .fs or .FS extension. Be aware that all other pages will
be ignored unless explicitly included in a parsed file (by use of the
MICinclude tag).
1.2.2 The Control File
A control file is a file which, by convention, contains all the
special MIC-defined subroutines setup, cleanup and
handle_exception, which are useful programs to have for a given
pile. 4 These special files are discussed in detail later.
The control file must be named 'control.pl' and will be copied
literally into the pile. This means that one should not HTML-escape
within this file, since it is pure Perl code. One may wish to put some
library subroutines in this file, although this is discouraged unless
the subroutines are used directly and primarily by the special
MIC-defined subroutines mentioned above. The recommended way of
including library functions for use in the MIC code is to place the
library file at the top of the control file and then calling the functions normally.
1.2.3 The Piler and the Driver
A compliant MICpiler takes all the .mic, .html, .fs5 and the optional
control file (and other MICincluded files) to produce a pile. The pile
should contain all the information necessary to properly execute the
site, generate errors, control flow, etc. This pile is run by the
Pile-Driver which interprets the code contained within the pile. The
compiler must produce valid Perl code that conforms to the
specifications in this document and is suitable to be run by an
executable that conforms to the MIC-Driver specification
(B). The driver component on the MIC system is the
program that a Web server (or some other program) uses to execute the code contained within the pile.
- 1
- Arbitrary as long as they comply to the
MIC-Datatype Interface Specification; see C
- 2
- A
logical grouping of data fields covered later.
- 3
- Introduced in MIC 2.0, and
refined in version 2.1.
- 4
- Note that the MIC spec does not require the user to have these
subroutines in their piles, nor are they required for the
proper functioning of the interface or the program.
- 5
- Suffixes
are case-insensitive.
MIC 3.0 designed on four basic concepts:
- HTML-like embedded logic and pages as functions
- associating forms with `fieldspaces'
- providing support for error verification and reporting
- providing native and automatic security features and data
integrity features
In a sense, MIC extends HTML with the above ideas. Of course, that
analogy hardly does MIC justice.
2.1 HTML-Like Embedded Logic and Pages as Functions
The idea here is to simply add logic to to HTML pages which allow for
conditional display and/or processing and to encapsulate pages into
functions. The usefulness of this approach is shared code (HTML or
otherwise) and more powerful, rich, and useful behavior of the pages
without the clunkiness of CGI programming. Studying the
example found in E.1 should provide
sufficient insight into the meaning of this concept.
2.2 FieldSpaces and Forms
While not all forms must be associated with a fieldspace (see section
3.2.2, it is possible to do so using MIC. Associating a fieldspace with a form means that the data collected
in the fields of the form is stored not only in the CGI object, but is
also stored in a Fieldspace object. There may be numerous effects to
this approach depending upon the implementation of the fieldspace and other
factors. For example, it may cause updates in a database so that if a user's
computer crashes, the user can restart their session right where they left
off. Apart from that, all fieldspaces form the basis for most of MICs
more powerful features, aside from embedded logic.
All fieldspaces, no matter their implementation, are the basis of
data verification and management, error reporting, etc. There are
three central concepts concerning fieldspaces themselves:
- fields and associated data types
- static fields
- dynamic fields
2.2.1 Fields and Data Types
A fieldspace contains, among other things, fields. Fields are
associated with HTML input fields and are usually affected by user
inputs1. Thus, it is best to think of fields as more
or less the encapsulation of HTML input controls (readers will often
find the terms used interchangebly).
MIC requires that every field be associated with a data type. The data
type specifies what type of data to expect (e.g., a number, a name, a
US state abbreviation, etc.), and how to display it. This is how error
verification is handled2. It
is through these fields, accessed through the fieldspace object, that
data is most often manipulated and viewed within MIC.
2.2.2 Static Fields
There are two broad types of fields, static and dynamic. These names
do not mean constant and variable, but are more closely related to an
idea of static forms and dymamic forms.
A static field is one for which there will be only one
instance. Drawing from HTML, if one were coding a form in HTML, all
the inputs (i.e., fields) would be static. The distinction will be
made more clear in the next section.
2.2.3 Dynamic Fields
A dynamic field is best thought of in context of a dynamic form. A
dynamic form is a form for which the number (but not the type) of
inputs is unknown. A form to enter the number of new members to club
might be a good candidate. Their might be one, two, or 100 new
members. In this example, one could use statics, with member1,
member2, etc. and just have an ``Add More'' and ``Done'' button, but
there are other cases where such behavior is harder to code with
statics (or standard CGI scripting) and dynmaics become far more
attractive. This is especially so when tries to support error checking
and reporting for the above mini-example.
Dynamic fields are coded somewhat as templates, and then instantiated
as needed based on certain varying parameters, namely their index
number and the value of the parameter num_display, which is covered
in later discussions regarding dynamic fields. A single template can
be coded and one, 100, or a million different fields can be created,
tracked, reported and managed. This is especially useful when users
are accessing existing data and want it displayed to them.
2.3 Error Verification and Reporting
MIC provides numerous and rich facilities for data verification and
error reporting. This was one of the primary forces behind the
creation of MIC and was greatly expanded with MIC 2.0.
2.4 Native Security and Data Integrity Features
The idea here is to provide some basic security features that one
would desire on all pages and make them automatic. This includes such
things as helping to ensure data integrity and program flow.
One big concern with going through HTML is handling proper escaping
and unescaping so that the user sees the proper value and the program
sees the proper data. That is, if the user puts in <, we want the
user and data to (usually) see < and not `<.'
- 1
- It is possible, however, to have fields that are completely
affected by programmatic inputs (i.e., the program takes their values
from other fields, etc.)
- 2
- Any proper implementation
of a data type system should have a type that accepts all inputs.
3.1 Execution Flow
Of course, it is important to understand how the myriad of pages,
fieldspaces and bits will be executed. The first thing that
happens when a page is requested is that the web server will receive
the request and do its thing. Presumably, it will have some way of
knowing that the request should be handled by a pile, say an extension
or a certain directory and will redirect the request to the pile
driver.
The pile driver then picks it up and will do its stuff. As far as the
MIC coder's code goes, this involves:
- the setup subroutine in the control file is called
- the page (.html or .mic) is called
- if there is a form tag which has a MICfieldspace associated with
it, then:
- the code within the MICfieldspace tags, but external to all
groups and all MICdefines is called (this is the fieldspace setup
code)
- if one or more dynamic field groups are requested or mandated to
be instantiated, then the group setup code is executed for each, with
the appropriate index number being specified as is proper for the
above mentioned field groups; the resulting object definition, if any,
is retained for the next step
- all field default code, both static and dynamic, is called
unless MIC finds any given field to be internally maintained, in which
case the initial value is loaded from some external, fieldspace
implementation specific data retention object (e.g., a CGI object or a
database table)
- all arbitrary field code is run for instantiated objects
- the cleanup routine is called
For more on the rules and specification governing fieldspaces and
forms, see section 4.3 for more on forms, section ?? for more on default and arbitrary field code, and section ?? for specifics on MIC-compliant fieldspace
implementations.
3.2 Writing Pile Source
3.2.1 Special Consideration
Because MIC is meant to be HTML-like and somewhat viewable by an HTML
browser, it is necessary that all MIC code be HTML-escaped. How to and
what to HTML-escape is not covered in this document, but users of MIC
must be familiar with it.1
Do not confuse literal double quotes, < and > symbols with HTML
control characters. For example,
<MICwhile test="test()">
hello
</MICwhile>
Before discussing style and MIC coding standards, it should be
mentioned that MIC currently has no native commenting. Commenting can
be done through either Perl commenting (while within a MICPerl tag),
or with HTML comments. Note that HTML comments, however, will be
viewable in the final product. Thus, sensitive information should not
be mentioned.
3.2.2 Style Guidlines
MIC style is compilicated by the fact that it involves not only HTML,
but also logic and control code. Thus, one must approach the problem
with an open mind. The following guidlines are the result of working
with MIC and, thus, are in evolution. They are by and large, the work
of Mr. Rockenbaugh and stem from his experience with MIC. As MIC comes
to be used by others in different situations, it may certainly be
found that the suggestions laid out here are non-optimal.
MIC versus HTML
As noted above, the compiler will take direct cognizance of files
ending in .html, .mic, and .fs (case-insensitively). Now the purpose of
the latter two is clear and distinct. These files should (though,
they are not required) to contain the definition for a single
fieldspace.2
The difference between the code within the other two types, .mic and
.html, is not so clear cut. Both types will be compiled into viewable
pages, and in this respect, are the same as far as the compiler and
driver are concerned. Stylistically, however, most pages should
probably be of the .html type.
The .mic extensions should be used consistently within a site. Beyond
that, they should, if nothing else, indicate ancillary pages that are
mostly perl code. For instance, a page whose purpose is to look at
state and direct users to another page (without accepting any user
input or doing much output) could qualify for a .mic extension.
Indentation
Proper indentation of a MIC page is one of the harder things to
do. The main reason for this is that while HTML can be indented on
conceptual groups, such as a table, rows, blockquotes, etc., and Perl
and programming languages can be indented on logic blocks and lexical
groups, how one properly indents a mixture of the two is a hard
question.
In general, one must be more conservative about what is indented so
that there is still room to indent when one wants to indent. Logical
indentation should be favored over layout indentation, though large
conceptual groups in the layout scheme should be indented for clarity,
and these will often closely correspond to a logical block in any
case.
A good MIC mode for emacs and/or other editors would be helpful as
font coloring would add another dimension to the indentation scheme
and make groupings clearer. For the time being, practice and common
sense are the best guides.
Be Strict: Variable Management
Since MIC 2.0, compliant compilers must produce code that, if source
code cooperates, be strictifiable. That is, MIC will introduce no
undeclared or unscoped global variables. Since global variable errors
have been found to be easy to produce and sometimes hard to identify,
it is highly recommended that all but a few special variables be
scoped to the page. To strictify a pile, one should include a 'use
strict;' statement at the top of the control file.
One should think of each of the following as a
lexical block:
- each .html or .mic page
- all code within a given MICfieldspace tag, but external to all
MICdefine and MICgroup tags within the MICfieldspace tag
- all code within a given MICgroup tag, but external to all
MICdefine and contained MICgroup tags
- all code within the default block within a given MICdefine
- all code within the setup (a.k.a. arbitrary) block within a
given MICdefine
When, out of necessity or for the sake of efficiency, one wishes to
pass variables between these lexical blocks, there are two
recommended, but dependant, methods. The first is to include the 'use
vars...;' statement after the 'use strict;' statement and simply have
the listed variables be global. If this is done, be sure and include
the special cleanup subroutine in the control file and undef each of
the declared variables. This is to ensure that global state errors do
not occur even when a FastCGI server is used to call the pile.3
There are two established cases where one should declare a global
variable in this fashion. The first is to make global common objects
or state indicators that will be needed by virtually every page and
fieldspace.
For instance, if one were designing an interface to a MUD, then we
might expect a Player object to be needed for the logic of virtually
every page and fieldspace. To make said object available, we would do
something like the following in the control file:
use strict;
use vars qw($player);
...
sub setup {
#$cgi is made available by the pile driver
my $player_id = get_player_id_from_cookie($cgi);
$player = find Player($player_id);
...
}
sub cleanup {
undef $player;
...
}
...
The second established use for global variables is the use of a global
variable used to pass information from one lexical block (see above)
to another. This is often done for the sake of efficiency as it turns
that a given page and its associated fieldspace (if there is one),
will often have need of the same information. Also, the code within a
MICdefine will very often require some of the same information that is
determined in the MIC code in a different lexical block.
By convention, this special variable is called '%pf_box,' which
stands for 'page/fieldspace box.' Examples of how to use %pf_box can
be found in various portions of this document.
Top of Page Code
Generally, if there is any setup or variables that need to be set up
for a page, then these should be handled at the top of the page, as
far as is possible and sensible. Variables local to the page should be
declared, and if possible, set up at this point. This is to allow the
page to be as much straight HTML, MIC logic-controls and snippets as
possible (without random MICperl's and such floating around).
MIC versus CGI data
By MIC data, we mean MIC fieldspaces. CGI data is the data found in
HTML input controls. Both methods of passing and accessing data are
available in MIC and each still have their place. There are two
schools of thought on the subject.
The first is to only use the MIC facilities. That is, to have
everything in fieldspaces and accessed through MIC functions.
The other method, preferred by the author, is to use MIC data for all
user manipulated data and use HTML/CGI data for all flag data, or data
that is never manipulated by the user or attached to user manipulated
data. The advantage of this method is not usability or ease of use,
but to maintain a logical division. Also, it has been found that this
flag data can cross fieldspaces.
MIC versus HTML Forms
MIC provides many useful features regarding field management and such,
but does allow one to use standard HTML forms. It used to be that you
had to use standard functions in order to change directories
properly. This is fixed in the latest release, but standard forms
might still be used in order to reduce overhead for simple functions
where MIC's advanced features are not necessary.
3.3 Compiling a MIC Pile
The syntax for compiling a MIC pile is:
micpiler [-I <absolute include path from machine root>]
<pile name> <output file name> <root of the pile source>
The optional -I argument specifies the directory to look for MIC
included files (see 4.5.1) when they are not found in
the proper place in the pile source.
The name of the pile is used internally, but, for convention sake,
should be related to the output file's name (which may be specified in
a relative fashion). The output file name should generally be the pile
name with a `.pile' appended to it. The `.pile' is the recommended
extension used by servers to redirect proccessing to the piledriver
(or a similiar script to handle the running of piles).
Finally, one must specify the root of the pile source. The compiler
will start at this point (which may be specified relative to the
current directory) and recursively traverse the subdirectories
proccessing all files ending in `.html,' `.mic,' or `.fs'.
Compilers may take further options. See the compiler documentation for
additional information.
- 1
- Do not escape the control file,
however, since it is pure Perl code.
- 2
- Fieldspace definitions elsewhere will actually be
potent, but it is considered bad style.
- 3
- If,
for some reason, you wish to maintain state between page calls, then
you not want to undef your globals. This should be done very
carefully, however, and is rarely ever needed or preferred to
alternative methods.
By (enforced) convention, most MIC-specific tags begin with
`MIC.'1 The few tags which do not begin
with MIC are only found and are only valid within other MIC container
tags. This helps to ensure that they will not be overrun by future
HTML or browser extensions. There are basically three types of MIC
tags. The first, a code snippet tag, is the only one that does not
emulate HTML tag syntax and look. A second tag, the MICPerl tag, is
for general purpose coding. There a number of other tags, however,
that perform functions that could be coded directly in Perl, but which
are so common as to be supported directly by MIC in order to maintain
HTML consistency and ease the task of MIC markups.
Of these tags, some control program flow and page logic, such as
MICif. Others are used within forms to display values or set up submit
buttons.
4.1 Coding Tags
4.1.1 Perl Snippets
Syntax
[+ arbitrary evaluatable Perl token +] |
(HTML-escapes) |
[- arbitrary evaluatable Perl token -] |
(URI-escapes) |
[= arbitrary evaluatable Perl token =] |
(verbatim) |
Description
The Perl snippet mark is really not a tag, but simply declares a place
to insert some arbitrary Perl code. The code cannot be greater than
one line in length; that is, any code that requires a `;' must go in a
MICPerl and not a snippet. In fact, the `;' is optional in the
snippet.
Most generally, the snippet is used to print some value to the
page. This value may or may not be viewed by the final user. That is,
it could be used in an HTML link or what not. The three tags differ in
their output. The first ( [+ ... +] ) will HTML-escape the result of the
Perl code; it is therefore almost always the right thing to use except
in links. The second ( [- ... -] ) will URI-escape, so it is almost
always the right thing to use in links (and not elsewhere). The third
( [= ... =] ) does not process the code's output and is rarely if ever
appropriate.
Normally, code snippets will be inserted within an HTML document where
it is advantageous to maintain the look of the document, yet there is
some variable fragment which needs to be resolved at run-time (when a
user actually views the page). For example, one might have something
like:
Hello [+ $name +], how are you doing today?
or
<a href=http://[- $server || $default -]/face.html?flag=[- $flag -]>
Two notable limitations of the snippet are that commenting them out in
any fashion will not prevent the code within from being executed,
and that each snippet must be contained entirely on one line.
Note that since the [- ... -] snippet will URI escape, it cannot be
used for the entire value of an href tag as it will likely screw
up. `?' and `&' specifically will both be messed up.
Syntax
<MICPerl>
arbitrary Perl code
</MICPerl >
Description
The MICPerl tag defines a section of the HTML document as Perl
code. It allows coders to integrate complex data gathering and
processing functions directly into an HTML document. It functions much
the same as the JavaScript tag in Netscape, except that it does not
rely on a proprietary language.
The MICPerl tag is the preferred tag for any code over a line or so in
length, or for any code not meant to print to the HTML page. It might
be used to query databases, perform calculations or anything else Perl
is capable of.
Only Perl code, and not MIC code, should appear within a MICPerl.
Note also that MICPerl should not attempt to change the contents of
the page2 as there is no
guarantee that this will work as expected since the compiler will be
unaware of changes made from within the MICPerl container tags. Also
be aware that MICPerl tags are part of the re-evaluation process when
pages are verified (see 5.2), and
this fact needs to be taken into account since if a vpage is used, the
code will be run twice.3
4.2 Logic Tags
Syntax
<MICif test="Perl conditional code">
arbitrary MIC-HTML code
</MICif>
Description
The MICif is a special tag which allows for parts of a page to be
conditionally constructed or proccessed4. This tag
helps to maintain consistency in HTML look and avoids always having to
use the MICPerl tag.
The MICif tag should be used whenever there are sections of the page
or control code which should only be conditionally processed and/or
constructed. As mentioned earlier, this tag could be subsumed into
MICPerl (in certain cases), but that would break the HTML look and
simplicity, which is the goal of MIC. Compare:
<MICPerl>
if ($sufficient_funds){
</MICPerl>
<h2>You have enough money</h2>
<MICPerl>
}
else{
</MICPerl>
<h2>Sorry, insufficient funds.</h2>
<MICPerl>
}
</MICPerl>
to:
<MICif test="$sufficient_funds">
<h2>You have enough money</h2>
</MICif>
<MICelse>
<h2>Sorry, insufficient funds.</h2>
</MICelse>
The MIC code (which may include a MICPerl) contained within the
opening and closing MICif tags constitutes a lexical block of
code. This is true of all the MIC native logic tags.
MICif tags are only potent at runtime, however. A MICfieldspace within
a MICif, for instance, is legal, but will actually have no effect. The
MICfieldspace will be read at compile time and the fieldspace will end
up being defined.
Syntax
<MICelse [test="arbitrary test code"]>
arbitrary MIC-HTML code
</MICelse>
Description
The MICelse tag subsumes the functions of an elsif (else if) and
else. For a complete understanding of MICelse, be sure to reference
the MICif section.
When given the optional argument, MICelse acts as an elsif
statement. Otherwise, it will default to an else (essentially,
elsif(true)...). This allows one to test for multiple
possibilities and also provides the ability to hand control over a
default section of code.
Note that a MICelse tag must immediately follow a MICif or another
MICelse. There cannot be MIC-HTML between the end of one and the
beginning of another. In fact, the only thing allowed between
</MICif>
and <MICelse>
is whitespace.
Syntax
<MIClist list="list or code to return a list" iterator=var
to map items to>
arbitrary MIC-HTML code
</MIClist>
Description
MIClist is analogous to a `foreach' command. MIClist is used to
iterate over a list and perform operation on or display each
element. The `list' parameter defines how the list is to be generated,
or may even specify a literal Perl list which is currently in
scope. The `iterator' parameter defines the name of the variable which
shall contain each of the elements of the list. This variable will be
lexically scoped to the block containing the MIClist. Example:
<table>
<MIClist list="&get_accounts" iterator="$account">
<tr><td>Name: [+ $account->name; +] </td>
<td>Acc. Number: [+ $account->number; +]</td>
<td>Balance: [+ $account->balance; +]</td>
</tr>
</MIClist>
<!-- $account is now out of scope -->
</table>
might produce output something like:
Name: Mr. MIC Acc. Number: ad192381 Balance: $12,000.00
Name: Hojo McMorman Acc. Number: 918231 Balance: $0.27
Syntax
<MICwhile test="arbitrary Perl code">
arbitrary MIC-HTML code
</MICwhile>
Description
MICwhile provides a MIC native while loop that will iterate over the
MIC-HTML code enclosed within the MICwhile environment until the
conditional fails.
Generally, there will be some Perl within a MICPerl or snippet which
will cause the loop to eventually terminate. For example:
<MICPerl>my $test = 0;</MICPerl>
<MICwhile test="$test < 4">
Iteration: [+ ++$test; +]<br>
</MICwhile>
would produce something like:
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Like all the other MIC native logic tags, the MIC code between the
opening and closing MICwhile tags constitute a lexical block.
4.3 Form Tags
Forms tags have been separated, because much of the complexity of MIC
is introduced by forms.
Syntax
<form ... [MICfieldspace=some legal name string]
[errorpage=a MIC-HTML page name]>
MIC-HTML code
</form>
Description
MIC defines a necessary extension to the standard form tag. Each form
that will contain MICinputs, MIChiddens MICdisplays, or that part of a
page that is in a chain of pages for which the coder wishes to ensure
data propagation, must declare its fieldspace name within the form
tag.
The name must be defined somewhere within the files which MIC is
compiling with a MICfieldspace tag. The fieldspace must be defined in
a .fs file. For maintainability and style (though not mandatory), only
one fieldspace should be defined per file. This does not mean that one
cannot have non-MIC forms, however. It is possible to have such forms
and access their variables while within MICPerl tags, as one would in
standard CGI scripting.5 See ?? for stylistic notes on when to employ each of the differing
forms.
The value of the errorpage attribute is the name of a
MIC-HTML page in the pile to go to if there is an error
encountered during the verification process. This will override the
default value supplied in the fieldspace definition for this form
only.
Note that it is at the form tag (if a MICfieldspace is specified) that
the fieldspace object will be instantiated. Refer to ?? for how this will affect the execution of the page.
4.3.2 MICfieldspace
Syntax
<MICfieldspace name=fieldspace name inherit=class name
error_page=an html page>
one or more MICdefines, zero or more MICverifies and no more than one
non-nested MICgroup
</MICfieldspace>
Description
This tag and its included code defines a fieldspace object. These
tags must appear in a .fs file and there should generally be one
MICfieldspace tag per file with nothing but documentation and the tag
in a given file.
The code bounded by the MICfieldspace form tags and external to all
other MIC tags (MICdefine, MICgroup, MICverify) is treated as pure
Perl code (though it is still necesarry to HTML escape the code). For
this reason the logical MIC tags (MICif, MICelse, etc.) cannot be used
here, and there Perl equivalents should be used (if, elseif, etc.). In
addition, snippet markups or meaningless. Display tags also have no
meaning and cannot be used. MICinclude may be used, however. This is
because while a great portion of MIC code is meant to correspond
roughly to HTML output, the code within the MICfieldspace is meant for
proper setup and instantiation of fieldspaces, so has an inately
different purpose, and therefore, form.
No MICfieldspaces (or MICdefines) parameters should contain hyphens
('-').
name
It was true with MIC 2.0 and earlier that the name of the
MICfieldspace must be unique with regards to page names. That is, if
there was a page ``new_accounts.html'', then one could not have
name="new_accounts" in any fieldspace. Under MIC 3.0, there is
effective mangling of the fieldspace names and this is no longer a
problem.
It is recommended that the name of the file containing the fieldspace
have the same name as the fieldspace plus `.fs.' I.e., it is recommended that the
line
<MICfieldspace name="new_accounts" ...
appear within a file called new_accounts.fs.
Note that there are a few reserved words that are disallowed as field
space names. Specifically, `verify' and `inherit' are
forbidden. Other than these, a fieldspace may by any string of
alphabetic characters and the underscore. That is, it must match the
Perl regular expression /\A[a-zA-Z_]+\Z/.
inherit
The inherit parameter specifies the class name from which the field
space object to be constructed will inherit from. This will define
certain behaviors, outside of the scope of this document, tied to the
implementation of the MIC-compliant fieldspace. The type of behaviors
this will control will be things like the life and scope of the data
maintained by the fieldspace (subject to certain restrictions and
minimums required by MIC), the mechanism of data propagation and
retrieval, etc. It may even be possible to inherit from other existing
fieldspaces, e.g., inherit="MICFieldSpace::new_accounts", but this
is an untested feature which nevertheless should be supported in a
later release.
error_page
The error page parameter defines the page to go to in case of an
error. Further details are given later in section 5. Note
that this is a default value and can be overridden by the errorpage
attribute found in a form tag.
Syntax
<MICgroup name=group name
[obj=name of special object variable]
[numvar=name of special indexing variable]
[numdisplay=default number to display per invocation of the MICdynamicdisplay]
[maxnum=absolute maximum number to display]
[dummyok="true"]
>
Group setup code and at least one MICdefine
</MICgroup>
Description
All dynamic fields must belong to a MICgroup. There can only be one
primary MICgroup in a fieldspace, although other MICgroups may be
nested inside.6 This tag and its contents define the behavior and
member fields for a dynamic field which can then be later accessed
through a MICdynamicdisplay tag.
group setup
The group setup code is defined to be the Perl code within the
MICgroup tags, but external to the MICdefine or other MICgroup
tags. The expected and recommended use of this code is to set up $obj
(discussed below). $obj can then be used as the information source
for the field initializations within the MICgroup. It is common to
have $obj be iterated (if indeed it is iterated) from some object or
variable set defined in the initialization code (within the field
space but external to the MICgroup). If $obj is static, then a
statement such as:
$obj = $query_object;
is still required.
It is extremely important to realize the ramification for program
execution, however. Unfortunately, the relationship of the $obj to
the proper instantiation of fields is a bit involved.
The first thing to note is that the existence of $obj controls the
halting of field instantiation in a non-dummy fieldspace and the point
of dummy production in a dummy fieldspace. That is, if you have a
fieldspace that is not a dummy fieldspace, and your code dictates the
creation of 5 $obj's, then you will get a maximum of five field
groups total. If the fieldspace allowed dummies, the 6th field group
and up will be dummies. Note that this means that in the initalization
code of the MICdefine, one must not depend on $obj for dummy
fieldspaces... it won't be there. See section 4.3.4 for
more information on this.
$obj should be independent of the order of indices defined by
$index (discussed below). That is, it should either ignore $index
or not depend on the order of $index. So, if we have:
$obj = $batch_retriever->get_nth($index);
If we get $index as 2, 20, 1, 5, in that order, the code should
react reasonably. So, wanting to look back at the previous $obj or
assuming that the previous $index was one less that the current will
cause problems.
The fieldspace variable is made available as $fs within the group
setup code.
dummyok
A dummy field is a dynamic field for which there is no $obj (they,
thus, must occur in groups since $obj is defined for a group). As for
as ones MICdefine code goes, these fields must be handled (by testing
on the existence of $obj or by not requiring $obj), but they act
the same. The purpose of the distinction is to support two common
functions of dynamic fields.
The first category is where a form is meant to support n user inputs
where n may be limited (by maxnum) or infinite. In this case, we would
want to support dummyok to be true since some or all of the fields
might have no dependency on prior data.
The second category, for which we would want to set dummyok to false,
or leave the parameter out, would be where we want to allow users to
edit existing data, but not add anything of their own. In the latter
case, it is obvious that once we run out of $obj's (where each $obj
is a package of existing data for a group of fields), we don't need to
create any more fields (or groups) and so stop.
This, in short, is the interaction of dummyok and the existence of
$obj.
special variables
Generally, the value of the obj attribute should be $obj (which is
the default if the attribute is left out), because this is safe and
will be quickly understood by other MIC-coders by convention. Also,
other names may overrun special variables or global variables. Thus,
this convention also mandates that no global variable called $obj is
created within a pile. (Note that $obj is used in the text to refer
to that thing in code samples and in documentation.)
If there are nested groups, then a scheme such as $obj1, $obj2,
etc. is preferred. If, however, this is unclear (especially if
multiple objs are accessed in MICdefines which are members of nested
groups, one could more reasonably consider more descriptive
names. Nested names, however, must be unique within a fieldspace. No
guarantee is made on what will happen if these names clash.
The value of numvar should generally be set to $index for the same
reasons. $index is the default that will be used if the attribute is
left out.
Within the MICgroup (and nested MICgroup's), all MICdefine
initialization code will have $obj and $index made available to
it. While $index is set by MIC code, $obj must be set by the
MIC-coder in the group setup code.
Syntax
<MICdefine name=variable name type=IO class
data=data container class>
list to be passed to datatype constructor or list constructor[;;
Perl code to be executed in order to set up the field]
</MICdefine>
Description
MICdefine is used to define field types---how they will be displayed
and the type of data they contain. Any piece of data which may be
queried from or displayed to an end user should be
MICdefine'd. MICdefine tags have an undefined meaning outside of a
MICfieldspace tag.
Putting conditionals around a MICdefine (or any other fieldspace tag)
has no effect. There is a fundamental difference between the setup
code or group setup code (the code external to the MICdefine but
within a MICfieldspace and possible MICgroup) and they occupy
different lexical groups, even though bad style may make this
distinction unclear. For this reason and for simple style and purpose,
code within the code blocks following should be side effect-free with
regards to all data except for the field itself.
name
The name parameter of MICdefines within the MICfieldspace do not have
to be globally unique, but must be unique within the entire
MICfieldspace. MICgroups within a MICfieldspace do not constitute
separate namespaces.
type
The type parameter identifies the datatype to associate with this
field.7 This must
be the name of a MIC-compliant datatype, discussed in
9.1.
data
The data parameter is the name of a data encapsulator class to be used
by the datatype specified in type. Depending on the implementation of
the MIC-compliant datatypes being used, the separation of these two
parameters may seem unnecessary or even cumbersome and spurious, but
examples and justifications can be found in 9.1.
default code block, function or list
Immediately after the > follows the default specifier.
This is treated as the contents of a subroutine in the pile's
top package (i.e. global pile variables are available); braces
are optional. Often this is a single constant value or a short
constant list, but more programmatic code can be included.
There are many cases where multiple values are expected;
for more on this, see 8.
As noted in 3.1, this code block will not be executed
if MIC believes that there is data present which should override the
default data. It is a good idea to make your default data code side-
effect free. Return the list of values, but don't go off and execute
arbitrary programs or mangle data, etc.
$obj and $index (and all the obj's and indexes of parent groups)
will be available in this code block and the arbitrary code block, if
they themselves are available. Your code should never depend on any of
these, however, as described in 8.2.
Note that $fs and $field are not currently made available here.
arbitrary code block
The arbitrary and optional code defined within the block following the
double semicolon (which is itself optional if no arbitrary code block
is defined) is executed as the last step of field initialization (see
3.1). Within this block MIC coders will have the
special variables $fs and $field made available to them; at runtime
these will be the fieldspace object and the field object respectively.
Specifics on the field object can be found in the documentation
accompanying the MIC-compliant fieldspace implementation being used
in your MIC system. The MIC interface specification can be found in
9.2.
Dynamic MICdefines
Dynamic MICdefines are any MICdefines within MICgroup container
tags. Dynamic fields are discussed in more detail later. At this
point, it suffices to note that within the code block, the object
vaiarble and numvar variable will be made available through the action
of the MICgroup tag.
Syntax
<MICverify name=name for this verification test=test>
MIC-HTML code to be run... hopefully with a well defined purpose
</MICverify>
Description
MICverify is used to provide special verification procedures which are
not handled by the datatype verification procedures. It provides for
arbitrary tests and reports.
MICverify's are contained within a MICfieldspace tag. The name parameter
assigns a name to this MICverify. Later, in the MICsubmit tag, one can
specify MICverify names which must pass in order for the form to pass
the verification process.
The test parameter may be either a block of code or a function name to
call. A simple conditional statement is not sufficient because of the
accounting necessary for MIC's error tracking and reporting
functions. More about the necessary accounting in ??. For now, it will simply be noted that the code or
subroutine must return a boolean where a true value indicates that no
errors where found and a false indicates that an error was found, and
thus, the associated error text contained between the tags should be
processed and displayed when requested (with a MICerrorreport).
One may use a MICverify for the purpose of conditional
verification. That is, there may be a situation where the user may want to
verify fields A and B and run the verification X if parameter P is
set, and perform no verification otherwise. This may be accomplished
by using the verify_fields() and verify_verifies()
functions defined as necessary for a MIC compliant fieldspace
implementation. See 5.1.2 and
C.1.1.
It is assumed (and highly recommended) that one will redisplay any
fields involved in a failed test. This will give the end user the
chance to change faulty data without having to return to an old
form. See 5.3 for more about this.
Note that the MIC-HTML contained between the tags is deprecated
because it may not include certain MIC tags. Specifically, other
MICverifies are excluded (as well as MICfieldspace and MICdefine,
obviously).
Syntax
<MICsubmit
name=binds to an HTML control
value=unique among MICsubmits of the same name, matches an HTML control
goto=absolute location to go to after successful verification
[unconditional="true"]>
[<vfield name=MICdefine'd field name within fieldspace to verify >]
[<vpage name=A page to be re-evaluated and verified >]
[<vverify name=A MICverify defined for this fieldspace to be called >]
[<vpresent>]
</MICsubmit>
Description
This tag is used to declare how to handle submit buttons within a MIC
form. Each MICsubmit must be associated with an HTML control of the
same name/value designation.
The name parameter should generally be common to all the related
submits (MIC and regular) buttons for the form which this tag appears
on (though not expressly non-unique for other forms, even those
sharing the same field name space). The recommended value for the name
attribute is [page name]_submit. That is, if the submit buttons are
to appear on a page called `result.html', the recommended name value
would be `result_submit.' This is mainly to keep things regular and
easy to follow, although just about any name will work. If one has
multiple forms on a page, then the recommended naming convention is
'result_submit1', etc. This is a style issue, though.
There are reasons to have MICsubmits with differing names,
however. One is if one wants to implement variable goto's. Because of
the way MIC works, the goto parameter cannot be a variable. That is,
`goto=``$foo''' is not valid code. One could have something of the form:
<MICsubmit name=``test_submit'' value=``Submit''
goto=``analyze_test''>
</MICsubmit>
<MICsubmit name=``quiz_submit'' value=``Submit''
goto=``analyze_quiz''>
</MICsubmit>
<input type=``Submit'' name=``$destination'' value=``Submit''>
The name/value pairs are used to bind the MICsubmit with the standard
HTML controls. Unlike MICinput and MICdisplay, a standard matching
HTML control tag must also be included and will not be generated for
you. The matching control will most often be a control button, but
does not necessarily have to be. It may also be an image-map
designation, or even some a hidden input or radio button. When the
form is submitted, the value will be resolved control will be passed
to the associated MICsubmit.
Thus, when one does have different names for the MICsubmits and
their associated controls, one must be careful that two can never be
defined at the same time. This is also a concern, actually, if they
all have the same name. Thus, while the page flow can be directed by a
hidden, a radio-button group, a button cluster, or an image map,
having both a button cluster and a radio-button group will have
unpredictable effects as MIC will not know which parameter to use.
The goto parameter defines the absolute URL within the system to go to
after a successful submit. Refer to MICinclude for an example of
this. This page does not necessarily have to be in the same directory
and multiple submits can have pages in various directories (which is a
win over regular HTML submits and form control). Realize however that
each submit will share the target of the form tag, so to support
multiple targets, it is still necessary to break the control over
multiple forms.
If the attribute `unconditional' is included with the value of `true',
then the goto parameter will be invoked even in case of error. This
should be included only in the case where you want to go to the next
page even if there are errors produced by the verifications
associated with the MICsubmit where the unconditional parameter
appears. This may be the case with certain styles of error reporting.
Note that old errors (from previous pages in a series) will not cause
execution flow to redirect to the error page. Only errors produced by
the current page/submit will be redirected.
The three optional included tags, vpage, vfield and vverify define
pages (e.g., relative URLs), MICdefine'd fields and MICverify's,
respectively, that need to be checked to see if there was bad data
entered in the form. You may have as many or as few of these optional
tags as you wish. These tags, and the vpresent tag, are discussed in
section 4.4. Note that these tags only have
meaning in the context of a MICsubmit and that no other tags or naked
text has any meaning when contained by a MICsubmit.
Finally, the no-reset-dynamic attribute should be included if one
wishes to start counting dynamic fields from the current dynamic
field. This should generally only be included if a page is
self-referencing, in which case MICrollover and MICrollback
should most likely be used.
An example of a MICsubmit would be:
...
<MICsubmit name="application_submit" value="Submit"
goto="application/process_application">
<vfield name="applicant_name">
<vfield name="applicant_ssn">
<vverify name="enough_money">
</MICsubmit>
<input type="submit" name="application_submit" value="Submit">
<br>
<MICsubmit name="application_submit" value="Cancel"
goto="home">
</MICsubmit>
<input type="submit" name="application_submit" value="Cancel">
...
Syntax
<MICdo name=name of tied dynamic field
numvar=variable in which to place the current index>
code to be executed upon each instantiation
</MICdo>
Description
MICdo's are only valid within forms. Their purpose is to ``do''
something to each instantiation of the dynamic field specified in the
name attribute. Within the MICdo, $field is made available to the
coder to modify and check. MICdo's are not necessarily expected to be
side effect-free with regards to other variables, but they should be
nice from a maintainability/debugging standpoint.
Also available within the code block is the variable specified by
numvar. Before we continue, let us look at an example:
<MICdo name="name" numvar="$index">
$val_hash{$index}->{name} = $field->value();
</MICdo>
For every field present, the group iteration index of that field will
be used to key an anonymous hash. The string name will then key the
value of the field name corresponding to the group iteration.
So, what do we mean by group iteration? When dynamic fields are
created, the first one to be created is the first group iteration, the
second the second, etc., etc.
Of course, the astute reader is now wondering what fields are present.
Under MIC 2.1 and greater, the fields present are those which are
needed to be displayed, those which have changed from their initial
values (those fields which have had user input which is not exactly
equal to the original value), those that are in error, or those that
are members of a group where some field in that group meets the
previous criteria.
These facts are often exploited in the use of a MICdo. For an example,
see E.2.
Syntax
<MICinput name=MICdefined variable name [no-format=``true'']
[edit_test=``test''][changflag=variable]>
Description
MICinput is analogous to the standard HTML <input ...> tag. The
size of the input field created, its default value (if any) and other
attributes are defined earlier in MICdefine.
MICinput is used to create input fields on forms for MIC defined
values. It must only be used within the <form...> tags which
have the optional fieldspace parameter. The name parameter takes a
MICdefined name which has (or will be) defined for the MICfieldspace
of the current form.
Note that the MICinput does not overwrite the normal <input ...>
tag, but is in addition to it. That is, one may freely mix MICinput
and input tags and make use of both. Realize, however, that there is
no MIC-supported checking and verification for non-MIC input, nor will
the data be saved to the database, etc.
Non-MIC fields should be controlled through standard HTML inputs and
MIC defined fields should be controlled through MICinputs. A MICinput
with a non-MICdefine'd field and a standard HTML input with a
MICdefined field are both undefined.8
MICinputs handle both static and dynamic fieldspaces. If a
dynamic field is requested outside of a MICdynamicdisplay, then the
results are undefined. Currently, it is also not permissible to have
non-dynamic field within a MICdynamicdisplay since this is almost
always the wrong thing to do. This may be supported in future
releases, however.
Also, any MICinput will automatically attempt to format the value
before displaying it. This means that the data may change form, but
not meaning, from one viewing to the next. This may be overidden by
the tag no-format=true, or there may be mechanisms within the
datatype object. The formatting is not only for viewing purposes; if
successful, it will store the canonical form in lieu of the
original. If unsuccessful (i.e., unable to canonicalize), the original
form will be maintained. This functionality does not provide any error
handling on its own. For that, you must specify the proper checks and
reporting mechanisms as specified in 4.4.
The optional changeflag attribute takes the name of a Perl variable
that will be set to true if the value of the named field ever changes
due to end-user action. This variable will be introduced by MIC and
will be scoped to the page.
The optional edit_test attribute allows us to test whether we want to
do a MICinput or a MICdisplay. If the edit_test is true, then html
input is generated for the associated MICdefine value. If the
edit_test is false, then the value of the MICdefine is outputted to the
user.
4.3.9 MICdisplay
Syntax
<MICdisplay name=MICdefined variable name [no-format="true" raw="true"]>
Description
MICdisplay is used to display MICdefine'd variables. It will display
the current value of the field. A MICdisplay is compatible with a
MICinput and will cause no conflicts if both are used on the same page.
The raw option, if set, will cause the value contained to be
displayed without HTML escaping. The intended purpose for this
functionality is to allow the presentation of the data as HTML within
the HTML. Note that raw displayed values are never formatted.
Syntax
<MIChidden name=MICdefined variable name [no-format="true"]>
Description
MIChidden will place the value of the proper field in a hidden HTML
tag. Use this tag with caution. Usually, if you want to use it, you
probably shouldn't. Remember, the fieldspace will propagate all data
for you.
4.3.11 MICdynamicdisplay
Syntax
<MICdynamicdisplay name=group name [numvar=index name]
>
deprecated mic code
</MICdynamicdisplay>
Description
MICdynamicdisplay defines a set of mic-code to be repeated until a
valid stop condition is met. This may be either:
- The loop has iterated a number of time equal to the number
defined by the numdisplay attribute in the associated MICgroup
tag9
- There are no more valid pre-defined fields to be displayed and
note that the group is not marked for dummyok.
- The total number of fields displayed for all calls to this page
is equal to the number defined by the maxnum attribute.
The optional numvar parameter will allow one to specify the name of an
index variable for use within the MICdynamicdisplay block. This
variable will hold the index of the current iteration. If not
specified, there is no default and the value will simply not
exist. The recommended name for this variable is ``$index.''
A Word about using MICdynamicdisplay
Note that when using a MICdynamicdisplay with MICrollover and
MICrollback tags, the page must be able to be called again and again
in succession. Each time, any new datatypes created are added to the
fieldspace and remembered. Only the proper ones, however, are
displayed.
4.3.12 MICrollover, MICrollback, and MICrefresh
Syntax
<MICrollover name=name to associate with submits
assocdynamic=group name which this button should control
[text=text to appear on button]>
[<vfield ...>]
[<vpage ...>]
[<vverify ...>]
</MICrollover>
[<vpresent>]
The syntax for MICrollback and MICrefresh is the same.
Description
These three tags indicate that a button should be placed at the point
the tags are placed. These buttons will have the effect of going to
the next page of the dynamic form and re-evaluating the page on which
they display after starting MICdynamicdisplay at a new index
point. The buttons are smart in that they know whether to display
themselves or not. That is, the rollback will not display on the first
page and the rollover will not display on the last. Neither will the
rollover display if there are no more valid items to be
considered. This will happen if any of the following conditions are
met:
- dummyok is false and the last obj evaluated or the first obj for
the next page is undefined
- there are no evaluated MICinputs in the MICdisplay (this means
that MICif's are potent on this condition)
- maxnum has been reached
The assocdynamic attribute is the name of the group which this button
should cause to roll back or forward. This must be specified due to
support of nested MICdynamics.10
Other than that, they act much like submit buttons, and, like submit
buttons, should have the same name within a form. One can place
verification tags between the containing tags to one's delight.
4.3.13 MICreinitializefs
Syntax
<MICreinitializefs test=perl code>
MIC Code to be run when the test is true
</MICreinitializefs>
Description
When the test is true, this will cause the fieldspace associated with
the form to be reinitialized at the point that this tag is dropped. The
code contained by the tag may contain setup code of some sort, but may
also contain messages to print to the user, etc. It is regular MIC
code. This tag's purpose is to refresh the fieldspace when actions on
the current page have changed the nature of the data. For instance, if
a user asks that certain items in a dynamic field be deleted, and the
page is refreshed, then we must first instantiate the regular
fieldspace and delete the fields. But, if we did not re-initialize, there
might be blank items on the screen. And, depending on how
initialization works, there is the possibility that a field will be
missed since the data may collapse on the next page, and the item
between the final on the current and the first on the next will never
get shown.
4.3.14 MICindexoverride
Syntax
<MICindexoverride test=perl code group=group to override
[previous=``true''] [steps=integer]>
Description
When test is true, then the index will either be set back to the
previous iteration (which may or may not be back a step because of the
MICrefresh tag) or back/forward a number of steps equal to the value
given. Either may be set and previous will override if both are set.
4.4 Error Handling and Verification
MIC's robust and flexible error handling system is one of its
most useful features. This system allows one to verify data and then
track, report and possibly correct errors. Both verification and
reporting are rather flexible and powerful, while tracking is
automatic. While the tags are discussed here, to fully understand MIC
error handling, one must read section 5.
Syntax
<vfield name=field name [ignore=``true'']>
Description
This has the effect of saying ``when the MICsubmit I am associated
with (contained by) is hit, then check this field for errors with
respect to its data type.''11
The name parameter identifies a field name within the associated
fieldspace. Since names of all fields in a given fieldspace must be
unique, MIC will know whether the field is dynamic or not. If it is
dynamic, then all instantiations of that field present at the time of
verification will be checked.
The effect is to call verify() (discussed in the cross interface
section, 9.2) on the field contained
within the fieldspace. The types of errors caught here are things like
`I am supposed to be an integer... am I?' as well as parameter
limitation checks, if supported.
The optional ignore parameter will tell MIC to ignore any
errors generated directly by this field. Furthermore, it will take the
field out of error. This is to allow for the idea that certain submits
may change the nature of what we care about and data that was
previously in error is no longer in error. Note, however, that any
verification will override ignore directives, so combining a vfield
tag with an ignore directive and a vinistantiated tag will have the
same effect as if the vfield tag were not there at all.
When we say ``generated directly,'' we mean generated by a vfield,
vcurrent or vinstantiated. If the field is in error through the agency
of an arbitrary verification (kicked off with vverify), then it will
remain in error for that reason, even if the ignore directive is
called.
Syntax
<vpage name=page name>
Description
This tag causes the named page to be reevaluated in the current
context (meaning, among other things, that any global variables will
have their current value). All fields which would be displayed (for
input or display only) will be verified.
Realize that any pages specified by a vpage tag will essentially be
re-run. If this is a concern, specify fields individually or use
vinstantiated. In fact, it has been found that, in practice,
vinstantiated works better and does what is wanted; be cognizant of
the fact that the fields checked by each method are not the same.
As an example of the above, if on the first run through af a page, we
increment a global var, then it will be the new, incremented value
when the page is re-evaluated for vpage. This will also have the
effect or incrementing the value again!
Note that there is no ignore attribute possible with vpage. This is
because vpage is being deprecated.
Syntax
<vverify name=verify name [ignore=``true'']>
Description
This causes the test specified by the named verify to be run, and if
it returns false, then the result of the MIC-HTML associated with the
verify will be associated with the error-reporting mechanisms.
The optional ignore tag will remove the verification from error and
all fields in error due to the verification. It will not remove direct
field errors, though.
4.4.4 vinstantiated
Syntax
<vinstantiated [ignore=``true'']>
Description
This causes all the fields which are instantiated at the moment to be
verified.12 In general, this is usually the preferred alternative
to vpage as it will generally have the desired affect without the side
effects of vpage.
The ignore attribute has the effect of removing all field errors, but
not verification errors. To remove all errors, use vignore.
Syntax
<vcurrent [ignore=``true'']>
Description
This tag has the effect of requesting a verification of all fields
that have the potential of having been changed. It is, thus, different
from vinstantiated in that past fields that may be hanging around due
to change or what not, will not be verified. This may be the more
efficient of the two to use, if it does what is needed.
The ignore directive will remove all fields from error that may have
changed in the current form. Note that it will not effect errors due
to verifications.
Syntax
<vignore >
Description
This tag will obliterate all errors, both field and verification.
4.4.7 MICerrorreport
Syntax
<MICerrorreport >
MIC-HTML
</MICerrorreport>
Description
This is used to iterate over all the error-packaging objects. Within
the tag, the special variable $error is made available within the
opening and closing tags. This variable can then be used to output
those things which an error report should have.
At the time of this draft, the only real requirement to be a
MIC-compliant error-packaging object are those methods necessary to
create and iterate. For this reason, one must look to the
documentation for the error packaging object to figure out how to do
what one wants. Later versions of MIC will likely have a more
integrated and user friendly interface.
4.5 Miscellaneous Tags
4.5.1 MICinclude
Syntax
<MICinclude src=a MIC-HTML file name>
Description
This command is used to include repeated code or text. This command
specifies a document or part of a document to include
verbatim13 at the point at which the tag is
included. You could think of it as simply dropping in the text of the
file. Note that the MICinclude statement is evaluated at compile time,
meaning that you cannot have variables in the src attribute.
The file is specified in an pile-absolute manner meaning that it is
not relative to the current page, but relative to the root of the site
to be compiled. The file is specified with path information, so if the
'hello' was in directory '/bob/micsite/branch' where micsite is the
root of the site to be compiled, then you would say
`src="branch/hello".' Note also that you never have a leading `/' in
the path information.14
To support files that are meant to be included in several different
piles (and therefore cannot be strictly contained under a single pile
root), one may use the -I option at compile time to specify an include
directory (see 3.3). In this case, the pile-root relative
file is first looked for and if net found, then the file is looked
relative to the include directory. So, from above, if there were no
file `/bob/micsite/branch/hello,' and the pile was compiled with `-I
/bob/include,' then the compiler would search
`/bob/include/branch/hello.' Note the search order above.
Note that because they are already included, files with the extension
.html, .mic or .fs that are within the site should never be
MICincluded. By convention, included files should have a `.inc'
extensions.
It may be possible to MICinclude files which are external to the site
(i.e., src="../style.inc"), but the feature is unsupported at the
time of this writing.
- 1
- If a form tag has the MICfieldspace parameter, then it
will be specially processed by MIC; it is not prepended, however,
since it is not MIC specific tag.
- 2
- Contained in the $content variable
- 3
- That is why the use of vpage is
discouraged in favor of vinstatiated.
- 4
- The MICif tag, and
all logic tags, are, in fact, strictly potent at runtime.
- 5
- The special variable $cgi is
available for this and other purposes.
- 6
- Nested groups have been tested to some extent
at the time of writing, but it must be acknowledged that there are a
couple known minor bugs with nested groups. The behavior and code
appear, however, basically sound and the known bugs should be easy to
fix (they are already analyzed) when the need arises. That is not to
say that more extensive tests/usage will not turn up more fundamental
problems, though.
- 7
- At this point, the term field might become a bit
confusing. Field does not necessarily refer to a blank field like a
text input device in HTML. A field may be associated with any input
device; e.g., a radiobutton, checkbox, select list, etc..
- 8
- One of MIC's security
features keeps the standard fields from being potent by registering
which fields have the possibility of change.
- 9
- Future versions of MIC will allow one to overide the
default specified in the MICgroup with a value specified in the
MICdynamicdisplay.
- 10
- At the time of this writing,
nesting is only a partially tested feature with some known bugs.
- 11
- Datatype is a concept used by MIC
which may be supported to varying degrees with the data encapsulators
one is using in their MIC system. The idea is that user data is
expected to be of a type, which may be something like integer, credit
card number, or free form.
- 12
- That is all fields needed for the current page, all
fields in error, all fields which have changed, and all fields being
carried along.
- 13
- Or effectively so.
- 14
- The syntax src="branch::hello" would
also be acceptable.
Chapter 5 MIC Error Handling
5.1 User Defined Verification Routines
User defined functions may be of two types, inline or called. The
inline method should only be used for small snippets of
code. Generally the accounting overhead that is currently necessary
and the fact that most simple checks are generally handled by the
fieldspace checks means that inline functions are, by and large, not
the right choice. If a user defined function is used, don't forget to
use or require the module in the control file.
MIC defines that field supported error checks are done before user
defined checks. This is done so that one can be sure that the data one
is testing is at least canonically correct so far as the datatype can
gurantee.
5.1.1 Error Accounting
Though the exact interface to the fieldspace object, as far as
accounting goes, is beyond the scope of this document, there are some
general principles that can be discussed here. First of all, user
defined checks should only be used if the checks supported directly by
the field objects are insufficient. What is defined by MIC, however,
is that the user functions must return a true false value in every
call to the function.
By accounting, we mean that it is necessary to put fields in error and
remove them from that state when appropriate. This should be done
carefully and the logic of the functions should be carefully checked
to make sure that the accounting is done correctly.
Additionally, MIC is also concerned with whether the MICverify itself
is in error or not. Therefore, the function should return a true or
false value to indicate that no errors or at least one error was
found, respectively. As noted in the MICverify definition, this will
control the display of the MIC-HTML error text contained by the
MICverify open and close tags.
5.1.2 Conditional Verification
One important use of MICverifies is for conditional
verification. Sometimes we want to verify certain fields and/or
verifications based on parameters or data state. To do this, we use a
MICverify which may call other MICverifies or field verifications
directly.
The two MIC required functions (see ??) verify_fields() and
verify_verifies() are used to make these calls. An example of
how this is generally done is given in ??. Generally, however, the verification that determines what
verifications to perform should always itself return true and do no
accounting of its own as the fieldspace functions will do their own
accounting.
5.2 Page Verification
Though usually less preferred than vinstantiated, there might be times
in which a user wishes to use vpage. Such an instance might be if the
verification for fields is particularly costly for some reason, and/or
a great number of fields are being instantiated, many of which we do
not wish or need to re-verify.
If vpage is used, one must be very cautious about state errors. Realize
that all the code within a page will be run again in order to
determine what is on the page. The page is essentially redisplayed at
time of verification, although there is no output to the user. This
means that for vpage to function without any unexpected side effects,
the page must be more or less side effect free, at least when it is
called again to be verified.
Though considered bad style, it may be necessary to case out when the
page is being called. That is, put the sections of the page that will
cause `bad' things to happen if they are run twice in if-statements
and have some sort of global flag1 or HTML parameter that signals that the block in question should
not be run.
5.3 Error Pages
There are generally two types of error reporting as far as the user is
concerned: contextual and non-. MIC supports both.
The idea for contextual reporting is that errors are reported where
they occurred, or in context. This is accomplished by setting the
error page for a particular page to be itself. The page should then
be redisplayed with the appropriate error messages in an aesthetically
pleasing spot.
Non-contextual error reporting should be reserved for pages that can
yield very complex errors and/or dynamic fields.2 Realize also that the interface for dynamic
error handling is, at the moment largely within the domain of the
error packaging object and thus is not all that pretty. It is also
outside the scope of this document.3
- 1
- If running in fast CGI
mode
- 2
- It is not
always the case that it is easier or more desirable to report dynamic
field errors in a non-contextual manner, but it is more often true
than with static fields.
- 3
- This should be remedied
in future versions of MIC.
The control file serves two main purposes. The first is to make all
the neccessary use's and require's that the pile will
need. The second is to define zero or more of the three optional MIC
defined subroutines.
Two of these subroutines will be executed before and after,
respectively, each MIC-HTML page. They may set certain common
variables, perform security checks, etc. They are named setup and
cleanup. The third is used for handling pile errors. This does not
mean field errors.
setup()
setup() is, as far as the MIC coder is concerned, called as the first
step in any page evaluation (see 3.1). setup() is
meant to initialize certain variables, and or perform security checks
and such.
If setup returns some value, then this will stop the page which would
have been processed/displayed from doing so. Instead, the return value
of setup will be treated as what should be proccessed and output. If
there is no return value, then the program will proceed normally.
Thus, perhaps there is a page 'session_lost.html' which is meant to
deal with the fact that a customers session has been lost or
corrupted. We check for this fact in setup with something like:
...
if (session_lost()) { return Pile::my_pile::session_lost(); }
...
If session_lost() is true, whatever page was requested will not be
proccessed or displayed; instead, session_lost() will be. For this
reason, be sure and return undef or an empty list at the end of the
setup routine. By the rules of perl, simply ending the routine could
cause erroneous misdirection.
cleanup()
cleanup()'s primary purpose is to do that: cleanup(). The first reason
it was included was to be able to undef global variables set up in
setup(). It may also be used to make database commits, or for any
other reason.
handle_exceptions()
The third subroutine is handle_exceptions. It is invoked if a Perl
exception is caught by a MIC-compliant
piledriver.1 If an exception is
thrown, then it will be handed off to
handle_exceptions().2 Whatever this
page returns will be handed off to the customer. Therefore,
handle_exception should generally retun a nice HTML page reporting
the error.
Since MIC provides robust error handling for field related errors,
this type of error reporting should generally be reserved for errors
that ``shouldn't happen.'' Of course, this doesn't mean that the error
shouldn't look nice.
- 1
- Implemented by Error.pm
- 2
- Unless the type of error is
Error::Simple, in which case it is assumed to be generated by a die or
syntax error; piledrivers may handle these themselves.
Chapter 7 MIC Perl Programming/Markup
7.1 The CGI Object
When programming, one may access the $cgi object from within any Perl
snippets, MICPerl tags or within field or fieldspace definitions. One
may even access this object from within the test parameters of
logic/flow control MIC tags.
7.2 HTML Headers
MIC provides a global hash, that is reset for each call to a MIC page,
which may be referenced from any page code (but not fieldspace code
unless passed in by some mechanism) called `headers.' The keys of this
hash are intended to be header lines and the values their values. They
will be printed as <
key>
= ``<
value>
''.
This hash is normally not accessible from the fieldspace because the
fieldspace code gets compiled into a different package.
7.3 The Fieldspace Object
Any time one is within a form tag (with a MICfieldspace specified) or
within a MICfieldspace tag, there will be a Perl object, $fs,
available. It is through this object that one may access variables
(which have been MICdefine'd) of the current fieldspace. This
interface to this object is not totally defined by the MIC
specification, though some of the methods on it are defined in
9.2, ?? and in the documentation for the implementation of the the
MIC compliant fieldspace object that is being utilized.
This object is used to access fields and the informaiton within those
fields. It as also used to ascertain certain state questions,
especially regarding errors, about the fieldspace. As far as a
MIC-coder's code is concerned, the fieldspace should be used to get
information, but not change it. Generally, when the MIC-coder is
changing information (as in setting default values), they will be
presented with the field itself. The MIC-coder should never change
state information directly through the fieldspace object except
in MICverifies. It is hoped that eventually, this will even be
unnecessary.
7.4 MIC Provided Perl Functions and Objects
This section outlines functions and objects (other than the $fs
object, which is considered outside of, though compliant with, MIC)
which MIC makes available within a Perl context. These may be used
within a MICPerl tag, and will not, unless noted, function as expected
in a snippet tag.
scalar return_page (scalar)
This function takes the name of the page to be returned and returns
the content generated by this page. Generally, this should be used
like ``return return_page(`new_page');
'' and not to rip content
from some page for insertion. This is better done with MICincludes and
by other methods.
The page specified should be MIC-root relative and can be in
functional or HTML format. It may be a page within the current pile or
a mounted pile (sub-pile) of the current pile, in which case the
MIC-root relative designation is obviously through the mount
point. The function will access the $headers variable and make drop
the proper headers in order that relative paths don't getted confused
on the receiving page.
MountManager
The MountManager object is made available to a pile in order that
child or sub-piles may be mounted to directories within the primary or
parent pile. Here, we specify the public interface on this object. The
MountManager object may be accessed through the special variable
$mount_manager, which is global to the pile and must be used in
order for the pile to be strictifiable.
mount (scalar, scalar, scalar)
This function mounts the sub-pile named in the first argument to the
directory named in the third. The second argument is the physical
location of the sub-pile in the directory structure.1
register (list ref)
This is used to list all the variables which should be shared between
parent and sub-piles. All the variables listed will be aliased across
the piles namespaces when control is passed to the sub-pile and
de-aliased when control is returned to the parent.
7.5 Mounting Piles
The idea behind mounting piles is much the same as mounting a Unix
directory to a mount point. All requests through the mount point will
be passed the sub-pile mounted to that point and any routing
(directory or page) information following the mount point navigates
within the sub-pile.
Currently, MIC only supports one level of mounting. Their can be one
primary pile and one level of children. Future versions of MIC may
allow for sub-piles to mount sub-piles as well. Programatically, this
is not that hard, but may induce coders to create hard-to-resolve
errors.
7.6 Specifying Pages within the MIC-Site
There are many times within MIC-HTML when one needs to specify a
page. Within a MIC tag, it is done in the following manner:
- list each sub-directory off the root of the site
- specify the page name (the .html, .mic, .HTML and .MIC are optional)
See the section about MICinclude for an example.
Note, however, that within the HTML tags, there is no change from the
standard fashion. An <
a href="...>
tag stays the same
and does not follow the above procedure. You specify the link relative
to the page where the link is located on and it is allowable to have
`..' in the path information.2
The reason for this is the way that MIC thinks about pages versus how
the web server thinks about them. The web server is requesting these
pages through the agency of the piledriver. Within MIC, however, pages
are functions. MIC takes your page specification and converts it to a
function call.
In fact, sometimes you want to be able to redirect control flow
explicitly. An example of this has already been provided in the
discussion of the setup routine in the control file. Rarely, but, at
times, you will want to do this for a page as well. That is, you might
have something like:
...
<MICPerl>
if ($customer->secure()) {
return return_page('login/secure');
}
else { return return_page('login/insecure');
</MICPerl>
...
MIC 3.01 allows the return page to be in a directory other than the
current directory. Users should note that this will only work as
expected if the end-user's browsers support the location tag. Care
should also be taken if one is using frames and the user programmer
wishes different buttons to have differnt targets. For this to work as
expected, it is still necessary for one to have multiple forms.
7.6.1 return_page()
The return_page() function is the only MIC-required library function
that is required to be provided to the MIC coder by the MIC spec. Any
particular implementation of MIC may provide other useful functions,
but all must provide this function. The functionality and effect are
specified above. Again, the effect of calling this function is
undefined unless the user's browser supports the location header.
7.7 Special Concerns
7.7.1 Shared Variables
It is common to share variables between fieldspaces and pages. When
this is done, one must take careful note of any dependencies
introduced, however. Remember that that the fieldspace will, in
almost every case, be called in some context where the page is not
called first, even if the fieldspace is only used on that
page.3 Thus any variables that the fieldspace depends
on should be declared/initialized/set in the fieldspace and not on the
page.
7.7.2 Regarding Values from Fieldspaces
Programmers must realize that MIC 2.0 implements a conservative
instantiation routine. This brings up a couple of issues worth noting.
First, $fs->get_field('field_name')->value() and
$fs->field_name() might cause runtime errors as the field, though
defined, might not be present at the time it is called, and thus
calling an object method of nothing will cause your program to break.
The recommended solution is the use of exceptions, which, in Perl, are
handled through the use of eval. One should learn about this command if
one is not already familiar with it.
Secondly, even using evals, if one has code like:
my $var;
$var =
eval {$fs->get_field('acc_number')->value();};
$account->set_acc_number($var);
then although one will not have a runtime error, unexpected
behavior will most likely occur. Remember that fields are only loaded
if they are changed from their initial value, are in error, or a
member of a group where one or more members fall into the previous
definitions.4
Let us say that the acc_number field is intially blank or set to the
value of the current account, if there is any. The customer goes in to
page, fills in the account number, and it gets updated. The next day,
the customer goes back to the page. We find that we already have an
account number associated with the customer, so the account number
will display the number that they filled in the first visit. After
hitting submit (or whatever), when the above code is called, if the
user has not changed the account number, then it will get set to
blank. This is because the field will not be instantiated, so the eval
statement will return undef and $var will get set to undef. To avoid
this problem, one might check $@ or rethink code.
7.7.3 Data Propagation
Be aware that data propagates in a chain. If a programmer has a
multipart form, then any page that a user could get to must include
the fieldspace of concern or the data will be lost. Help pages
generally present a challenge to interface design for this
reason.
The other option, of course, is to store off the data and reload,
this, however, is not preferred unless one is going to break from the
form for more than a page or two.
7.7.4 Conglomeration
Under MIC, the urge to conglomerate should be avoided. That is, pages
should not, generally, submit to themselves and behave completely
differently depending on whether they are the information page or the
processing page. That is, a form should call another page to handle
the processing of the data on the form, and not itself. Otherwise, one
is not using the full power of MIC and maintainability and ease of
reading and enhancing a site is, it has been found, generally
decreased.
- 1
- This
should most probably be an absolute directory set by some constant
that can be modified as needed.
- 2
- Absolute pages are allowed too,
but generally discouraged as less maintainable.
- 3
- In this case, the fieldspace will be instantiated for
verification purposes.
- 4
- The entire set of static fields costitutes such
a group.
Chapter 8 Forms, Fieldspaces, Fields and Considerations Thereof
General error reporting has been discussed above, and will be
discussed in greater detail in the cross interface
specifications. Though related, we will not rehash those subjects
here.
MIC, when fulfilling its purpose, must deal with and process gobs of
end user information. This, of course, brings us into contact with
forms and the carriers of that data, fieldspaces and fields. This
sections intent is to help coders understand what these things are and
how they should be used.
8.1 What is a Fieldspace?
A fieldspace is conceptually the holder of all your fields. There is
exactly one fieldspace associated with each MIC form. This fieldspace
knows what fields might be present and how to initialize them.
The fieldspace object, presented to the coder as $fs, is created at
the point in the page where the user has <
form
MICfieldspace="...>
. After running through some trivial setup,
the fieldspace then recieves information encoded at compile time about
what fields the page might potentially need. With this information and
all the necessary state information propagated from the previous
page1, the fieldspace then goes on to instantiate
all the fields required by the MIC spec.
The fieldspaces primary purpose, as far as the MIC coder is concerned,
is to provide access to fields. The fieldspace is also the recipient
of the accounting information necessary in user defined verifications.
8.2 Objs, Dummies and Data Management
As mentioned briefly in the MICdefine reference, the function of the
$obj object should be well understood to prevent odd errors. As
described before, $obj is tied with the creation of fields and dummy
fields. It is important to note in the field setup code, however, that
one may never rely on the existence of $obj or $index.
At first, this may seem counter-intuitive; one might expect $obj,
etc. to always be present under certain circumstances if one is using
a non-dummy fieldspace. The reason that one cannot depend on this is
because if a member of a group is changed and the other's get carried
along, then the changed member will obviously get its value from the
user data and not from the default data, but the other members will
also be filled from the value that they had at the time that the
changed field was changed. Thus, the default code will be
circumvented for the sake of efficiency.
8.3 Multiple Values/One Field
After MIC 2.1 beta, MIC was able to support the concept of multiple
values for one field. The impetus for this enhancement was the need to
support select boxes, though it is also properly employed in
checkboxes and may, in fact, be employed with any type of HTML
control. It is suggested that the MIC coder become familiar with the
idea of multiple values for a single parameter within HTML 4.0, as
this is the model which drove the design of the MIC interface.
Generally, it is best to think of fields as always containing lists of
data--it just so happens that in the common case, these are lists of
one. A field may be initialized to contain multiple values, or it may
recieve multiple values from an HTML page. Any values received override
all previous values. That is, if a field is initialized to contain two
values, `A' and `B', then if the page is displayed, user input is
received and the HTML parameter associated with the field has only `C'
associated with it, then the field will contain only `C' after the
processing of that page. If the page were to have two, twenty, or one
hundred values associated with the parameter associated with the
field, then that is how many values the field will contain.
Note that there is no guarantee on the order in which the HTML
parameters or field values will be processed, displayed or
returned. This stipulation is without regards to any guarantee that
the HTML specification may make.
See E.3.
- 1
- The methods of propagation are of no concern to the MIC
user and may be various.
Chapter 9 Cross Interface Requirements
The complete MIC system is an integrated set of parts. This helps
ensure both maintainability and usability of the system. The interface
to these sub systems utilized by MIC are described in this section. This
chapter, while a user may find some of the funtions and/or
specifications useful, is primarily meant for MIC itself. That is, the
MIC compiler and/or generated code relies, or may rely, on the function
being defined in this interface. In the appendix (??), one will find a suggested interface for fieldspaces and
datatypes. This may be used as a starting point for implementers or as
a conceptual reference for beginners, but should not be relied upon
unless the documentation for the particular implementation of these
sub-systems being utilized states that it conforms to this
specification.
Note that this does not define requirements imposed by peers or lessers
(if one views MIC as being the parent in this little
hegemony). Specifically, there may be requirements imposed on the
datatypes interface by the fieldspace system, or vice-versa.
9.1 Datatypes
In the parlance of MIC, a datatype is a field. That is, each field has
associated with it a single datatype object that manages the values
associated with that field. The term `field' and `datatype' will be
used interchangeably as clarity dictates.
A datatype is an encapsulator of data that knows what type of data it
expects to be encapsulating and how it expects to display itself. It
will generally be able to detect errors in the form or range of the
data, though exactly what will be detected is outside of the scope of
this specification.
list/scalar value ()
This will return the value encapsulated and will function
appropriately in either a list or scalar context. The value that is
returned might not be the value that was received as the functions
verify, format and canonicalize may all act to change the form of the
value, though not its canonical value.
set_value (list/scalar value)
Will set the value to value. Note that this will not cause MIC to
think that the value has changed if called directly in code. It can be
used to set default values, though using the default value code
portion of a MICdefine is the preferred method for accomplishing this.
set_possible (scalar values)
This function takes a reference to a hash of possible values. For all
datatypes, it will make sure that the canonical form of the
encapsulated data can be found in the list passed in (there are no
constraints if there is no list), and for scroll list, check boxes,
etc., it will use this list to generate the user displayed list. The
keys are the value of the encapsulated data. See documentation of the
datatypes for additional meaning and usage of the keys and values.
list/scalar canonicalize ()
This will examine all the values associated with the field and try and
massage the data into canonical form as defined for the datatype
specified for the field. If successful (i.e., all the data forms were
recognized and successfully tranformed), then it will return the list
or the first member of the list of values. If not successful it
will raise an exception.
verify ()
This will run field verification functions on the field to make sure
that the encapsulated data conforms to the canonical form and possibly
further restrictions. If there is an error, then it will throw an
error of a specific type. A human readable description of the errors
should be accessible by the text() method defined on the error which
should return a reference to an array of messages.
scalar/list format (bool quite)
This will format the canonical data as per the users request. If the
quite flag is set, then errors will be quitely ignored. If not set,
then this function may throw an exception. If successful, it will
return the formatted value.
scalar call_me (scalar name)
This will return the name by which this field should be referred to
for the end user. It will optionally take a new name. Note that there
is not any requirement to treat various dynamics differntly. That is,
it's okay if all of them are required to have the same name.
9.2 Fieldspaces
This section details the functions which a MIC-compliant fieldspace
object and the fields within it must support.
DataObj new (FieldSpace)
Takes a data object of some type, which may be various depending upon
the implementation and/or desired characteristics of the FieldSpace and
returns a properly instantiated, yet trivial, FieldSpace object. To
fully instantiate all the data, the proper fields are then requested
and instantiate() is called on the FieldSpace object.
The DataObj is the encapusalator or indicator on how to retrieve
and/or resolve the data necessary for proper instantiation. It may be
of various types; e.g., a CGI object, some sort of database table
handle, or even a simple ID string.
request_group (scalar group_name)
Must be called before instantiate() to have a defined effect, this
function requests that the named group be made available in the
FieldSpace object. If the group_name is unknown, a warning will be
sent to stderr, but program will otherwise continue unaffected.
Making a request for `_main' is how one requests the static or root
group. Requesting a dynamic group has the effect of instantiating the
next set of fields from that group based on the current index numbers
and the num_display var set in the MICgroup tag.
instantiate ()
Will possibly raise on exception if there are errors in instantiation.
datatype get_field (scalar field_name)
datatype <field name> ()
Takes field_name and returns the datatype associated with the
field. It may also call the field name directly, though this method is
not recommended. It will not work if the name of the field is the same as
any functions defined within the fieldspace implementation, which
will not be enumerated here.
scalar or null deposit_state (scalar data_obj, bool internal)
This function is meant to work in conjunction with
retrieve_state, though exactly what it does is highly
dependent on the nature of the fieldspace. It will take the data_obj
figure out all the state data that it needs to continue operation when
the next page in the chain is called. The return value, if defined,
should be printed out to the HTML page before the close of the form.
If the boolean internal is set to true, the function may deposit state
to the data_obj, but will not expect any sort of activity on MIC's
part. This is for propagation across other boundaries or sub-boundaries.
retrieve_state (scalar data_obj)
This function is called as part of the initialization process and sets
the fieldspace into the proper state to comply with MIC.
9.3 Error Packagers
This section details the functions which the error packaging objects
which MIC makes use of must support.
- No directory off root should bear the same name as any fieldspace
- No directory off the root with the same name as a fieldspace
should have a page called `handle_rolls'
A.2 Fieldspaces
- No fieldspace should contain `verifies'
Appendix B MIC Driver Specifications
The MIC driver should be an executable that expects to reside on a
machine and be called to handle certain HTTPD requests. It will
expect to look in the environment variables `REDIRECT_URL' and
`PATH_INFO.' These should contain the appropriate information about
the url being requested. The driver will expect to find
/\/[\w_]+\.pile\//
where the characters before the `.pile'
indicate the pile name and the characters along with the extension
indicate the name of the file containing all the subroutines and
definitions for the pages within the pile.
The driver will then require that file and take everything after
`.pile' to be a page name. It will then call the function associated
with the page name. This subroutine is formed by `Pile::<pile
name>::<page>' where page is the page name, sans valid extension,
prepended by recursive parent directories seperated by `::.' This
function may or may not be mapped to a mounted pile function.
The setup function should be called unless it returns null, then the
value returned should be returned by the driver (ostensibly to the web
server) and driver's job is done.
If setup runs successfully, then the page function will be called,
either in the parent pile, or in the proper mounted pile. If no errors
are thrown, then the cleanup routine should be called in a safe
context and errors reported if the evaluation fails.
If the page routine throws an error, then the driver should call the
function handle_exceptions function. This function is evaluated in a
safe context, and if successful, the return value will be returned,
cleanup will be called as above, and execution will cease. If there
was a problem with the handle_exceptions function, then this problem
should be reported.
If there is no handle exceptions function, then the error should be
reported as gracefully as possible, cleanup should be called as above,
and execution should cease. Note that cleanup is always called.
Appendix C Suggested MIC-Compliant Datatype and FieldSpace Specification
C.1 FieldSpace
See 9.2 for functions required by MIC to
compile. The functions listed here are not needed by MIC to compile,
but are needed in order that required functionality be provided to the
MIC coder.
bool verify_fields (array ref field_list)
This object method takes a reference to a list of fields to run field
verification over and returns a true if none of the fields were found
to be in error, and false otherwise. This method is not side effect
free. The fieldspace object will take note of the fields errorfull
state and act just as if a vfield tag were in place associated with
the field.
bool verify_verifies (array ref verify_list)
Has essentially the same effect as verify_fields(), but will
cause the verifications defined with the MICverify tag to be run at
the point where this object method is called.
These functions are not required, but could be useful to programmers
and so the functionality and names are suggested for the encouragment
of consistent MIC code and standards.
bool changed_p (scalar field_name, bool virtual)
This function returns true if field_name has been changed during the
lifetime of the current field chain (regardless of its current
value). If the optional boolean arguement is set, then the function
will check to see if any field of that virtual name1 has changed.
bool in_error (scalar field_name, bool virtual)
Same as changed_p excepting that the boolean returned will
indicate whether the field is in error for any reason.
bool in_ferror (scalar field_name, bool virtual)
Same as changed_p excepting that the boolean returned will
indicate whether the field is in error with regards to a field-data
check.
bool in_vferror (scalar field_name, bool virtual)
Same as changed_p excepting that the boolean returned will
indicate whether the field is in error with regards to an arbitrary
verification check.
bool errors_p ()
Returns true if there are any errors in the fieldspace.
C.2 Data Types
The required functions are outlined in ??, so here, we only enumerate suggested interfaces.
add_possible (scalar values)
values should be a reference to a hash like in set_possible, but this
function should be provided for convenience to expand possible
values.
int data_count ()
Will return the number of discrete data items encapsulated.
set_attribute (scalar attributes)
Takes a reference to a hash which will be used to define how the data
should be displayed to end users.
set_parameters (scalar parameters)
Takes a reference to a hash defining constraints on data beyond the
requirement that it be canonicalizeable.
set_format (scalar format)
Takes a reference to a hash defining how to format the canonical value
when the format() function is called.
- 1
- A virtual
name being a field name prepended by zero or more group names in order
of relationship with a `::' separating each group name.
This section documents known bugs for which there are no plans to fix
for the 3.0 release. They should be fixed for the final release,
3.01.
- It is glaringly difficult to use many features of the error
reporting parts of MIC without a good understanding of the internals
of the error packaging objects, esp. with regards to dynamic
fields. This needs further evaluation and design.
- Although nested groups are usable, there is state loss in
that if there is a parent group is pageable and children groups are
pageable, then when the parent is paged, the children will believe
their index is that of the the index of the children on the previous
instantiation of the parent. That is, if on page one of the parent
group, we page to page two of the child group, then when we page to
page two of the parent, we will be on page two of the child, even if we
have never specifically paged that instantiation.
- It is believed that the maxnum attribute of the MICgroup tag has
no effect.
- The error marking routines break abstractions and need to be
implemented in their own tag, or MICinput needs better design.
Note that portions of the code presented in this section are dependant
on interfaces which are outside the scope of this document (e.g., the
arbitrary code within a MICdefine). Thus, the exact syntax of the code
that any given program may contain may differ. An effort has, however,
been made to make the examples clear as to their meaning.
E.1 Embedded Logic
Consider the following snippets:
from login.html:
...
Please enter your user name and password:
<form action="check_password.mic">
User Name:<input name="username" type="text"><br>
Password:<input name="password" type="password"><br>
<input name="login_submit" type="submit" value="Submit">
</form>
...
*******
from check_password.mic:
...
<MICif test="check_login($cgi->param('username'),
$cgi->param('password'))">
return Pile::example::index($cgi);
</MICif>
<MICelse>
return Pile::example::login($cgi);
</MICelse>
...
*******
The above example illustrates the use of simple embedded
logic, calling pages as functions, and the use of HTML forms within
MIC (which is trivial). In the above example, we are using a direct
CGI call to check the value of the fields, which is discouraged in
general, but may be appropriate in certain cases (see ??. The above, in particular, is a bad example in that
respect as far as the style guidlines are concerned.
On the basis of the result of the function check_login, we either
return the index page or return to the login page. Note that the
browser will believe that the page being displayed is called
`check_login.mic,' but since all three of the pages of concern are at
the same directory level, this is okay as far as functionality is
concerned.
Consider the following code snippets:
from employee_entry.fs:
...
<MICgroup name="employees" obj="$obj"
numvar="$index" numdisplay="10" dummyok="true">
<Micdefine name="eid" data="employee_id"
type="text">
get_employee_id($index);
</MICdefine>
<MICdefine name="name" data="text"
type="text">
get_employee_name($index);
</MICdefine>
<MICdefine name="ssn" data="ssn" type="text">
get_employee_ssn($index);
</MICdefine>
<MICdefine name="salary" data="uscurrency"
type="text">
get_employee_salary($index);
</MICdefine>
</MICgroup>
...
*******
from enter.html:
...
<form action="overridden"
MICfieldspace="employee_entry">
<MICdynamicdisplay>
<hr>
Name: <MICdisplay name="name">
SSN: <MICdisplay name="ssn"><br>
Salary: <MICdisplay name="salary><br>
</MICdynamicdisplay>
<MICrollback name="entry_submit"
assocdynamic="employees">
<vinstatiated>
</MICrollback>
<MICrollover name="entry_submit"
assocdynamic="employees">
<vinstantiated>
</MICrollover>
<br>
<MICsubmit name="entry_submit" value="Submit"
goto="process">
<vinstantiated>
</MICsubmit>
<input type="submit" name="entry_submit"
value="Submit">
</form>
...
*******
from process.html:
...
<MICPerl>
my %new_employees;
</MICPerl>
<form action="none" MICfieldspace="employee_entry">
<MICdo name="eid" numvar="$index">
$new_employees{$index}->{id}->{$field->value()};
</MICdo>
<MICdo name="name" numvar="$index">
$new_employees{$index}->{name}->{$field->value()};
</MICdo>
<MICdo name="ssn" numvar="$index">
$new_employees{$index}->{ssn}->{$field->value()};
</MICdo>
<MICdo name="salary" numvar="$index">
$new_employees{$index}->{salary}->{$field->value()};
</MICdo>
</form>
<MIClist iterator="$index" list="keys %new_employees">
<MICPerl>
my $new_id;
if ($new_employees{$index}->{id}) {
$new_id = new_employee_id();
$new_employees{$index}->{id}->{$new_id};
add_employee($new_employees{$index});
}
else {
update_employee($new_employees{$index});
}
</MICPerl>
</MIClist>
...
*******
The above code is meant to take new employee data and store it in a
database as well as display and update existing employee data. The
default code blocks will fill in the first n employees (where n is the
number of existing employees). Assume that the default code block
returns null when we go off the first n employees, leaving blank text
boxes.
Let us assume that we have strict error checking on all the data so
that we know when we get to the processing page, it is all good
data. That is, assume there is a lot of error checking and reporting
that is not shown. Part of this error checking is to ensure that if
one field is filled out, then the other two are.
Note that because of the instantiation rules of MIC, to change this
form from only adding new employees, to adding and updating means that
we only need to add 6 lines in the fieldspace file and 6 in the
process.html (all of which are shown). When we get to the process
page, we blindly load up everything that is there, only noting the
state of the eid field at the very end. This is okay, since none of
the blank fields or unchanged fields for existing customers will be
instantiated, so all our data on the processing page are interesting.
So, we then MICdo over the fields, building up a hash, which is then
passed into the add_employee function, which takes the information
found in the hash reference and adds it to database or the
update_employee function.
E.3 Multiple Values
Consider the following code snippets:
from multiple.fs:
...
<MICdefine name="selector" data="AtomicData::Text" type="HTMLIO::Select">
"daniel";;
{
$field->display({multiple => 3}};
$field->set_possible_hash({zane => Zane,
daniel => Daniel,
charles => Charles,
sam => Sam,
micheal => Michael});
}
</MICdefine>
...
The above creates a field that will display itself as a select box
with the multiple param set to three and the items as indicated in the
anonymous hash passed to set_possible. Daniel (value daniel) will be
highlighted/selected initially.
*******
from select.html:
<html><body>
<form action="overridden" MICfieldspace="multiple">
Please select everyone to invite to your party:<br>
<MICinput name="selector"><br>
<input type="submit" name="select_submit"
value="Submit">
<MICsubmit name="select_submit" value="Submit"
goto="display">
</MICsubmit>
</form>
</html></body>
*******
from display.html:
<html><body>
<form action="none" MICfieldspace="multiple">
The revelers are:<br>
<MIClist iterator="$reveler"
list="$fs->get_field(`selector')->value()">
<b>$reveler</b><br>
</MIClist>
<input type="submit" name="multiple_submit"
value="Revise">
<MICsubmit name="multiple_submit" value="Revise"
goto="select">
<input type="submit" name="multiple_submit"
value="Done">
<MICsubmit name="multiple_submit" value="Done"
goto="done">
</form>
</body></html>
*******
If we point a user to the select page, they will get a 3-row select
box with the name `Daniel' highlighted. On this page, the field will
contain the single value, `daniel.' Suppose the user selects
`Charles,' `Sam,' and `Michael' (poor Zane) and hits submit. They will
then go the display page and be presented with the names `Daniel,'
`Charles,' `Sam,' and `Michael'1. Remember that `Daniel' was never deselected. The fieldspace
now contains `daniel,' `michael,' `charles,' and `sam.' They then hit
the `Revise' button and are taken back the revise page. The fieldspace
contains all value but `zane' and the select box has all names
selected except `Zane.' The user then selects `Zane' and deselects
`Daniel' and resubmits. Now, we behave as before with `Zane' and
`zane' substituted for `Daniel' and `daniel.' Happy with the
arrangements, the user then hits `Done' and it does its trivial thing.
- 1
- In no particular
order
This document was translated from LATEX by
HEVEA.