Method and apparatus for generating object oriented user interfaces

A user interface generator for developing object oriented user interfaces. The user interface generator creates separate class files containing user interfaces suitable for use in different languages. The interfaces can be easily implemented in an object oriented application program through inheritance. The invention allows the rapid generation of complex user interfaces to minimize costs associated with internationalization of software.

FIELD OF THE INVENTION 
This invention relates to the development of user interfaces, and in 
particular to a user interface generator which enables the rapid 
development of complex user interfaces for use in object oriented 
programs. The invention greatly reduces the effort required to 
internationalize software products. 
BACKGROUND OF THE INVENTION 
A well-designed and highly intuitive user interface can be the difference 
between a successful product and an unsuccessful one. Because of its 
market importance, much planning and extensive development is expended not 
only in the initial design and development of the user interface, but also 
in the repetitive modifications and refinements to the user interface 
which occur while testing the software. Consequently, the user interface 
can be a relatively expensive portion of the overall software product. 
Many software products are sold internationally. Readying a product for 
release in another country typically requires modifying the user 
interface, since a user interface designed for use in a country in which 
one particular language is predominately used will typically be unsuitable 
for use in another country in which another language is predominately 
used. The process of converting a user interface for use in different 
countries is referred to as "internationalization." Since software 
products are frequently released in many different countries, the 
modifications to the user interface which are necessary to 
internationalize the product for the various countries can be relatively 
expensive. 
Some software products and operating systems, such as the MICROSOFT WINDOWS 
operating system, provide features, such as resource files, which can be 
used in conjunction with certain software development languages, such as 
C++ to help address such internationalization issues. However, resource 
files are not universally available in all development languages, and in 
fact, are not offered in the JAVA language, which is one of the most 
popular programming languages. Resource files also suffer from many 
disadvantages. The development environments which generate user interfaces 
which rely on resource file capabilities do so by marking the application 
program with `marker` characters which, if accidentally disturbed by a 
developer editing the application, will cause the program to cease 
working. Further, resource files have no object oriented characteristics, 
and thus cannot leverage the advantages of object oriented languages, such 
as inheritance, encapsulation and polymorphism. In view of the importance 
and widespread acceptance of object oriented programming languages, this 
limitation is highly undesirable. Moreover, in most conventional 
development environments, the code necessary to implement the user 
interface is intermixed and intertwined with the code which implements the 
functionality of the program. For both development and maintenance 
reasons, it would be preferable if the code to implement the user 
interface could be encapsulated from the remainder of the program. 
The JAVA programming language has become increasingly popular over the last 
several years because of its write-once run-anywhere portability. JAVA is 
used not only for creating programs, or applets, which execute over a 
network, but also for stand-alone applications. Another reason for JAVA's 
popularity is its close adherence to true object oriented programming 
philosophy, and the elimination from the language of certain programming 
constructs, such as pointers, which can cause bugs in the software which 
are very difficult to locate. 
Internationalization becomes a very important issue with regard to JAVA's 
ability to create program applets which automatically download across a 
network upon access of a World Wide Web page. The nature of an Internet 
WEB page is that it can be accessed by anyone in the world having access 
to the Internet. JAVA applets capable of providing only a single user 
interface in one language are essentially useless to individuals not 
conversant in that language. For commercial ventures, shutting out a large 
number of potential customers due to language barriers is undesirable. 
From the foregoing, it is apparent that a method and system which enables 
the rapid generation of user interfaces in multiple languages, which 
isolate the user interfaces into one or more separate classes, and which 
generate user interfaces that are operative to be used in an object 
oriented programming language would be highly desirable. 
SUMMARY OF THE INVENTION 
It is one object of this invention to provide a method and system which 
enables the rapid development of user interfaces. 
It is another object of this invention to provide a method and system for 
generating object oriented user interfaces. 
It is yet another object of this invention to provide a method and system 
for generating user interfaces which interface with an application program 
through object oriented techniques, such as inheritance. 
It is still another object of this invention to provide a method and system 
for implementing resource file capabilities in the JAVA programming 
language. 
Additional objects, advantages and other novel features of the invention 
will be set forth in the description that follows. To achieve the 
foregoing and other objects, and in accordance with the purposes of the 
present invention as described above, a user interface generator is 
provided for implementing a plurality of user interfaces for use in an 
object oriented program. The user interface generator reads a parameter 
structure containing commands identifying each user interface. The 
commands include definitions of user interface components, such as 
buttons, text boxes, list boxes, and the like. At least some of the user 
interface components preferably have textual labels associated therewith. 
The textual labels for each respective user interface can be in a language 
which is different from the language used by the textual labels in the 
other user interfaces. A language class is generated for each user 
interface based on the commands in the parameter structure. Each language 
class contains methods and data for creating the user interface components 
and textual labels associated therewith. A decision, or selection, class 
operative to instantiate one of the language classes as a function of a 
selected language is generated. The user interfaces can be used with an 
object oriented program which instantiates a first object from a derived 
class which inherits from the decision class. A second object is 
instantiated from one of the language classes as a function of a selected 
language, and the user interface associated with the selected language is 
displayed. 
According to one embodiment of this invention, a link class is generated, 
and each language class implements the link class. The decision class 
contains a link class variable and is operative to set the link class 
variable to reference one of the language classes as a function of the 
selected language. 
According to another embodiment of this invention, the commands in the 
parameter structure can identify which events associated with the user 
interface components will be processed by the object oriented program. The 
language class which generates the user interface is operative to invoke 
an event method in the object oriented program upon the occurrence of any 
of the identified events. The command in the parameter structure can 
include the name of the particular event method in the object oriented 
program to invoke for each event. According to another embodiment of this 
invention, an abstract contract class is generated which inherits from the 
decision class. The abstract contract class contains an abstract event 
method which is overridable by the event method in the object oriented 
program. The first object instantiated in the object oriented program 
inherits from the decision class through the abstract contract class. 
The user interface generator according to this invention enables the rapid 
development of multiple user interface classes, each of which is operative 
to implement a separate user interface in a particular language. The user 
interface classes interact with an object oriented program through the 
object oriented technique of inheritance. The object oriented program can 
instantiate an object from one or more of the generated user interface 
classes depending upon the suitability of a particular user interface. 
The user interfaces generated by the method and system according to this 
invention are true object oriented classes, and accordingly offer the 
benefits of object oriented languages, including encapsulation, 
polymorphism, and inheritance. The user interface generator according to 
this invention also allows an object oriented program to control the 
behavior of the user interface by providing event handling methods which 
are invoked upon the occurrence of user interface events. 
Still other objects of the present invention will become apparent to those 
skilled in this art from the following description, wherein there is shown 
and described preferred embodiments of this invention. As will be 
realized, the invention is capable of other different obvious aspects all 
without departing from the invention. Accordingly, the drawings and 
description will be regarded as illustrative in nature and not as 
restrictive.

