Wiki Markup |
---|
Hidden |
DO NOT EDIT THE CONTENT OF THIS PAGE DIRECTLY, UNLESS YOU KNOW WHAT YOU'RE DOING. THE STRUCTURE OF THE CONTENT IS VITAL IN BEING ABLE TO EXTRACT CHANGES FROM THE PAGE AND MERGE THEM BACK INTO SERVOY SOURCE{hidden} {sub-section:description|text=}The Maintenance plugin can be used in combination with the solution import hooks to control the workflow when importing solutions into the Servoy Application Server. The pre-import and post-import hooks |
The Maintenance plugin can be used in combination with the solution import hooks to control the workflow when importing solutions into the Servoy Application Server.
The pre-import and post-import hooks i.c.w.
...
the
...
Maintenance
...
plugin
...
allow
...
the
...
automatic
...
execution
...
of
...
administrative
...
tasks
...
on
...
the
...
Servoy
...
Application
...
Server
...
while
...
importing
...
solutions,
...
like:
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Solution
...
Import
...
Hooks
...
During
...
solution
...
import
...
from
...
the
...
Servoy
...
Admin
...
Page,
...
modules
...
with
...
certain
...
name
...
patterns
...
are
...
handled
...
in
...
a
...
special
...
way.
...
Modules
...
whose
...
names
...
start
...
with
...
"before_import"
...
are
...
handled
...
as
...
pre-import
...
hooks.
...
Their
...
...
event
...
handlers
...
are
...
executed
...
before
...
the
...
solution
...
is
...
actually
...
imported.
...
Similarly,
...
modules
...
whose
...
names
...
start
...
with
...
"after_import"
...
are
...
handled
...
as
...
post-import
...
hooks.
...
Their
...
...
event
...
handlers
...
are
...
executed
...
after
...
the
...
solution
...
is
...
actually
...
imported.
...
Note | ||||||||
---|---|---|---|---|---|---|---|---|
| =
|
| }||||||
In the next major version the pre_ & post_import hook modules will get their own SolutionType, instead of having to rely on SolutionName prefixes. {note} |
If
...
multiple
...
modules
...
exists
...
with
...
a
...
name
...
that
...
start
...
with
...
"before_import"
...
or
...
"after_import",
...
they
...
will
...
be
...
all
...
handled
...
in
...
this
...
way,
...
but
...
no
...
handling
...
order
...
is
...
guaranteed.
...
Pre
...
&
...
post
...
import
...
hook
...
modules
...
are
...
to
...
be
...
self
...
contained,
...
meaning
...
that
...
they
...
are
...
not
...
to
...
rely
...
on
...
included
...
modules.
...
Note | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| =
|
|
|
|
|
|
| }|||||||||||
In the next major version, the inclusion of modules in the pre & post import hooks will not be allowed. {note} |
During
...
the
...
execution
...
of
...
the
...
...
event
...
handlers
...
from
...
the
...
pre
...
&
...
post
...
import
...
hooks,
...
any
...
output
...
printed
...
with
...
...
will
...
be
...
redirected
...
to
...
the
...
import
...
log,
...
which
...
you
...
can
...
see
...
in
...
the
...
Servoy
...
Admin
...
page.
...
Typical
...
usage
...
scenario
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
All
...
these
...
steps
...
can
...
be
...
automated
...
by
...
creating
...
a
...
pre-import
...
and
...
a
...
post-import
...
hook
...
module.
...
The
...
pre-import
...
hook
...
module
...
can
...
have
...
the
...
following
...
function
...
set
...
as
...
its
...
...
event
...
handler:
...
Code Block | ||||
---|---|---|---|---|
| ||||
function onBeforeImportSolutionOpen()
{
application.output("Putting server into maintenance mode...");
plugins.maintenance.setMaintenanceMode(true);
application.output("Notifying and disconnecting connected clients...");
plugins.maintenance.sendMessageToAllClients("A solution upgrade will take place on the server. You will be disconnected in 2 minutes.");
application.sleep(2 * 60 * 1000);
plugins.maintenance.sendMessageToAllClients("A solution upgrade will take place on the server. You will be disconnected NOW.");
plugins.maintenance.shutDownAllClients();
application.output("Proceeding to import...");
}
{code}
|
This
...
function
...
puts
...
the
...
servoy
...
Application
...
Server
...
into
...
maintenance
...
mode
...
and
...
sends
...
a
...
notification
...
to
...
all
...
connected
...
clients,
...
telling
...
them
...
that
...
in
...
two
...
minutes
...
they
...
will
...
be
...
disconnected.
...
The
...
function
...
waits
...
for
...
two
...
minutes,
...
then
...
it
...
sends
...
another
...
message
...
to
...
the
...
clients,
...
telling
...
them
...
that
...
they
...
will
...
be
...
immediately
...
disconnected.
...
Then
...
all
...
connected
...
clients
...
are
...
killed.
...
From
...
this
...
moment
...
on,
...
no
...
new
...
client
...
will
...
be
...
able
...
to
...
connect
...
to
...
the
...
Server.
...
The
...
post-import
...
hook
...
module
...
can
...
have
...
the
...
following
...
function
...
as
...
its
...
onOpen
...
event
...
handler:
...
Code Block | ||||
---|---|---|---|---|
| ||||
function onAfterImportSolutionOpen()
{
application.output("Taking server out of maintenance mode.");
plugins.maintenance.setMaintenanceMode(false);
application.output("Clients can now connect to the server.");
}
{code}
|
This
...
function
...
takes
...
the
...
Server
...
out
...
of
...
maintenance
...
mode,
...
so
...
that
...
clients
...
can
...
again
...
connect
...
to
...
it.
...
Modifying
...
Database
...
Structure
...
and
...
Content
...
Using
...
the
...
Maintenance
...
plugin,
...
it
...
is
...
possible
...
to
...
programmatically
...
modify
...
the
...
database
...
structure.
...
It
...
allows
...
for
...
tables
...
to
...
be
...
created
...
and
...
dropped
...
or
...
modify
...
existing
...
tables
...
by
...
creating
...
and
...
deleting
...
columns.
...
On
...
solution
...
import,
...
Servoy
...
will
...
automatically
...
create
...
all
...
missing
...
tables
...
and
...
columns,
...
based
...
on
...
the
...
metadata
...
confined
...
in
...
the
...
solution
...
export
...
file.
...
When
...
more
...
control
...
is
...
required
...
on
...
how
...
the
...
columns
...
are
...
created
...
and/or
...
columns
...
need
...
to
...
be
...
removed
...
or
...
altered,
...
the
...
pre
...
import
...
hook
...
i.c.w.
...
the
...
Maintenance
...
plugin
...
allows
...
the
...
developer
...
full
...
control.
...
For
...
example
...
the
...
following
...
function,
...
set
...
as
...
handler
...
for
...
the
...
onOpen
...
even
...
of
...
a
...
pre-import
...
hook,
...
will
...
delete
...
a
...
no
...
longer
...
needed
...
column
...
from
...
a
...
table.
...
Code Block | ||||
---|---|---|---|---|
| ||||
function onSolutionOpenBeforeImport()
{
var server = plugins.maintenance.getServer("example_data")
if (server) {
var table = server.getTable("todo_list")
if (table) {
table.deleteColumn("todo_list_suggested_by")
var result = server.synchronizeWithDB(table)
if (result)
application.output("'Suggested By' column removed.")
else
application.output("Something went wrong while deleting column.")
}
else {
application.output("Table 'todo_list' cannot be found.")
}
}
else {
application.output("Server 'example_data' cannot be found.")
}
}
{code}
|
The
...
function
...
tries
...
to
...
obtain
...
a
...
reference
...
to
...
the
...
server
...
where
...
the
...
table
...
is
...
stored.
...
If
...
successful,
...
then
...
it
...
tries
...
to
...
obtain
...
a
...
reference
...
to
...
the
...
table
...
which
...
holds
...
the
...
obsolete
...
column.
...
If
...
this
...
step
...
is
...
also
...
successful,
...
then
...
it
...
deletes
...
the
...
column.
...
In
...
order
...
to
...
make
...
the
...
change
...
permanent,
...
the
...
table
...
must
...
be
...
synchronized
...
with
...
the
...
underlying
...
database.
...
In
...
pre-import
...
and
...
post-import
...
hooks,
...
besides
...
changing
...
the
...
database
...
structure,
...
you
...
can
...
also
...
change
...
the
...
database
...
content.
...
This
...
is
...
done
...
in
...
the
...
classical
...
way,
...
by
...
using
...
the
...
foundset
...
API.
...
It's
...
also
...
possible
...
to
...
use
...
the
...
...
...
to
...
modify
...
both
...
data
...
and
...
the
...
datamodel
...
in
...
the
...
database.
...
If
...
changes
...
are
...
made
...
to
...
the
...
datamodel
...
this
...
way,
...
after
...
completing
...
the
...
changes,
...
the
...
function
...
...
needs
...
to
...
be
...
called,
...
to
...
make
...
the
...
Servoy
...
Application
...
Server
...
aware
...
of
...
the
...
changes
...
made.
...
Note | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| =
|
|
| }|||||||
When deploying in a multi database SaaS model, any operation done on the Database Servers needs to be performed on each clone of the master Database Server. The [getDataModelClonesFrom(serverName) |#getDataModelClonesFrom]function can be used to retrieve a list of all Database Servers marked as clone of a master Database Server (using the " [ from|Database Servers#Data model cloned from]" property{note} {note:title=Maintenance plugin & [Servoy Cluster]}All operations performed by the Maintenance plugin when executed on a Servoy Application Server that is part of a Servoy Cluster will operate on the entire cluster.{note} {note:title=Maintenance plugin availablility}The Maintenance plugin is only available to the code being executed inside the pre and post import hooks. The plugin can not be used in normal clients{note}{sub-section}\\ {table:id=|class=servoy sReturnTypes}{tr:style=height: 30px;}{th}Return Types{th}{tr}{tr}{td}{span:class=sWordList}[JSClientInformation]{span}{span:class=sWordList}[JSServer]{span}{span:class=sWordList}[JSTableObject]{span}{td}{tr}{table}\\ {table:id=|class=servoy sSummery}{colgroup}{column:padding=0px|width=80px}{column}{column}{column}{colgroup}{tr:style=height: 30px;}{th:colspan=2}Method Summery{th}{tr}{tbody}{tr}{td}{td}{td}[#getConnectedClients]() Returns an array of JSClientInformation elements describing the clients connected to the server.{td}{tr}{tbody}{tbody}{tr}{td}[String]\[\]{td}{td}[#getDataModelClonesFrom](serverName) Retrieves a list with names of all database servers that have property DataModelCloneFrom equal to the parameter.{td}{tr}{tbody}{tbody}{tr}{td}[JSServer]{td}{td}[#getServer](serverName, \[mustBeEnabled\], \[mustBeValid\]) Retrieves an instance of JSServer corresponding to the server with the name specified through the "serverName" argument.{td}{tr}{tbody}{tbody}{tr}{td}[String]\[\]{td}{td}[#getServerNames](\[mustBeEnabled\], \[mustBeValid\], \[sort\], \[includeDuplicates\]) Retrieves a list with the names of all available database servers.{td}{tr}{tbody}{tbody}{tr}{td}[Boolean]{td}{td}[#isInMaintenanceMode]() Returns true if the server is in maintenance mode, false otherwise.{td}{tr}{tbody}{tbody}{tr}{td}void{td}{td}[#sendMessageToAllClients](message) Sends a message to all connected clients.{td}{tr}{tbody}{tbody}{tr}{td}void{td}{td}[#sendMessageToClient](clientId, message) Sends a message to a specific client, identified by its clientId.{td}{tr}{tbody}{tbody}{tr}{td}void{td}{td}[#setMaintenanceMode](maintenanceMode) Puts the server into/out of maintenance mode, depending on the boolean parameter that is specified (if the parameter is true, then the server will be put into maintenance mode; if the parameter is false, then the server will be put out of maintenance mode).{td}{tr}{tbody}{tbody}{tr}{td}void{td}{td}[#shutDownAllClients]() Shuts down all connected clients.{td}{tr}{tbody}{tbody}{tr}{td}void{td}{td}[#shutDownClient](clientId) Shuts down a specific client, identified by its clientId.{td}{tr}{tbody}{table}\\ {table:id=function|class=servoy sDetail}{colgroup}{column:padding=0px|width=100%}{column}{colgroup}{tr:style=height: 30px;}{th:colspan=1}Method Details{th}{tr}{tbody:id=getConnectedClients|class=node}{tr:id=name}{td} h6. getConnectedClients{td}{tr}{tr:id=sig}{td}{span:style=float: left; margin-right: 5px;}{span}{span:id=iets|style=float: left; font-weight: bold;}getConnectedClients{span}{span:id=iets|style=float: left;}(){span}{td}{tr}{tr:id=des}{td}{sub-section:getConnectedClients_des|text=|trigger=button}{sub-section}{sub-section:getConnectedClients_des|trigger=none|class=sIndent}Returns an array of JSClientInformation elements describing the clients connected to the server.{sub-section}{td}{tr}{builder-show:permission=edit}{tr:id=snc}{td}*Since*\\{sub-section:getConnectedClients_snc|text=|trigger=button}{sub-section}{sub-section:getConnectedClients_snc|trigger=none|class=sIndent} Replace with version info{sub-section}{td}{tr}{builder-show}{builder-show:permission=edit}{tr:id=prs}{td}*Parameters*\\{sub-section:getConnectedClients_prs|text=|trigger=button}{sub-section}{sub-section:getConnectedClients_prs|trigger=none|class=sIndent}{sub-section}{td}{tr}{builder-show}{builder-show:permission=edit}{tr:id=ret}{td}*Returns*\\{sub-section:getConnectedClients_ret|text=|trigger=button}{sub-section}{sub-section:getConnectedClients_ret|trigger=none|class=sIndent}{sub-section}{td}{tr}{builder-show}{builder-show:permission=edit}{tr:id=see}{td}*Also see*\\{sub-section:getConnectedClients_see|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getConnectedClients_see|trigger=none}{sub-section}{div}{td}{tr}{builder-show}{builder-show:permission=edit}{tr:id=link}{td}*External links*\\{sub-section:getConnectedClients_link|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getConnectedClients_link|trigger=none}{sub-section}{div}{td}{tr}{builder-show}{tr:id=sam}{td}{*}Sample* \\ {sub-section:getConnectedClients_sam|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getConnectedClients_sam|trigger=none}{code:language=javascript} // WARNING: maintenance plugin is only meant to run during solution import using before or after import hook(so not from Smart/Web client) //Returns an array of JSClientInformation elements describing the clients connected to the server. var clients = plugins.maintenance.getConnectedClients(); application.output("There are " + clients.length + " connected clients."); for (var i = 0; i < clients.length; i++) application.output("Client has clientId '" + clients[i].getClientId() + "' and has connected from host '" + clients[i].getHostAddress() + "'."); {code}{sub-section}{div}{td}{tr}{tr:class=lastDetailRow}{td}{td}{tr}{tbody}{tbody:id=getDataModelClonesFrom|class=node}{tr:id=name}{td} h6. getDataModelClonesFrom{td}{tr}{tr:id=sig}{td}{span:style=float: left; margin-right: 5px;}[String]\[\]{span}{span:id=iets|style=float: left; font-weight: bold;}getDataModelClonesFrom{span}{span:id=iets|style=float: left;}(serverName){span}{td}{tr}{tr:id=des}{td}{sub-section:getDataModelClonesFrom_des|text=|trigger=button}{sub-section}{sub-section:getDataModelClonesFrom_des|trigger=none|class=sIndent}Retrieves a list with names of all database servers that have property DataModelCloneFrom equal to the parameter.{sub-section}{td}{tr}{builder-show:permission=edit}{tr:id=snc}{td}*Since*\\{sub-section:getDataModelClonesFrom_snc|text=|trigger=button}{sub-section}{sub-section:getDataModelClonesFrom_snc|trigger=none|class=sIndent} Replace with version info{sub-section}{td}{tr}{builder-show}{tr:id=prs}{td}{*}Parameters* \\ {sub-section:getDataModelClonesFrom_prs|text=|trigger=button}{sub-section}{sub-section:getDataModelClonesFrom_prs|trigger=none|class=sIndent}serverName {sub-section}{td}{tr}{tr:id=ret}{td}{*}Returns* \\ {sub-section:getDataModelClonesFrom_ret|text=|trigger=button}{sub-section}{sub-section:getDataModelClonesFrom_ret|trigger=none|class=sIndent}[String]\[]{sub-section}{td}{tr}{builder-show:permission=edit}{tr:id=see}{td}*Also see*\\{sub-section:getDataModelClonesFrom_see|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getDataModelClonesFrom_see|trigger=none}{sub-section}{div}{td}{tr}{builder-show}{builder-show:permission=edit}{tr:id=link}{td}*External links*\\{sub-section:getDataModelClonesFrom_link|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getDataModelClonesFrom_link|trigger=none}{sub-section}{div}{td}{tr}{builder-show}{tr:id=sam}{td}{*}Sample* \\ {sub-section:getDataModelClonesFrom_sam|text=|trigger=button}{sub-section}{div:class=sIndent}{sub-section:getDataModelClonesFrom_sam|trigger=none}{code:language=javascript} // WARNING: maintenance plugin is only meant to run during solution import using before or after import hook(so not from Smart/Web client) //Retrieves a list with names of all database servers that have property DataModelCloneFrom equal to the parameter. var serverNames = plugins.maintenance.getDataModelClonesFrom('my_server'); for (var i=0; i<serverNames.length; i++) application.output("Process server " + i + ": " + serverNames[i]); {code}{sub-section}{div}{td}{tr}{tr:class=lastDetailRow}{td}{td}{tr}{tbody}{tbody:id=getServer|class=node}{tr:id=name}{td} h6. getServer{td}{tr}{tr:id=sig}{td}{span:style=float: left; margin-right: 5px;}[JSServer]{span}{span:id=iets|style=float: left; font-weight: bold;}getServer{span}{span:id=iets|style=float: left;}(serverName, \[mustBeEnabled\], \[mustBeValid\]){span}{td}{tr}{tr:id=des}{td}{sub-section:getServer_des|text=|trigger=button}{sub-section}{sub-section:getServer_des|trigger=none|class=sIndent}Retrieves an instance of JSServer corresponding to the server with the name specified through the "serverName" argument. If the optional argument "mustBeEnabled" is set to true, then the JSServer instance is returned only if the server is active. Similarly, if the "mustBeValid" optionalfrom" property |
Note | ||
---|---|---|
| ||
All operations performed by the Maintenance plugin when executed on a Servoy Application Server that is part of a Servoy Cluster will operate on the entire cluster. |
Note | ||
---|---|---|
| ||
The Maintenance plugin is only available to the code being executed inside the pre and post import hooks. The plugin can not be used in normal clients |
HTML Table | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||
|
HTML Table | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
HTML Table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|