back to j2megame.org

JSR-238

Mobile Internationalization API (JSR-238) Mobile Internationalization API.

See:
          Description

Packages
javax.microedition.global Contains classes that implement the JSR-238, "Mobile Internationalization API".

 

Mobile Internationalization API (JSR-238)

Mobile Internationalization API.

This document defines JSR-238, the Mobile Internationalization API, version 1.0.

Author: JSR-238 Expert Group (e-mail: jsr-238-comments@jcp.org)

Status: Final Specification

Released: 2005-02-15

Copyright © 2004-2005 Nokia Corporation. All rights reserved.

Revision history
Version Published Description
0.1 2004-04-20 API proposal, revision 1
0.2 2004-05-04 First EG internal Community Review Draft
0.3 2004-05-24 Second EG internal Early Draft
0.4 2004-06-02 Submitted to JCP Early Draft Review with updated license
0.5 2004-08-25 First EG internal Public Draft
0.6 2004-10-04 Second EG internal Public Draft
0.7 2004-10-15 Public Review Draft
0.8 2004-11-29 Proposed Final Draft Candidate 1
0.9 2004-12-08 Proposed Final Draft Candidate 2
0.9.1 2004-12-14 Proposed Final Draft
0.9.4 2005-02-02 Final Specification, Release Candidate 1
0.9.5 2005-02-11 Final Specification, Release Candidate 2
1.0 2005-02-15 Final Specification

RESEARCH AND EVALUATION LICENSE

NOKIA CORPORATION IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE TERMS CONTAINED IN THIS LICENSE ("LICENSE"). PLEASE READ THE TERMS AND CONDITIONS OF THIS LICENSE CAREFULLY. BY ACCESSING OR USING THE SPECIFICATION YOU WILL BE BOUND BY THE TERMS OF THIS LICENSE.

JSR-238 Mobile Internationalization API Specification ("Specification")

Specification Lead: Nokia Corporation ("Specification Lead")

1. NOTICE; LIMITED LICENSE GRANTS

1.1 The Specification Lead hereby grants You a non-exclusive, non-transferable, worldwide, royalty-free, fully paid-up, limited license (without the right to sublicense) solely under intellectual property rights licensable by the Specification Lead to analyze and to use the Specification for research, evaluation, optimization and development purposes. In addition You may make a reasonable number of verbatim copies of this Specification in its entirety for Your private or internal use, as applicable, in accordance with the terms and conditions of this License.

1.2 No rights are granted under this License for internal deployment, the creation and/or distribution of implementations of the Specification for direct or indirect (including strategic) gain or advantage, the modification of the Specification (other than to the extent of Your fair use rights) or the distribution of the Specification or making the Specification available for 3rd parties.

1.3 Except as expressly set forth in this license, You acquire no right, title or interest in or to Specification or any other intellectual property licensable by the Specification Lead and no other rights are granted by implication, estoppel or otherwise. The Specification may only be used in accordance with the license terms set forth herein. This License will terminate immediately without notice from Specification Lead if You fail to comply with any provision of this License.

2. TRADEMARKS

2.1 Nokia is a registered trademark of Nokia Corporation. Nokia Corporation's product names are either trademarks or registered trademarks of Nokia Corporation. Your access to this Specification should not be construed as granting, by implication, estoppel or otherwise, any license or right to use any marks appearing in the Specification without the prior written consent of Nokia Corporation or Nokia's licensors. No right, title, or interest in or to any trademarks, service marks, or trade names of any third parties, is granted hereunder.

2.2 You shall not be allowed to remove any of the copyright statements or disclaimers or other proprietary notices contained in the Specification and You are obliged to include the copyright statement and the disclaimers, if any, in any copies of the Specification You make.

3. DISCLAIMER OF WARRANTIES