Reference will now be made in detail to present preferred embodiments of 
the invention, examples of which are illustrated in the accompanying 
drawings, wherein like numerals indicate the same elements throughout the 
views. 
DETAILED DESCRIPTION 
Referring now to FIG. 1, a block diagram is shown which illustrates a user 
interface generator, such as application generator 26, according to one 
embodiment of this invention. Application generator 26 reads a parameter 
structure 20 which contains one or more groups (e.g. 22 and 24) of 
commands, each of which groups defines a separate user interface. 
Parameter structure 20 can be a file generated manually, through the use 
of a text editor, or can be a memory structure generated by a front end 
program which creates suitable commands based upon input from a user. The 
commands in groups 22 and 24 set forth the various user interface 
components, such as buttons, lists, panels, text areas, and other 
conventional user interface components, as well as textual labels, if any, 
associated with such user interface components. The language used for the 
textual labels in group 22 can be different from the language used for the 
textual labels in group 24. In addition to the user interface components, 
commands can identify particular events associated with such components, 
such as a key.sub.-- press event and a key.sub.-- release event, which are 
to be processed in an object oriented program which will implement the 
generated user interfaces. 
The user interfaces defined by groups 22 and 24, respectively, can differ 
not only in the language they use to label their components, but also in 
more substantive ways, such as in the number and types of components, and 
the particular events for which notification is desired. Thus, the various 
user interfaces in parameter structure 20 may appear very different from 
one another. 
Based on the commands in parameter structure 20, application generator 26 
generates several output files suitable for generating the user interfaces 
defined by the commands. For each separate user interface defined in 
parameter structure 20, application generator 26 generates a language 
class (e.g., 28 and 30) which is a class structure containing methods and 
data suitable for generating the user interface defined by the respective 
commands in groups 22 and 24. For example, language class 30 is a class 
containing methods and data suitable for generating a user interface as 
defined by the commands in group 24, and language class 28 is a class 
containing methods and data suitable for generating a user interface as 
defined by the commands in group 22. Application generator 26 also 
generates a link class 32, a decision class 34, and a contract class 36, 
each of which will be described in greater detail below. 
The files generated by application generator 26, such as language classes 
28 and 30, link class 32, decision class 34 and contract class 36 are 
files which contain program statements suitable for use in an object 
oriented programming language, such as the JAVA programming language. It 
is intended that such files be used in conjunction with an object oriented 
application program through inheritance. Application generator 26 can be 
developed in any suitable programming language, including object oriented 
or non-object oriented programming languages. 
Parameter structure 20 can also be referred to as a resource file, in that 
it contains instructions for the creation of user interface components. 
However, as will become apparent from the description herein, parameter 
structure 20 provides much greater functionality than conventional 
resource files, in that not only can events be identified for processing 
by an object oriented program, but also that parameter structure 20 is 
used to generate true object oriented user interfaces. 
FIG. 2 is a block diagram which shows the relationship between the files 
generated by application generator 26 and a class defined in an object 
oriented program which implements the user interface generated by 
application generator 26. FIG. 2 illustrates this relationship through the 
use of pseudo-JAVA programming statements. For the ease of illustration, 
JAVA's lowercase requirements have been ignored. An application program 38 
(developed by an individual, for example) contains a class definition at 
code segment 42 which, as illustrated by arrow 43 extends, or inherits, 
from contract class 36. As illustrated in FIG. 1, contract class 36 was 
generated by application generator 26 in response to the commands in 
parameter structure 20. Class 36 is referred to as a "contract" class 
because it in some respects defines the "contract" between the 
user-developed application program 38 and the user interface classes 28 
and 30. As discussed in greater detail herein, contract class 36 contains 
component variables and abstract event methods which allow application 
program 28 and user interface classes 28 and 30 to interact. 
Contract class 36 includes a code segment 44 which specifies (as 
represented by arrow 46) that contract class 36 extends, or inherits, from 
decision class 34. Decision class 34 contains various code segments 
necessary to run-time, or dynamically, instantiate an object from a 
particular language class such as language class 28. For purposes of 
illustration, language class 30 is not shown in FIG. 2, however, depending 
upon the user's environment or upon user selection, language class 30 may 
be instantiated instead of language class 28. Decision class 34 contains a 
code segment 48 which declares a variable "LLINK" of type "LINK." The 
"LINK" variable type refers to an object instantiated from link class 32 
(FIG. 1), which can be a JAVA interface class of type `LINK`. Link class 
32 essentially creates the run-time binding between the application object 
and the user interface object. Through link class 32, decision class 42 
can dynamically instantiate an object from the desired language class. 
According to one embodiment of this invention, the "LINK" variable type is 
a JAVA interface class. Each of language classes 28 and 30 `Implement` 
link class 32, as shown in code segment 52. 
FIG. 3 is a block diagram showing the run-time relationship between the 
various objects instantiated from the classes shown in FIG. 2. FIG. 3 
illustrates this relationship through the use of pseudo-JAVA programming 
statements, again ignoring JAVA's lowercase requirements for ease of 
illustration. Application program 38 contains a derived class 47. The 
definition of derived class 47 includes code segment 42, which establishes 
the inheritance relationship between derived class 47 and abstract 
contract class 36. Derived class 47 also includes code segment 56 which 
contains event handling code. Such event handling code is generated by the 
developer of application program 38 to process the events which were 
specified in parameter structure 20. Code segment 54 illustrates one 
mechanism for specifying which of language classes 28 or 30 to use to 
generate the user interface. Although code segment 54 "hard-codes" the 
language to use, application program 38 typically will request from a user 
a preferred language, and based on the user's response determine which 
language class to use for the user interface. As illustrated by arrow 62, 
upon execution of code segment 54, code segment 60 in object 58 will be 
executed and the specified language will be stored in a `LANG` variable in 
code segment 61, for later use. 
Code segment 39 causes the instantiation of object 58 from derived class 
47. The various object portions of object 58 defined by the respective 
classes are delineated for purposes of illustration. For example, object 
portion 34' reflects the portion of object 58 which is instantiated by the 
instructions in decision class 34. Likewise, object portion 36' of object 
58 represents the portion instantiated from the instructions in contract 
class 36, and object portion 47' of object 58 reflects the portion 
instantiated by the software instructions in derived class 47. 
During the instantiation of object 58, code segment 64 (the constructor) of 
object portion 47' is invoked, which in turn invokes the constructor of 
its parent class, contract class 36. As shown in code segment 66, the 
constructor of object portion 36' in turn invokes the constructor of its 
parent class, decision class 34. At code segment 70, the constructor of 
object portion 34' uses the variable `LANG` (previously initialized from 
code segment 54) in code segment 61 to determine what language has been 
selected. Based on the selected language, object portion 34' at code 
segment 70 instantiates an object from the appropriate language class. In 
the example shown in FIG. 3, object 59 is instantiated from language class 
28. After instantiation of object 59, code segment 70 invokes a method of 
object 59, passing a reference to itself to object 59. At code segment 77, 
object 59 stores the reference to object 58 in a variable at code segment 
75. This variable establishes a linkage to object 59, including the data 
and methods defined in object portion 36'. At code segment 79, object 59 
creates and initializes the appropriate user interface components defined 
in parameter structure 20. Some, or all of these components can be defined 
in object portion 36', which allows access to such components by 
application program 38 through inheritance. Since derived class 47 
inherits from contract class 36 and decision class 34, application program 
38 can access any of the variables and/or methods defined in either of 
contract class 36 or decision class 34. Although not shown herein, 
contract class 36 can also contain abstract event methods, which can be 
overrided in derived class 47 and invoked by object 59 upon the occurrence 
of an event associated with the user interface. This enables application 
program 38 to provide desired functionality to the user interface created 
by object 59. 
The ability of code segment 70 to selectively instantiate a user interface 
object, such as object 59, from any of a plurality of language classes, 
allows the run-time designation of a user interface based on external 
criteria. Moreover, the ability to designate in parameter structure 20 the 
events for which application program 38 will be notified allows 
application program 38 to implement unique functionality in each user 
interface. 
Application generator 26 can be written in any conventional or special 
purpose programming language. One phase of application generator 26 
involves parsing the command tokens and unique identifiers specified in 
parameter structure 20. The ability to read data and parse tokens is the 
subject of many books in the field of computer science, and is well known 
to those skilled in the art, and thus will not be discussed in detail 
herein. Another phase of application generator 26 involves generating the 
appropriate software instructions and files as a function of the contents 
of the commands in parameter structure 20. Although parsing and code 
generation are known to those skilled in the art, a mechanism for 
accomplishing the parsing and code generation will be disclosed, followed 
by an example of a parameter structure 20 and corresponding generated 
output files. 
OVERVIEW 
According to one object oriented implementation of application generator 
26, a tree of objects is built during the parsing phase, with each object 
representing a user interface component specified in parameter structure 
20. During the code generation phase, the tree of objects is traversed, 
and each object in the tree is requested to generate the appropriate code 
for the respective object type and context of the code. 
To generate a tree of objects, the parsing module has a separate class for 
each type of user interface component which can be defined in parameter 
structure 20, such as a button class, a panel class and a checkbox class. 
Each class includes data members suitable for storing the attributes of a 
particular component as specified in parameter structure 20, and one or 
more methods suitable for generating code for declaring and initializing a 
component of that object type. For example, a TextField class includes a 
data member for storing the identifier of the TextField, a data member for 
storing a default text, and pointers for pointing to other objects such as 
a layout object and an action object. As the parser reads a particular 
type of user interface component in parameter structure 20, it 
instantiates an object from the appropriate type of class, and stores the 
specified information in the appropriate data members of the instantiated 
object including such information as the identifier, if any, the actions 
for which the application program wishes to be notified, the names of 
methods to invoke for each action, and the layout of the object. Thus, for 
each TextField component specified in parameter structure 20, the parser 
will instantiate a separate object containing data describing the 
TextField. The objects are maintained in the tree through pointers. The 
classes preferably derive from common base classes to allow inheritance of 
common data members and methods. When the parsing phase is completed a 
tree of objects exists, with each object representing a user interface 
component. 
During the code generation phase, the class files which need not be 
modified are created, preferably by copying the class files from master 
class files. For example, in the example provided below, the contents of 
link class 32 are the same regardless of the commands in parameter 
structure 20. Thus, a new link class 32 is created by merely copying the 
commands from an existing master link class 32 to a new file. After these 
class files have been created, class files which are specially created 
depending upon the contents of parameter structure 20 are generated. For 
each class file which requires special modifications, the following 
procedure is performed. The appropriate template file associated with the 
respective class file is read. The commands are copied from the template 
file to a new class file until a marker character, such as a `$` 
character, is encountered. Upon encountering a marker character, the code 
generator traverses the tree of objects created during the parsing phase, 
and for each object in the tree the appropriate method of the object is 
invoked to generate code for that particular type of marker character. The 
particular code generation method invoked can differ depending upon the 
type of code to be generated. For example, an object can have a code 
generation method to generate a line of JAVA code which declares an object 
of that type, and can have a different code generation method to generate 
one or more lines of JAVA code which initializes an object of that type 
according to the commands in parameter structure 20. After traversing the 
tree of objects, the template file is again read, and the commands are 
copied from the template file to the new class file until the next marker 
character is encountered. The tree of objects is then again traversed. 
This cycle of copying commands from the template file and traversing the 
tree of objects continues until the template file is completely processed, 
and the new class file exists. 
EXAMPLE 
Application generator 26 will now be further described with reference to an 
example which illustrates the contents of the generated files based upon a 
particular parameter structure 20. The example will be described with 
reference to Tables 1-9 and FIGS. 4-6. Table 1 contains an example of a 
syntax, or grammar, of a command language suitable to define a user 
interface according to one embodiment of this invention. 
TABLE 1 
__________________________________________________________________________ 
(Grammar) 
__________________________________________________________________________ 
1 GRAMMAR SUMMARY 
2 stmt: 
3 LANGUAGE label // label = name of language 
4 [IDENT] BUTTON string layout actions // string = text in button 
5 [IDENT] CANVAS layout actions 
6 [IDENT] CHECKBOX string layout actions // string = text label of 
checkbox 
7 [IDENT] CHECKBOXGROUP layout actions {string} END // string list = 
8 // labels with radio buttons 
9 [IDENT] CHOICE layout actions {string} END // string list = choices 
10 
[IDENT] LABEL string layout actions // string = text of label 
11 
[IDENT] LIST int is.sub.-- multiple layout actions // int = # of 
rows, is.sub.-- multiple = 
12 
// single/multiple select 
13 
[IDENT] PANEL layout.sub.-- type layout actions {stmt} END 
14 
[IDENT] SCROLLBAR is.sub.-- horizontal int int layout actions // 
is.sub.-- horizontal = 
15 
// horizontal/vertical, ints are min and max values 
16 
[IDENT] TEXTAREA string layout actions // string = contents of text 
area 
17 
[IDENT] TEXTFIELD string layout actions // string = contents of text 
field 
18 
layout: 
19 
`{`string`}` // for BORDERLAYOUT; string = North, South, East, 
West, 
20 
Center 
21 
`{`string`}` // for CARDLAYOUT; string = name of card 
22 
`{``}` //for FLOWLAYOUT 
23 
`{``}` // for GRIDLAYOUT 
24 
layout.sub.-- type: 
25 
BORDERLAYOUT 
26 
CARDLAYOUT 
27 
FLOWLAYOUT 
28 
GRIDLAYOUT int int // ints designate size of grid 
29 
actions: 
30 
`[`{event.sub.-- name`:`string}`]` (// string = function called when 
event occurs 
31 
event.sub.-- name: 
32 
ACTION.sub.-- EVBNT 
33 
GOT.sub.-- FOCUS 
34 
KEY.sub.-- ACTION 
35 
KEY.sub.-- ACTION.sub.-- RELEASE 
36 
KEY.sub.-- PRESS 
37 
KEY.sub.-- RELEASE 
38 
LOST.sub.-- FOCUS 
39 
MOUSE.sub.-- ENTER 
40 
MOUSE.sub.-- EXIT 
41 
MOUSE.sub.-- DOWN 
42 
MOUSE.sub.-- UP 
43 
MOUSE.sub.-- MOVE 
44 
MOUSE.sub.-- DRAG 
45 
LIST.sub.-- SELECT 
46 
LIST.sub.-- DESELECT 
47 
SCROLL.sub.-- LINE.sub.-- UP 
48 
SCROLL.sub.-- LINE.sub.-- DOWN 
49 
SCROLL.sub.-- PAGE.sub.-- UP 
50 
SCROLL.sub.-- PAGE.sub.-- DOWN 
51 
SCROLL.sub.-- ABSOLUTE 
52 
WINDOW.sub.-- DESTROY 
53 
WINDOW.sub.-- ICONIFY 
54 
WINDOW.sub.-- DEICONIFY 
55 
WINDOW.sub.-- MOVED 
__________________________________________________________________________ 
The square brackets `[ ] shown in Table 1 indicate optional syntactical 
components. The characters `//` are used to indicate comments. The brace 
characters `{ }` used at lines 7, 9 and 13 represent zero or more 
repetitions. Brace characters surrounded by quotes, such as at lines 22 
and 23, represent literal brace characters. Although the grammar shown in 
Table 1 is one example of a command language, it is apparent that such a 
command language could comprise any suitable grammar. A parameter 
structure 20 containing commands following the grammar in Table 1, and 
which will be used in this example, is presented below in Table 2. 
TABLE 2 
__________________________________________________________________________ 
(Parameter Structure 20) 
__________________________________________________________________________ 
1 LANGUAGE English 
1 AddFilePanel PANEL BORDERLAYOUT 
2 PANEL FLOWLAYOUT {&lt;North&gt;} 
3 LABEL "FileName:" {} 
4 textField TEXTFIELD "MyFile.SAV" {} 
5 END 
6 PANEL BORDERLAYOUT {&lt;South&gt;} 
7 PANEL FLOWLAYOUT {&lt;East&gt;} 
8 BUTTON "OK" {} [ACTION.sub.-- EVENT : doOKAction] 
9 BUTTON "Cancel" {} [ACTION.sub.-- EVENT : doCancelAction] 
10 
END 
11 
END 
12 
END 
13 
14 
LANGUAGE Achish 
15 
16 
AddFilePanel PANEL BORDERLAYOUT 
17 
PANEL FLOWLAYOUT {&lt;North&gt;} 
18 
LABEL "FileName.sub.-- ACH:" {} 
19 
textField TEXTFIELD "MyFile.SAV"{} 
20 
END 
21 
PANEL BORDERLAYOUT {&lt;South&gt;} 
22 
PANEL FLOWLAYOUT {&lt;East&gt;} 
23 
BUTTON "OK.sub.-- ACH" {} [ACTION.sub.-- EVENT : doOKAction] 
24 
BUTTON "Cancel.sub.-- ACH" {} [ACTION.sub.-- EVENT : 
doCancelAction] 
25 
END 
26 
END 
27 
END 
__________________________________________________________________________ 
As shown in Table 2, parameter structure 20 contains commands for defining 
a first user interface in the English language at lines 1-12, and a second 
user interface in the Achish language (an imaginary language) at lines 
14-27. The same key words, or tokens, are used to define each user 
interface, however, this is not necessary. For example, the user 
interfaces could contain different user interface components and specify 
that notification be provided for different events, which may be desirable 
depending upon the particular language in which the user interface is 
being implemented. As can be seen with respect to lines 3 and 18, 8 and 
23and 9 and 24, the differences between the user interfaces defined in 
Table 2 is that the first user interface has textual labels in the English 
language and the second user interface has textual labels in the Achish 
language. 
Referring briefly to FIG. 1, application generator 26 reads parameter 
structure 20 (Table 2), and generates multiple files, such as language 
classes 28 and 30, link class 32, decision class 34, and contract class 
36. Because each respective generated file will have certain similarities 
regardless of the content of parameter structure 20, application generator 
26 preferably utilizes template files as input files for use in generating 
the various files. A template file is a skeleton file which contains the 
programming instructions which are common to all generated files of a 
particular type, and which identifies where unique programming 
instructions which implement the defined user interface are to be 
inserted. For example, application generator 26 uses a contract class 
template file, as set forth below in Table 3, to generate contract class 
36. 
TABLE 3 
______________________________________ 
(Template File) 
______________________________________ 
1 import java.awt.*; 
3 // ========================== 
4 // $