Manifests

Summary:
  • The Curl IDE creates and maintains a manifest file as part of the IDE project.
  • You can edit the manifest file if necessary.
  • Manifest files help you manage and share application resources, and deploy your application.

Overview

A Curl application may consist of a single applet or script together with any number of related packages, graphical images, audio files, or other resources. These resources may be used by a large number of source files, and some resources may be shared by more than one application.
The location of such resources can change as an application is developed, tested, and deployed. A manifest is a special Curl source file used to manage the resources for one or more related Curl applications or libraries. Manifest files use the .mcurl extension. The Curl IDE creates a manifest file for you when you create a project, and maintains the manifest as you add and remove project resources. See Project Structure. If necessary, you can edit a manifest file by hand.
When you deploy a project, the IDE uses information you have supplied to create an appropriate manifest for the deployed application. See Deploying Projects.
You can use the applet or script declaration to specify a manifest by setting the manifest keyword to the name of the manifest file. The IDE automatically adds a manifest specification, like the one in the following code sample, to any applet file created in a project.
{curl 6.0 applet}
{applet 
    manifest = "manifest.mcurl",
    {compiler-directives careful? = true}
}
An applet or script that specifies a manifest automatically uses it to handle package import statements that do not explicitly specify a package location. When you use manifests, do not specify package locations directly in the source code, unless you have a specific reason to override the location specified in the manifest. The following example code shows an applet and its manifest.
Applet:
{curl 6.0 applet}
{applet 
    manifest = "manifest.mcurl",
    {compiler-directives careful? = true}
}
{import * from DOC.LOGO}

{value
    {show-logo}
} 
Manifest:
{curl 6.0 manifest}
{manifest APPLET-PROJECT}

{component file start.curl,
    location = "start.curl"
}

{component package DOC.LOGO,
    location = "load.scurl"
}

{component directory images,
    location = "images"
}
You can also use manifests to locate other resource files without directly specifying their URLs in your code through use of the manifest-url procedure.

Structure of Manifest Files

A manifest file must begin with a valid curl herald that identifies it as a manifest and specifies the Curl API versions for which it is valid. An optional manifest statement can follow the herald. The manifest statement can provide a name for the manifest, and additional meta-data. Curl recommends using the same naming convention for manifests as for packages. See Naming a Package. In the IDE, the manifest name is the name of the root node of the project. The IDE supplies the default manifest name PROJECT.
|| File:  manifest.mcurl
{curl 6.0 manifest}
{manifest PROJECT}
The rest of the manifest file may contain:

Manifest Components

The syntax of the component statement is:
Syntax:{component component-type COMPONENT.NAME,
    location = {url "path"} [, ...]
    [, name = value [, ...] ]
}
where:
component-type identifies the type of the component. Curl provides these standard component types; applet, package, manifest, and script. You can also use any valid identifier to describe another type of component. The IDE uses file for file resources and directory for directory resources.
COMPONENT.NAME names the component. It may be a compound name consisting of one or more valid Curl identifiers separated by dots, such as DOC.NAME.
location =
{url "path"}
specifies a location for the component. The path may be either a string representing an absolute URL, or a path relative to the URL of the file in which this component statement appears. You must provide at least one location, and can provide additional ones
name = value specifies optional additional meta-data for the component, where name is a valid Curl identifier and value is a valid meta-data value of the appropriate type.
The component-type and COMPONENT.NAME are the primary keys for locating components listed in the manifest. For Curl components, such as packages, the COMPONENT.NAME should be the same as the name declared in the source for the component. You can give other component types any name. You do not need to list all attributes of the resource in the manifest, but only attributes listed in the manifest can be used to locate components using the manifest.
For packages, all meta-data values specified in the component declaration must match the actual meta-data for the package or else an error results when the package is loaded. For instance if a package MY-PACKAGE declares its version to be 1.2:
{curl 6.0 package}
{package MY-PACKAGE, version = "1.2"}
Then the corresponding component declaration must provide the same version number or omit it entirely. These entries are correct:
{curl 6.0 manifest}
|| These entries are ok:
{component package MY-PACKAGE,
    version = "1.2",
    location = {url "my-package.scurl"}
}
{component package MY-PACKAGE,
    location = {url "my-package.scurl"}
}
This entry is inconsistent with the actual package.
{curl 6.0 manifest}
|| This one is inconsistent with the actual package:
{component package MY-PACKAGE,
    version = "1.3",
    location = {url "my-package.scurl"}
}
Unless you explicitly provide a list of curl-versions, the versions are assumed to be the same as those declared in the curl herald of the manifest file containing the component declaration.
Duplicate component declarations are allowed in manifests. Generally, when more than one might match, component declarations with higher versions are preferred over those with lower versions, otherwise the first one listed in the manifest is preferred.