3.1 SUBJECT TO ANY STATUTORY WARRANTIES OR CONDITIONS WHICH CAN NOT BE EXCLUDED, THE SPECIFICATION IS PROVIDED "AS IS" WITHOUT WARRANTY OR CONDITION OF ANY KIND EITHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, AND STATUTORY ARE HEREBY DISCLAIMED. THE ENTIRE RISK ARISING OUT OF OR RELATING TO THE USE OR PERFORMANCE OF THE SPECIFICATION REMAINS WITH YOU.

3.2 THE SPECIFICATION MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. SPECIFICATION LEAD MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.

4. LIMITATION OF LIABILITY

4.1 TO THE FULLEST EXTENT PERMITTED BY LAW, IN NO EVENT WILL THE SPECIFICATION LEAD OR ITS SUPPLIERS BE LIABLE FOR ANY LOST PROFITS, LOST SAVINGS, LOST REVENUE, LOST DATA, PROCUREMENT OF SUBSTITUE GOODS, OR FOR ANY DIRECT, INDIRECT, INCIDENTIAL, SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES, EVEN IF THE SPECIFICATION LEAD OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES OR DAMAGES. IN ADDITION THE SPECIFICATION LEAD AND ITS SUPPLIERS WILL NOT BE LIABLE FOR ANY DAMAGES CLAIMED BY YOU BASED ON ANY THIRD PARTY CLAIM.

4.2 Some jurisdictions do not allow the exclusion of implied warranties, or the limitation for consequential damages, so Section 4.1 may not apply to You in whole, but in such case Section 4.1 will apply to You to the maximum extent permitted by applicable law.

5. EXPORT CONTROL

5.1 You shall follow all export control laws and regulations relating to Specification.

6. RESTRICTED RIGHTS LEGEND

6.1 Note to U.S. Government Users. The Specification is a "Commercial Items", as that term is defined at 48 C.F.R. 2. 101, consisting of "Commercial Computer Software" and "Commercial Computer Software Documentation", as such terms are used in 48 C.F.R. 12.212 or 48 C.F.R. 227.7202, as applicable. Consistent with 48 C.F.R. 12.212 or 48 C.F.R. 227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software Documentation are being licensed to U.S. Government end users a) only as Commercial Items and b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States.

This specification was produced by the JSR-238 Expert Group in the Java Community Process (JCP). For more information, visit the JSR-238 web page.

Contributors

The Expert Group consisted of representatives from the following companies (in alphabetical order):

Comments

Your comments about this specification are welcome. Please send them by electronic mail to the following address:

<jsr-238-comments@jcp.org>

Document conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" and "OPTIONAL" in this specification are to be interpreted as described in RFC 2119 (see "Related documentation").

Monospaced type is used to denote literal text such as /global and constants such as DEVICE and 0x7FFFFFFF.

Unicode characters are expressed in the U+NNNN notation, where NNNN denotes a 16-bit hexadecimal code point.


Mobile Internationalization API

Introduction

This specification defines Mobile Internationalization API, a J2ME Optional Package containing an application program interface that allows MIDP application developers to internationalize their MIDP applications. Internationalization is a prerequisite to localization, both very important in multilingual software development.

The API provides the locale-specific formatting of dates, times, numbers (including percentages) and currency amounts. It is also possible to construct messages that have a variable number of ordered parameters. Furthermore, the API defines a mechanism to retrieve application-specific and device-specific resources, and provides services for the locale-specific collation (sorting) of strings.

Mobile Internationalization API is designed as an Optional Package, intended to be used with the Mobile Information Device Profile (MIDP) running over the Connected, Limited Device Configuration (CLDC). The implementation should also work in the Connected Device Configuration (CDC) and MAY be implemented using it. For more information, see the System requirements section.

All classes in this API are in a single package, javax.microedition.global.

Goals

The goal of the Mobile Internationalization API is to provide internationalization services to Java MIDlets running in MIDP over CLDC. While Java 2, Standard Edition provides extensive support for internationalization, this support has not been included in the more limited configurations and profiles of Java 2, Micro Edition.

