/* * Copyright ThinkTank Maths Limited 2006 - 2008 * * This file is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * This file is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this file. If not, see <http://www.gnu.org/licenses/>. */ package javax.microedition.location; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; /** * The <code>LandmarkStore</code> class provides methods to store, delete and retrieve * landmarks from a persistent landmark store. There is one default landmark store and * there may be multiple other named landmark stores. The implementation may support * creating and deleting landmark stores by the application. All landmark stores MUST be * shared between all J2ME applications and MAY be shared with native applications in the * terminal. Named landmark stores have unique names in this API. If the underlying * implementation allows multiple landmark stores with the same name, it must present them * with unique names in the API e.g. by adding some postfix to those names that have * multiple instances in order to differentiate them. * <p> * Because native landmark stores may be stored as files in a file system and file systems * have sometimes limitations for the allowed characters in file names, the * implementations MUST support all other Unicode characters in landmark store names * except the following list: * <ul> * <li>0x0000...0x001F control characters</li> * <li>0x005C <code>'\'</code></li> * <li>0x002F <code>'/'</code></li> * <li>0x003A <code>':'</code></li> * <li>0x002A <code>'*'</code></li> * <li>0x003F <code>'?'</code></li> * <li>0x0022 <code>'"'</code></li> * <li>0x003C <code>'<'</code></li> * <li>0x003E <code>'>'</code></li> * <li>0x007C <code>'|'</code></li> * <li>0x007F...0x009F control characters</li> * <li>0xFEFF Byte-order-mark</li> * <li>0xFFF0...0xFFFF</li> * </ul> * Support for the listed characters is not required and therefore applications are * strongly encouraged not to use the characters listed above in landmark store names in * order to ensure interoperability of the application on different platform * implementations. * <p> * The <code>Landmark</code>s have a name and may be placed in a category or several * categories. The category is intended to group landmarks that are of similar type to the * end user, e.g. restaurants, museums, etc. The landmark names are strings that identify * the landmark to the end user. The category names describe the category to the end user. * The language used in the names may be any and depends on the preferences of the end * user. The names of the categories are unique within a <code>LandmarkStore</code>. * However, the names of the landmarks are not guaranteed to be unique. * <code>Landmark</code>s with the same name can appear in multiple categories or even * several <code>Landmark</code>s with the same name in the same category. * <p> * The <code>Landmark</code> objects returned from the <code>getLandmarks</code> * methods in this class shall guarantee that the application can read a consistent set of * the landmark data valid at the time of obtaining the object instance, even if the * landmark information in the store is modified subsequently by this or some other * application. * <p> * The <code>Landmark</code> object instances can be in two states: <br> * <ul> * <li>initially constructed by an application </li> * <li>belongs to a <code>LandmarkStore</code> </li> * </ul> * A <code>Landmark</code> object belongs to a <code>LandmarkStore</code> if it has * been obtained from the <code>LandmarkStore</code> using <code>getLandmarks</code> * or if it has been added to the <code>LandmarkStore</code> using * <code>addLandmark</code>. A <code>Landmark</code> object is initially constructed * by an application when it has been constructed using the constructor but has not been * added to a <code>LandmarkStore</code> using <code>addLandmark</code>. * <p> * Note that the term "belongs to a <code>LandmarkStore</code>" is defined above in a * way that "belong to a <code>LandmarkStore</code>" has an different meaning than the * landmark "being currently stored in a <code>LandmarkStore</code>". According to the * above definition, a <code>Landmark</code> object instance may be in a state where it * is considered to "belong to a <code>LandmarkStore</code>" even when it is not stored * in that <code>LandmarkStore</code> (e.g. if the landmark is deleted from the * <code>LandmarkStore</code> using <code>deleteLandmark</code> method, the * <code>Landmark</code> object instance still is considered to "belong to this * <code>LandmarkStore</code>"). * <p> * The landmark stores created by an application and landmarks added in landmark stores * persist even if the application itself is deleted from the terminal. * <p> * Accessing the landmark store may cause a <code>SecurityException</code>, if the * calling application does not have the required permissions. The permissions to read and * write (including add and delete) landmarks are distinct. An application having e.g. a * permission to read landmarks wouldn't necessarily have the permission to delete them. * The permissions (names etc.) for the MIDP 2.0 security framework are defined elsewhere * in this specification. */ public class LandmarkStore { /** * Creates a new landmark store with a specified name. All LandmarkStores are shared * between all J2ME applications and may be shared with native applications. * Implementations may support creating landmark stores on a removable media. However, * the Java application is not able to directly choose where the landmark store is * stored, if the implementation supports several storage media. The implementation of * this method may e.g. prompt the end user to make the choice if the implementation * supports several storage media. If the landmark store is stored on a removable * media, this media might be removed by the user possibly at any time causing it to * become unavailable. * <p> * A newly created landmark store does not contain any landmarks. * <p> * Note that the landmark store name MAY be modified by the implementation when the * store is created, e.g. by adding an implementation specific post-fix to * differentiate stores on different storage drives as described in the class * overview. Therefore, the application needs to use the listLandmarkStores method to * discover the form the name was stored as. However, when creating stores to the * default storage location, it is recommended that the implementation does not modify * the store name but preserves it in the form it was passed to this method. It is * strongly recommended that this method is implemented as character case preserving * for the store name. * * @param storeName * the name of the landmark store to create * @throws NullPointerException * if the parameter is null * @throws IllegalArgumentException * if the name is too long or if a landmark store with the specified name * already exists * @throws IOException * if the landmark store couldn't be created due to an I/O error * @throws SecurityException * if the application does not have permissions to create a new landmark * store * @throws LandmarkException * if the implementation does not support creating new landmark stores */ public static void createLandmarkStore(String storeName) throws NullPointerException, IllegalArgumentException, IOException, LandmarkException, SecurityException { try { com.openlapi.LandmarkStore.createLandmarkStore(storeName); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Delete a landmark store with a specified name. All the landmarks and categories * defined in the named landmark store are irrevocably removed. If a landmark store * with the specified name does not exist, this method returns silently without any * error. * <p> * Note that the landmark store names MAY be handled as either case-sensitive or * case-insensitive (e.g. Unicode collation algorithm level 2). Therefore, the * implementation MUST accept the names in the form returned by listLandmarkStores and * MAY accept the name in other variations of character case. * * @param storeName * the name of the landmark store to delete * @throws NullPointerException * if the parameter is null (the default landmark store can't be deleted) * @throws IOException * if the landmark store couldn't be deleted due to an I/O error * @throws SecurityException * if the appliction does not have permissions to delete a landmark store * @throws LandmarkException * if the implementation does not support deleting landmark stores */ public static void deleteLandmarkStore(String storeName) throws NullPointerException, IOException, SecurityException, LandmarkException { try { com.openlapi.LandmarkStore.deleteLandmarkStore(storeName); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Gets a LandmarkStore instance for storing, deleting and retrieving landmarks. There * must be one default landmark store and there may be other landmark stores that can * be accessed by name. Note that the landmark store names MAY be handled as either * case-sensitive or case-insensitive (e.g. Unicode collation algorithm level 2). * Therefore, the implementation MUST accept the names in the form returned by * listLandmarkStores and MAY accept the name in other variations of character case. * * @param storeName * the name of the landmark store to open. if null, the default landmark * store will be returned * @return the LandmarkStore object representing the specified landmark store or null * if a landmark store with the specified name does not exist. * @throws SecurityException * if the application does not have a permission to read landmark stores */ public static LandmarkStore getInstance(String storeName) throws SecurityException { return new LandmarkStore(com.openlapi.LandmarkStore .getInstance(storeName)); } /** * Lists the names of all the available landmark stores. The default landmark store is * obtained from getInstance by passing null as the parameter. The null name for the * default landmark store is not included in the list returned by this method. If * there are no named landmark stores, other than the default landmark store, this * method returns null. * <p> * The store names must be returned in a form that is directly usable as input to * getInstance and deleteLandmarkStore. * * @return an array of landmark store names * @throws SecurityException * if the application does not have the permission to access landmark * stores * @throws IOException * if an I/O error occurred when trying to access the landmark stores */ public static String[] listLandmarkStores() throws SecurityException, IOException { return com.openlapi.LandmarkStore.listLandmarkStores(); } final com.openlapi.LandmarkStore wrapped; /** * Private constructor so that stores may only be created using the static methods of * this class. * * @throws IOException * @throws SecurityException */ private LandmarkStore(com.openlapi.LandmarkStore wrapped) { this.wrapped = wrapped; } /** * Adds a category to this LandmarkStore. All implementations must support names that * have length up to and including 32 characters. If the provided name is longer it * may be truncated by the implementation if necessary. * * @param categoryName * name for the category to be added * @throws IllegalArgumentException * if a category with the specified name already exists * @throws NullPointerException * if the parameter is null * @throws LandmarkException * if this LandmarkStore does not support adding new categories * @throws IOException * if an I/O error occurs or there are no resources to add a new category * @throws SecurityException * if the application does not have the permission to manage categories */ public void addCategory(String categoryName) throws IllegalArgumentException, NullPointerException, LandmarkException, IOException, SecurityException { try { wrapped.addCategory(categoryName); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Adds a landmark to the specified group in the landmark store. If some textual * String field inside the landmark object is set to a value that is too long to be * stored, the implementation is allowed to automatically truncate fields that are too * long. * <p> * However, the name field MUST NOT be truncated. Every implementation shall be able * to support name fields that are 32 characters or shorter. Implementations may * support longer names but are not required to. If an application tries to add a * Landmark with a longer name field than the implementation can support, * IllegalArgumentException is thrown. * <p> * When the landmark store is empty, every implementation is required to be able to * store a landmark where each String field is set to a 30 character long string. * <p> * If the Landmark object that is passed as a parameter is an instance that belongs to * this LandmarkStore, the same landmark instance will be added to the specified * category in addition to the category/categories which it already belongs to. If the * landmark already belongs to the specified category, this method returns with no * effect. If the landmark has been deleted after obtaining it from getLandmarks, it * will be added back when this method is called. * <p> * If the Landmark object that is passed as a parameter is an instance initially * constructed by the application using the constructor or an instance that belongs to * a different LandmarkStore, a new landmark will be created in this LandmarkStore and * it will belong initially to only the category specified in the category parameter. * After this method call, the Landmark object that is passed as a parameter belongs * to this LandmarkStore. * * @param landmark * the landmark to be added * @param category * where the landmark is added. null can be used to indicate that the * landmark does not belong to a category * @throws SecurityException * if the application is not allowed to add landmarks * @throws IllegalArgumentException * if the landmark has a longer name field than the implementation can * support or if the category is not null or one of the categories defined * in this LandmarkStore * @throws IOException * if an I/O error happened when accessing the landmark store or if there * are no resources available to store this landmark * @throws NullPointerException * if the landmark parameter is null */ public void addLandmark(Landmark landmark, String category) throws SecurityException, IllegalArgumentException, IOException, NullPointerException { wrapped.addLandmark(landmark.wrapped, category); } /** * Removes a category from this LandmarkStore. The category will be removed from all * landmarks that are in that category. However, this method will not remove any of * the landmarks, only the associated category information from the landmarks. If a * category with the supplied name does not exist in this LandmarkStore, the method * returns silently with no error. * * @param categoryName * name for the category to be removed * @throws NullPointerException * if the parameter is null * @throws LandmarkException * if this LandmarkStore does not support deleting categories * @throws IOException * if an I/O error occurs * @throws SecurityException * if the application does not have the permission to manage categories */ public void deleteCategory(String categoryName) throws NullPointerException, LandmarkException, IOException, SecurityException { try { wrapped.deleteCategory(categoryName); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Deletes a landmark from this LandmarkStore. This method removes the specified * landmark from all categories and deletes the information from this LandmarkStore. * The Landmark instance passed in as the parameter must be an instance that belongs * to this LandmarkStore. * <p> * If the Landmark belongs to this LandmarkStore but has already been deleted from * this LandmarkStore, then the request is silently ignored and the method call * returns with no error. Note that LandmarkException is thrown if the Landmark * instance does not belong to this LandmarkStore, and this is different from not * being stored currently in this LandmarkStore. * * @param lm * the landmark to be deleted * @throws SecurityException * if the application is not allowed to delete the landmark * @throws LandmarkException * if the landmark instance passed as the parameter does not belong to * this LandmarkStore * @throws IOException * if an I/O error happened when accessing the landmark store * @throws NullPointerException * if the parameter is null */ public void deleteLandmark(Landmark lm) throws SecurityException, LandmarkException, IOException, NullPointerException { try { wrapped.deleteLandmark(lm.wrapped); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Returns the category names that are defined in this LandmarkStore. The language and * locale used for these names depends on the implementation and end user settings. * The names shall be such that they can be displayed to the end user and have a * meaning to the end user. * * @return an Enumeration containing Strings representing the category names. If there * are no categories defined in this LandmarkStore, an Enumeration with no * entries is returned. */ public Enumeration getCategories() { return wrapped.getCategories(); } /** * Lists all landmarks stored in the store. * * @return an Enumeration object containing Landmark objects representing all the * landmarks stored in this LandmarkStore or null if there are no landmarks in * the store * @throws IOException * if an I/O error happened when accessing the landmark store */ public Enumeration getLandmarks() throws IOException { Enumeration lms = wrapped.getLandmarks(); return wrapOpenLAPIEnumeration(lms); } /** * Lists all the landmarks that are within an area defined by bounding minimum and * maximum latitude and longitude and belong to the defined category, if specified. * The bounds are considered to belong to the area. If minLongitude <= maxLongitude, * this area covers the longitude range [minLongitude, maxLongitude]. If minLongitude > * maxLongitude, this area covers the longitude range [-180.0, maxLongitude] and * [minLongitude, 180.0). * <p> * For latitude, the area covers the latitude range [minLatitude, maxLatitude]. * * @param category * the category of the landmark. null implies a wildcard that matches all * categories * @param minLatitude * minimum latitude of the area. Must be within the range [-90.0, 90.0] * @param maxLatitude * maximum latitude of the area. Must be within the range [minLatitude, * 90.0] * @param minLongitude * minimum longitude of the area. Must be within the range [-180.0, 180.0) * @param maxLongitude * maximum longitude of the area. Must be within the range [-180.0, 180.0) * @return an Enumeration containing all the matching Landmarks or null if no Landmark * matched the given parameters * @throws IOException * if an I/O error happened when accessing the landmark store * @throws IllegalArgumentException * if the minLongitude or maxLongitude is out of the range [-180.0, * 180.0), or minLatitude or maxLatitude is out of the range [-90.0,90.0], * or if minLatitude > maxLatitude */ public Enumeration getLandmarks(String category, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) throws IOException, IllegalArgumentException { Enumeration lms = wrapped.getLandmarks(category, minLatitude, maxLatitude, minLongitude, maxLongitude); return wrapOpenLAPIEnumeration(lms); } /** * Gets the Landmarks from the storage where the category and/or name matches the * given parameters. * * @param category * the category of the landmark. null implies a wildcard that matches all * categories * @param name * the name of the desired landmark. null implies a wildcard that matches * all the names within the category indicated by the category parameter * @return an Enumeration containing all the matching Landmarks or null if no Landmark * matched the given parameters * @throws IOException * if an I/O error happened when accessing the landmark store */ public Enumeration getLandmarks(String category, String name) throws IOException { Enumeration lms = wrapped.getLandmarks(category, name); return wrapOpenLAPIEnumeration(lms); } /** * Removes the named landmark from the specified category. The Landmark instance * passed in as the parameter must be an instance that belongs to this LandmarkStore. * <p> * If the Landmark is not found in this LandmarkStore in the specified category or if * the parameter is a Landmark instance that does not belong to this LandmarkStore, * then the request is silently ignored and the method call returns with no error. The * request is also silently ignored if the specified category does not exist in this * LandmarkStore. * <p> * The landmark is only removed from the specified category but the landmark * information is retained in the store. If the landmark no longer belongs to any * category, it can still be obtained from the store by passing null as the category * to getLandmarks. * * @param lm * the landmark to be removed * @param category * the category from which it will be removed. * @throws SecurityException * if the application is not allowed to delete the landmark * @throws IOException * if an I/O error happened when accessing the landmark store * @throws NullPointerException * if either parameter is null */ public void removeLandmarkFromCategory(Landmark lm, String category) throws SecurityException, IOException, NullPointerException { wrapped.removeLandmarkFromCategory(lm.wrapped, category); } /** * Updates the information about a landmark. This method only updates the information * about a landmark and does not modify the categories the landmark belongs to. The * Landmark instance passed in as the parameter must be an instance that belongs to * this LandmarkStore. * <p> * This method can't be used to add a new landmark to the store. * * @param lm * the landmark to be updated * @throws SecurityException * if the application is not allowed to update the landmark * @throws LandmarkException * if the landmark instance passed as the parameter does not belong to * this LandmarkStore or does not exist in the store any more * @throws IOException * if an I/O error happened when accessing the landmark store * @throws NullPointerException * if the parameter is null * @throws IllegalArgumentException * if the landmark has a longer name field than the implementation can * support */ public void updateLandmark(Landmark lm) throws SecurityException, LandmarkException, IOException, NullPointerException, IllegalArgumentException { try { wrapped.updateLandmark(lm.wrapped); } catch (com.openlapi.LandmarkException e) { throw new LandmarkException(e); } } /** * Converts an Enumeration of com.openlapi.Landmark objects into an Enumeration of * javax.microedition.location.Landmark objects. * * @param landmarks * @return */ Enumeration wrapOpenLAPIEnumeration(Enumeration landmarks) { if (landmarks == null) return null; Vector lms = new Vector(); while (landmarks.hasMoreElements()) { com.openlapi.Landmark landmark = (com.openlapi.Landmark) landmarks .nextElement(); lms.addElement(new Landmark(landmark)); } return lms.elements(); } }