Manifest Delegation

Manifests can delegate to other manifests using delegate-to:
{delegate-to MORE-COMPONENTS, location = "more-components.mcurl"}
The IDE adds a delegate-to statement to the project manifest when you add a delegate-to resource to the project.
The Curl RTE searches each delegate manifest in order whenever it does not find a desired resource in the delegating manifest. The herald of the delegate manifest must contain at least one API version in common with the manifest that delegates to it. For instance, manifest A with the herald:
{curl 2.0 manifest}
{manifest A}
could delegate to manifest B with the herald:
{curl 2.0, 2.1 manifest}
{manifest B}
but not manifest C:
{curl 2.1 manifest}
{manifest C}
The Curl RTE ignores a manifest without producing an error if the manifest herald does not include the API version used to evaluate the current applet or script. In the preceding example, manifest A can delegate to manifest B, and mainifest B can delegate to manifest C. However, if the current API is 2.0 then the contents of C are not be used in any lookups involving manifest A or manifest B.
These rules are intended to make it easy to use manifests to select components based on the currently active version of the Curl API.

Manifest Inclusion

Manifest files can also use include to add the contents of other files to the manifest.
{include "more-components.mcurl"}
The included file must contain expressions valid in a manifest file. You can include source files containing additional component declarations or separate manifest files with a compatible curl herald.
As with delegation, the herald of an included manifest must contain at least one API version in common with the manifest that includes it. For instance, manifest A with the herald:
{curl 2.0 manifest}
{manifest A}
could include manifest B with the herald:
{curl 2.0, 2.1 manifest}
{manifest B}
but not manifest C:
{curl 2.1 manifest}
{manifest C}
The Curl RTE ignores a manifest without producing an error if the manifest herald does not include the API version used to evaluate the current applet or script. In the preceding example, manifest A can include manifest B, and mainifest B can include manifest C. However, if the current API is 2.0 then the contents of C are not included.
Finally, any component declaration that does not explicitly specify its curl-versions inherits the value from the list of API versions declared in the herald for the manifest that most directly includes it. For example, components declared in manifest B would get the values 2.0 and 2.1 in their curl-versions whether or not B were loaded directly or as a result of inclusion by A.

Using Manifests to Locate Packages

An applet or script that has specified a manifest uses it to locate packages imported without an explicit location. The manifest must either contain an entry for the package or must refer through inclusion or delegation to a manifest that does.
Location information explicitly provided in source code overrides the manifest. Therefore, import statements must not use the location keyword, and a ComponentSelector used with import-package, must not have any location-hints.
The version number and other meta-data attributes specified in the import statement must match the component declaration in the manifest. The component declaration must declare all of the meta-data values used by the import.
The RTE uses the following procedure to find an instance of a package from information in a manifest:
  1. The name of the package, its version and any other meta-data attributes specific to the package are taken from the import statement. The version of the Curl API that is being used to run the current applet or script is also recorded.
  2. Possible matches are located in the manifest by identifying entries with a component type of "package", with the requested name, version and any other specified attributes.

    If no matches are found directly in the manifest, its delegate manifests are searched in order until matching entries are found. It is possible for multiple matches to be found, but they always come from the same manifest, since finding matches in one manifest stops the RTE from looking for matches in later delegate manifests.

    If no matches are found and the attributes match one of the built-in packages, such as CURL.LANGUAGE.REGEXP, then that is used; otherwise the import fails with an error.
  3. If there is more than one possible match, the candidates with the highest version numbers are preferred.
  4. If there is still more than one match then the match declared earliest in the manifest file is used.

Using Manifests to Locate Resources