This API is designed to provide its services in a compact and generic form. It augments the MIDP application platform by bringing MIDP applications to a similar level with desktop applications in terms of internationalization.

System requirements

The underlying configuration MUST be CLDC 1.1 or later, due to the inclusion of floating point numeric formatting. The CLDC 1.1 implementation SHOULD support the "mark and reset" functionality for input streams. (See the documentation of CLDC's java.io.InputStream class for details.) This ensures that the binary resource files used by this API can be read more efficiently. CLDC 1.1 also implies support for the characters in Unicode 3.0 or later.

The version of MIDP used MUST be 2.0 later. That version of MIDP defines the format of the microedition.locale system property more accurately than version 1.0, and contains user interface components to facilitate the entry of common data items in a locale-specific manner. It also requires character encoding support for UTF-8.

If the underlying operating system provides services for Unicode collation and other related internationalization functionality, implementations of this API SHOULD take advantage of those services.

This API is implementable in CDC. Most features can be implemented in CDC by mapping the functionality to the CDC subset of the J2SE libraries.

Version information

Applications MUST be able to determine the version of Mobile Internationalization API present in the device, if any, by querying the value of the system property microedition.global.version. For version 1.0 of the API the value returned MUST be the string "1.0". If Mobile Internationalization API is not present, the value returned MUST be null.

Implementation notes

Some internationalization features, particularly Unicode collation, can be challenging to implement in a constrained device. However, many operating systems that have implementations of J2ME configurations already have some required basic functionality. It is therefore advisable that implementations of this API rely on this existing functionality as much as possible, and attempt to map this API into native functionality.

Implementers are also encouraged to evaluate the suitability of the data available from the Common Locale Data Repository (CLDR) Project (see "Related documentation") for their purposes when implementing locale-specific formatting and Unicode collation.


Locales

A locale is a combination of a language and a country or region. It is used in internationalization as a label for conventions that are typical for speakers of the language in the country or region.

In the Mobile Internationalization API locales are used to distinguish between different resources, data formatting conventions and string comparisons. Many classes in the API have methods taking a locale parameter that affects the behaviour of the class.

Locale identifiers

In the Mobile Internationalization API locale identifiers are simple strings. They MUST follow the format of locale identifiers found in Chapter 5 of the MIDP 2.0 specification, unless the identifier is the empty string. MIDP 2.0 locale identifiers consist of an ISO 639-1 two-letter language code, an ISO 3166-1 two-letter country code, and a variant code. If the value is non-null, only the language code is mandatory.

For application resource files handled by this API, the empty string as a locale identifier has a special meaning, as discussed in the "Resource files" section. When formatting data items or sorting strings using an empty locale triggers locale-neutral behaviour (see the respective class descriptions).

For robustness and compatibility with J2SE, methods taking locale identifiers as parameters MUST accept both underscore (U+005F) and dash (U+002D). However, application programmers SHOULD use only the dash.

Note that many classes in this API use the value of the microedition.locale system property as the default locale unless something else is specified. As the MIDP specification allows this value to have the null value, some classes revert to a locale-neutral behaviour in such situations.


Resources

Resources are application data that is typically localized. When the application is run, a different resource may be loaded for the same identifier, depending on the current locale setting of the runtime system and the organization of the application resources. Each resource has an identifier that is used when loading the resource at runtime.

Mobile Internationalization API has two different resource categories: application resources and device resources. The ResourceManager class is used to access both application resources and device resources. Application resources are supplied by the developer and shipped with the application, whereas device resources have already been made available by the device manufacturer.

The set of device resources varies by manufacturer and is not in the scope of this API. Instead device manufacturers should define the appropriate public resources and their identifiers for application developers to use. The storage format of device resources is implementation-specific.

Base names

The application programmer can group related application resources together by using a base name. In this context it is a non-empty string that is used in the names of application resource files to indicate that they belong together. The base name can reflect anything the application developer wants, such as menu commands or messages.

If the base name is empty, it refers to device resources. For these resources there is no application resource file, but instead the manufacturer-defined resources are consulted.

Application developers SHOULD restrict the characters used in the base names to the ASCII character set. The JAR file specification does not explicitly state the character encoding used in the file names, and many utilities have problems with non-ASCII characters.

Application resource files

Application resources MUST be stored inside the application's JAR file. They MUST be in the binary resource file format defined by this specification (see the section "The binary resource file format").

The organization of the application resource files inside the JAR file MUST be as follows. The JAR file MUST contain a special directory named '/global' to store the resource files. This directory MUST contain a subdirectory for each supported locale. The directory names MUST be valid MIDP 2.0 locale identifiers.

Resource files specific to some locale MUST be placed inside the corresponding locale subdirectory under /global, whereas common resources MUST be placed in the /global directory. The names of the resource files MUST be of the form 'baseName.res', where baseName is the base name used in the ResourceManager constructors. For example, the absolute pathname of a resource file inside the JAR might be '/global/en/Menus.res' or '/global/fi-FI/Menus.res' for resources specific to locales en and fi-FI. In the case of common resources the filename might be '/global/Common.res'.

The following diagram illustrates this arrangement:

JAR file root
    |
    |
    +----global----Common.res
          |
          |
          +----fi-FI----Menus.res
               |        Labels.res
               |
               en-------Menus.res
               |        Labels.res
               |
               de-DE----Menus.res
                        Labels.res

This example contains seven resource files inside the JAR file, with absolute filenames such as /global/Common.res, /global/fi-FI/Menus.res, and so on.

Often it is advantageous to collect together elements that do not change from one locale to another. For example, you can save storage by placing into a common resource file those resources that could change but will never be translated.

According to the MIDP 2.0 specification, if the microedition.locale system property is present at all (i.e. it is non-null), it always contains the language part. To implement the common locale this API extends the MIDP 2.0 definition so that an empty locale identifier points to common resource files placed in the '/global' directory. These files MUST conform to the same naming rules as the locale-specific resources.

The resource retrieval mechanism MUST also support resource inheritance; if a resource is not found using the specified locale identifier, it is searched again with the last component of the locale identifier removed, until a match is found or it is determined that the resource is not found even in the common locale. For an in-depth description of the inheritance mechanism see the ResourceManager class description.

Note that the directory and file names inside the JAR are case-sensitive.

Enumerating supported resource locales

The ResourceManager class has a static method getSupportedLocales to determine which locales are supported for a given base name. For device resources this information MUST be provided by the implementation. For application resources the application JAR file MUST contain a meta-information file for each base name, called 'global/_baseName'. The meta-information mechanism avoids repeated lookups of resource files from inside the JAR file.

Each meta-information file lists the supported locales for the corresponding base name. The file MUST contain the locale identifiers of the locales supported for that base name, separated by one blank space (U+0020). These files SHOULD be generated along with the binary resource files.

If the contents of the meta-information file for some base name do not agree with the actual resource files inside the JAR file, the effect MUST be as follows when attempting to instantiate a ResourceManager for that base name and the requested locale:

For example, if the JAR file contains application resource files for the base name Menus for the Finnish, Hungarian and Brazilian Portuguese locales, the file global/_Menus would contain the following:

fi-FI hu-HU pt-BR

Values in the meta-information file MAY be quoted using U+0022 QUOTATION MARK, for example "fi-FI". If there are common resources for the base name, the file MUST include the empty string. The empty string MUST be quoted and it SHOULD be the first value in the file.

In the previous example, if the base name Menus had also common resources, the meta-information file _Menus would contain

"" fi-FI hu-HU pt-BR

This is equivalent to

"" "fi-FI" "hu-HU" "pt-BR"

If the meta-information file for the specified base name is not found, the getSupportedLocales method MUST throw a ResourceException with the error code METAFILE_NOT_FOUND.

The binary resource file format

This section describes the structure of the binary resource file format of Mobile Internationalization API. To be accessible using this API, resource files shipped with applications MUST be in this format.

Each resource in the resource file MUST have an associated ID, with a value of between 0x00000000 and 0x7FFFFFFF (inclusive). The resource IDs MUST be unique inside one resource file. However, the same resource ID can occur in other resource files with the same base name but different locales. This allows resource inheritance as discussed in the ResourceManager class description.

All resources are stored as byte arrays. Being the most common resources, strings are a special case in the API. The string data MUST be encoded in UTF-8. Other resources are stored as raw data, and the meaning of the data is application-specific. For example, it could be PNG image data passed to the createImage method of the LCDUI Image class.

The resource file format consists of the following:

The first byte of the signature MUST be 0xEE (the number 238 expressed in hexadecimal), the second and third bytes MUST be 0x4D and 0x49 (the characters 'M' and 'I' in UTF-8 encoding), and the fourth byte MUST contain the file format and API version. The top four bits of the version represent the major version, while the bottom four bits are the minor version. The minor and major versions MUST follow the version of the API specification. For example, in resource files intended for this version of the API (1.0) the version byte is 0x10.

The header length is expressed in bytes. The length MUST NOT include the 4-byte signature.

The file header MUST contain a table of 64-bit entries, one for each resource. The entries combine the following components into one value: the resource ID, the resource type, and the byte offset of the resource from the start of the file. The top 32 bits of the entry MUST contain the resource ID. The bottom 32 bits of the entry MUST contain the combined type and offset, with top eight bits representing the type, and the remaining 24 bits representing the byte offset from the start of the file. The lengths of the resource blocks are calculated from the byte offsets. The last entry in the table is special, with an offset that points past the end of the file. It is only used to calculate the length of the last actual resource. The entries MUST be in ascending order by byte offset.

The following figure illustrates the structure of the entry.

   bits 63...32     bits 31...0
|----------------|---------------|
   resource ID    type   offset 
                 |----|----------|

Zero-length resources are allowed in the resource file as placeholders for future content. The implementation MUST NOT return null for resources that have an entry in the offset table. Instead, for string resources the implementation MUST return the empty string, and for binary data it MUST return an empty byte array.

If the ResourceManager implementation supports the caching of resources, it SHOULD read the table of offsets and types into memory when it is first constructed. Later it MAY also cache the resources it reads. To determine if ResourceManager supports caching, applications can call the isCaching() method of the class. This information could be used to determine if the application itself needs to cache resources or not.

The application specific resources MUST appear in the resource file in ascending order by resource ID. However, the resource ID sequence MAY contain gaps, so that the index table is essentially a sparse array. This allows the implementation to skip straight to the desired resource using only the index, without reading the file over again from the start.

The type of each resource MUST be encoded in the top eight bits of the lower 32-bit half of the index entry. Currently the following values are defined for the resource type:

The resource type is used by the getResource and getString methods of the ResourceManager class. Different types of resources MAY occur in arbitrary order inside the resource file, except for the type 0x00, which is not an actual resource. There MUST be only one entry with type 0x00 in the file, and it MUST be the last entry in the offset table. The resource ID associated with that entry MUST be 0x80000000.

The maximum size of the resource file is determined by the number of resources in the file, their individual sizes and the offset. A resource file always contains the signature, the header and at least one offset, which MAY be the only one. Hence the minimum size of the resource file is 4 + 4 + 8 = 16 bytes. The use of invalid resource files MUST result in a ResourceException being thrown with error code DATA_ERROR.

All data in the resource file with units larger than an octet MUST appear in the "Big Endian" format (network byte order).

A sample resource file

This informative section describes a sample binary resource file. The file contains five resources (three strings and two images). The hexadecimal dump of the bytes in the file has been augmented with offset labels from the start of the file, and comments have been inserted (starting with the hash mark #). These offset labels and comments do not appear in the actual file. Also, all the image data is not shown.

000000   EE 4D 49 10         # signature and version
000004   00 00 00 30         # length of header
# start of offset table
         # ID=0x00000040, type=0x01, offset 0x000038
000008   00 00 00 40  01 00 00 38   
         # ID=0x00000041, type=0x01, offset 0x00003A
000010   00 00 00 41  01 00 00 3A
         # ID=0x00008000, type=0x10, offset 0x000040   
000018   00 00 80 00  10 00 00 40
         # ID=0x00008001, type=0x01, offset 0x00011F   
000020   00 00 80 01  01 00 01 1F
         # ID=0x00008002, type=0x10, offset 0x000123   
000028   00 00 80 02  10 00 01 23
         # ID=0x80000000, type=0x00 (end of resources), end offset   
000030   80 00 00 00  00 00 02 20   
# start of resources
         # the string 'OK' (ID=0x0040)
000038   4F 4B                    
         # the string 'Cancel' (ID=0x0041)
00003A   43 61 6E 63 65 6C        
         # data for image 'stop.png' (ID=0x8000)
000040   89 50 4E 47 0D 0A 1A 0A... 
         # the string 'Back' (ID=0x8001)  
00011F   42 61 63 6B              
         # data for image 'ok.png' (ID=0x8002)
000123   89 50 4E 47 0D 0A 1A 0A...  
000220   # end of file

The sample resource file contains resources with IDs 0x00000040, 0x00000041, 0x00008000, 0x00008001, and 0x00008002. At runtime, when an instance of ResourceManager has been created to access the contents of this file, the call getString(0x00000040) will return the string "OK", and the call getData(0x00008000) will return the data of the image file stop.png as a byte array. (The first call is equivalent to getResource(0x00000040), and the second is equivalent to getResource(0x00008000).) See the ResourceManager class documentation for details about the API calls.

Note that application developers SHOULD define symbolic constants for the application resources.

Advantages of the binary format

This informative section details the advantages of the binary resource format used in this API over text-based formats, such as the one used by the PropertyResourceBundle class in Java 2, Standard Edition.


Related documentation

JSR-118 Expert Group, Mobile Information Device Profile, version 2.0. Java Community Process. Available at http://www.jcp.org/en/jsr/detail?id=118.

Connected, Limited Device Configuration Specification, Version 1.1. Java Community Process. Available at http://www.jcp.org/en/jsr/detail?id=139.

Francois Yergeau, UTF-8, a transformation format of ISO 10646, RFC 2279. Available at http://www.ietf.org/rfc/rfc2279.txt.

S. Bradner, Key Words for use in RFCs to Indicate Requirement Levels, RFC 2119. Available at http://www.ietf.org/rfc/rfc2119.txt.

The Unicode Consortium, The Unicode Standard, Version 3.0. Addison-Wesley, 2000. See http://www.unicode.org.

Common Locale Data Repository (CLDR). See http://www.unicode.org/cldr/.

JAR File Specification. See http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html.


Programming examples

This informative section contains programming examples for Mobile Internationalization API.

Using application resources

These are code fragments from a demonstration MIDlet that uses a ResourceManager to load images and strings from binary resource files in the application's JAR file.

import javax.microedition.global.*;

public final class MoonDemo extends MIDlet implements CommandListener {
    private ResourceManager res;

    public static final int PHASE_NEW_MOON = 0;
    .
    .
    .
    public static final int PHASE_WANING_CRESCENT = 7;

    // Images for the different moon phases. 
    // These are loaded when first needed.
    private Image[] phaseImages = new Image[8];
    
    private int currentPhase;  // indicates the current phase shown
    private ImageItem moonPhaseImageItem;  // shows the image in the form
    .
    .
    .
    public MoonDemo() {
        try {
            // Use system default locale. We have English texts in the 
            // common locale for backup.
            res = ResourceManager.getManager("MoonPhases");
        }
        catch (ResourceException re) {
            System.out.println(re.getMessage() 
                + " (" + re.getErrorCode() + ")");
        }
        
        nextCommand = new Command(
            res.getString(MoonPhases.COMMAND_NEXT), Command.SCREEN, 1);
        exitCommand = new Command(
            res.getString(MoonPhases.COMMAND_EXIT), Command.EXIT, 1);

        mainForm = new Form(res.getString(MoonPhases.TEXT_MOON_PHASES));
        mainForm.addCommand(nextCommand);
        mainForm.addCommand(exitCommand);
        mainForm.setCommandListener(this);
        
        moonPhaseImageItem = new ImageItem("", null, 
            ImageItem.LAYOUT_CENTER, "");
        mainForm.append(moonPhaseImageItem);

        updateMainForm();        
        display.setCurrent(mainForm);
    }
    .
    .
    .
    private void updateMainForm() {
        if (phaseImages[currentPhase] == null) {
            // Get the phase image. Use new moon as the base and add the
            // current phase (0 to 7) to get the correct resource ID.
            byte[] imageData = res.getData(
                MoonPhases.IMAGE_NEW_MOON + currentPhase);
            phaseImages[currentPhase] = Image.createImage(
                imageData, 0, imageData.length);
        }

        moonPhaseImageItem.setImage(phaseImages[currentPhase]);
        
        // Just load the text. If the resource manager is caching,
        // the string will come from the heap and not from the JAR. 
        // Use new moon as the ID base.
        String phaseText = res.getString(
            MoonPhases.TEXT_NEW_MOON + currentPhase);
        
        moonPhaseImageItem.setLabel(phaseText);
    }
}

/** Utility class that contains the resource ID constants. */
public final class MoonPhases {     // class name is the basename
    // private constructor to prevent instantiation
    private MoonPhases() { }

    public static final int TEXT_MOON_PHASES = 1;
    public static final int COMMAND_NEXT = 2;
    public static final int COMMAND_EXIT = 3;
    
    public static final int TEXT_NEW_MOON = 11; 
    public static final int TEXT_WAXING_CRESCENT = 12;
    public static final int TEXT_FIRST_QUARTER = 13;
    public static final int TEXT_WAXING_GIBBOUS = 14;
    public static final int TEXT_FULL_MOON = 15;
    public static final int TEXT_WANING_GIBBOUS = 16;
    public static final int TEXT_LAST_QUARTER = 17;
    public static final int TEXT_WANING_CRESCENT = 18;
    
    public static final int IMAGE_NEW_MOON = 111; 
    public static final int IMAGE_WAXING_CRESCENT = 112;
    public static final int IMAGE_FIRST_QUARTER = 113;
    public static final int IMAGE_WAXING_GIBBOUS = 114;
    public static final int IMAGE_FULL_MOON = 115;
    public static final int IMAGE_WANING_GIBBOUS = 116;
    public static final int IMAGE_LAST_QUARTER = 117;
    public static final int IMAGE_WANING_CRESCENT = 118;
}

The MIDlet uses the following directory structure in the JAR file:

JAR file root
    |
    |
    +----global----MoonPhases.res
          |
          |
          +----da-DK----MoonPhases.res
               |
               |
               fi-FI----MoonPhases.res
               |
               |
               en-------MoonPhases.res
               |
               |
               hu-HU----MoonPhases.res

Formatting data items

These are code fragments from a demonstration MIDlet that formats data items correctly for the locale using a Formatter. The labels and the formatting templates are loaded from a resource file.

Calendar now = Calendar.getInstance();

StringItem todaysDate = new StringItem(res.getString(RES_LABEL_DATE),
    fmt.formatDateTime(now, Formatter.DATE_LONG));
todaysDate.setLayout(Item.LAYOUT_NEWLINE_AFTER);
formattingForm.append(todaysDate);
            
StringItem currentTime = new StringItem(res.getString(RES_LABEL_TIME), 
    fmt.formatDateTime(now, Formatter.TIME_LONG));
currentTime.setLayout(Item.LAYOUT_NEWLINE_AFTER);
formattingForm.append(currentTime);

Runtime rt = Runtime.getRuntime();
long totalMemory = rt.totalMemory();
long freeMemory = rt.freeMemory();

// reuse template variable            
String template = res.getString(RES_MESSAGE_TOTAL_MEMORY);
String totalString = fmt.formatNumber(totalMemory);
String totalMegString = fmt.formatNumber(totalMemory / 1048576.0, 1);
String totalMemoryMessage = Formatter.formatMessage(template, 
    new String[] { totalString, totalMegString });
     // in template:   {0}           {1}

float freePercentage = freeMemory / (float) totalMemory;
String freePercentageString = fmt.formatPercentage(freePercentage, 1);
                
template = res.getString(RES_MESSAGE_FREE_MEMORY);
String freeString = fmt.formatNumber(freeMemory);
String freeMegString = fmt.formatNumber(freeMemory / 1048576.0, 1);
String freeMemoryMessage = Formatter.formatMessage(template, 
    new String[] { freeString, freeMegString, freePercentageString });
     // in template:   {0}           {1}               {2}
                
StringItem totalMemoryString = new StringItem(
    res.getString(RES_LABEL_TOTAL_MEMORY), totalMemoryMessage);
totalMemoryString.setLayout(Item.LAYOUT_NEWLINE_AFTER);
formattingForm.append(totalMemoryString);
            
StringItem freeMemoryString = new StringItem(
    res.getString(RES_LABEL_FREE_MEMORY), freeMemoryMessage);
freeMemoryString.setLayout(Item.LAYOUT_NEWLINE_AFTER);
formattingForm.append(freeMemoryString);

StringItem piString = new StringItem(res.getString(RES_LABEL_PI), 
    fmt.formatNumber(Math.PI, 5));
formattingForm.append(piString);

The English language string resources used in this code are:

RES_LABEL_DATE            "Today's date:"
RES_LABEL_TIME            "Current time:" 
RES_MESSAGE_TOTAL_MEMORY  "{0} bytes ({1} MB)"
RES_LABEL_TOTAL_MEMORY    "Total memory:" 
RES_LABEL_FREE_MEMORY     "Free memory:" 
RES_LABEL_PI              "Value of π (to 5 decimal places):"
RES_MESSAGE_FREE_MEMORY   "{0} bytes ({1} MB), {2} free"

Sorting strings

The following sample code shows how to sort an array of strings in a locale-specific way using an instance of StringComparator.

private StringComparator comp;
    
private void sortList() {
    // Fetch the data from the List widget
    String[] data = new String[collationList.size()];
        
    for (int i = 0; i < data.length; i++) {
        data[i] = collationList.getString(i);            
    }
    
    // Prepare a StringComparator for sorting.
    if (comp == null) {
        comp = new StringComparator();  // use default locale
    }
    
    // Bubble sort; slow but illustrative 
    String hold = null;  // temporary holding area for swap
    for (int pass = 1; pass < data.length; pass++) {  // all passes
        for (int itemIndex = 0; 
                itemIndex < data.length - pass; itemIndex++) {
            int result = comp.compare(
                data[itemIndex], data[itemIndex + 1]);
            if (result > 0) {
                // first item belongs after second, c.f. "a[i] > a[i+1]"
                hold = data[itemIndex];
                data[itemIndex] = data[itemIndex + 1];
                data[itemIndex + 1] = hold;
            }
        }
    }
    
    // Populate the list again with the sorted data
    populateCollationList(data);



Copyright © 2004-2005 Nokia Corporation. All Rights Reserved.
Java is a trademark of Sun Microsystems, Inc.