Manifests may also be used to locate types of resources other than packages. This is most easily done by creating entries for the desired resources in the manifest and obtaining the location using the manifest-url function, which has the following signature:
Syntax:{manifest-url "component-type", "COMPONENT.NAME"
    [, manifest = alternate-manifest ]
    [, comparison-proc = proc ]
    [, name = value [, ...] ]
}
where:
component-typeis the component's type as given in the manifest.
COMPONENT.NAMEis the component's name as given in the manifest.
alternate-manifestspecifies the manifest to be searched. By default this is the manifest returned by get-default-manifest, but this allows a different one to be used. The alternate manifest must be a ComponentManifest object, which may obtained through a call to import-manifest.
proc specifies alternate selection criterion for choosing among multiple resources that match the specified attributes. By default, the matching resource with the highest version number or the one declared earlier in the manifest file will be selected.
name = value specify additional meta-data attributes for the target resource.
For example, suppose an applet needs to display an image but wants to make the identify of the actual image file configurable. The applet author can assign the image an arbitrary name and put matching entries in the manifest:
{curl 6.0 manifest}
|| Old version of product diagram
{component image PRODUCT-DIAGRAM,
    mime-type = "image/gif",
    content-size = 28000,
    version = "1.0",
    location = "old-product-diagram.gif"
}
|| New versions
{component image PRODUCT-DIAGRAM,
    mime-type = "image/gif",
    content-size = 28000,
    version = "3.0",
    location = "product-diagram.gif"
}
{component image PRODUCT-DIAGRAM,
    mime-type = "image/jpeg",
    content-size = 48000,
    version = "3.0",
    location = "product-diagram.jpeg"
}
The applet may then display the image without referring directly to its location:
{image source = {manifest-url "image", "PRODUCT-DIAGRAM"}}
Given the above manifest, this will select the 3.0 GIF version of the diagram since it has the highest version number and is declared before the 3.0 JPEG image. The applet could force the use of an older version of the image simply by specifying it in the manifest-url invocation:
{image
    source =
        {manifest-url "image", "PRODUCT-DIAGRAM",
            version = "1.0"
        }
}
Or it could force use of the JPEG version by providing the MIME type:
{image
    source =
        {manifest-url "image", "PRODUCT-DIAGRAM",
            mime-type = "image/jpeg"
        }
}
The applet may even customize the selection criterion to consider attributes of the runtime environment such as user preferences or available network bandwidth. For instance, the applet may prefer larger images when bandwidth is high and smaller images when it is low. This can be accomplished by writing a custom selection function and providing it to manifest-url:
{let use-big-images?:bool = false}
|| Return true if first component is preferred over the second:
{define-proc {pick-image
                 s1:ComponentSelector, s2:ComponentSelector
             }:bool
    let constant diff:int = s1.content-size - s2.content-size
    {if s1.component-type == "image" then
        {if diff > 0 then
            {return use-big-images?}
         elseif diff < 0 then
            {return not use-big-images?}
        }
    }
    || Use default criterion:
    {return {ComponentSelector.prefer-first? s1, s2}}
}
...
{image
    source =
        {manifest-url "image", "PRODUCT-DIAGRAM",
            comparison-proc = pick-image
        }
}
The chapter Deploying Projects contains additional information on using manifests in the IDE to organize and deploy applications.

Using Manifests to Locate Translation Files

Using a manifest to locate translation files is similar to locating other resources. Add entries that specify the package, the locale, and the corresponding translation file. For example, to specify English and Japanese translation files for a package called COM.EXAMPLE.DOC, add the following entries to the project manifest:
{component translations  COM.EXAMPLE.DOC,
    locale="en",
    location="resources/en/messages.xml"
}
{component translations COM.EXAMPLE.DOC,
    locale="ja",
    location="resources/ja/messages.xml"
}
The following entry specifies that the default translation file is English.
{component translations COM.EXAMPLE.DOC,
    locale="default",
    location="resources/en/messages.xml"
}

Links to Other Documentation

The following references point to additional documentation relevant to the use of manifests:
SyntaxBasic APIAdvanced API
curlappletComponentManifest
manifestscriptComponentSelector
componentimportget-default-manifest
delegate-tomanifest-urlget-empty-manifest
includefind-resourceimport-manifest
import-package