com.adobe.agl.util.UResourceBundle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
//##header J2SE15
/*
*******************************************************************************
* Copyright (C) 2004-2008, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
/*
* File: UResourceBundle.java
* ************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.adobe.agl.util;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import com.adobe.agl.impl.ICUResourceBundle;
import com.adobe.agl.impl.ICUResourceBundleReader;
import com.adobe.agl.impl.ResourceBundleWrapper;
/**
* A class representing a collection of resource information pertaining to a given
* locale. A resource bundle provides a way of accessing locale- specific information in
* a data file. You create a resource bundle that manages the resources for a given
* locale and then ask it for individual resources.
*
* In ResourceBundle class, an object is created
* and the sub items are fetched using getString, getObject methods.
* In UResourceBundle,each individual element of a resource is a resource by itself.
*
*
* Resource bundles in ICU are currently defined using text files which conform to the following
* BNF definition.
* More on resource bundle concepts and syntax can be found in the
* Users Guide.
*
*
* The packaging of ICU *.res files can be of two types
* ICU4C:
*
* root.res
* |
* --------
* | |
* fr.res en.res
* |
* --------
* | |
* fr_CA.res fr_FR.res
*
* JAVA/JDK:
*
* LocaleElements.res
* |
* -------------------
* | |
* LocaleElements_fr.res LocaleElements_en.res
* |
* ---------------------------
* | |
* LocaleElements_fr_CA.res LocaleElements_fr_FR.res
*
* Depending on the organization of your resources, the syntax to getBundleInstance will change.
* To open ICU style organization use:
*
* UResourceBundle bundle = UResourceBundle.getBundleInstance("com/mycompany/resources", "en_US", myClassLoader);
*
* To open Java/JDK style organization use:
*
* UResourceBundle bundle = UResourceBundle.getBundleInstance("com.mycompany.resources.LocaleElements", "en_US", myClassLoader);
*
*
* Please use pass a class loader for loading non-ICU resources. Java security does not
* allow loading of resources across jar files. You must provide your class loader
* to load the resources
*
* @stable ICU 3.0
* @author ram
*/
public abstract class UResourceBundle extends ResourceBundle{
/**
* Creates a resource bundle using the specified base name and locale.
* ICU_DATA_CLASS is used as the default root.
* @param baseName the base name of the resource bundle, a fully qualified class name
* @param localeName the locale for which a resource bundle is desired
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(String baseName, String localeName){
return getBundleInstance(baseName, localeName, ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
}
/**
* Creates a resource bundle using the specified base name, locale, and class root.
*
* @param baseName the base name of the resource bundle, a fully qualified class name
* @param localeName the locale for which a resource bundle is desired
* @param root the class object from which to load the resource bundle
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(String baseName, String localeName, ClassLoader root){
return getBundleInstance(baseName, localeName, root, false);
}
/**
* Creates a resource bundle using the specified base name, locale, and class root.
*
* @param baseName the base name of the resource bundle, a fully qualified class name
* @param localeName the locale for which a resource bundle is desired
* @param root the class object from which to load the resource bundle
* @param disableFallback Option to disable locale inheritence.
* If true the fallback chain will not be built.
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*
*/
protected static UResourceBundle getBundleInstance(String baseName, String localeName, ClassLoader root, boolean disableFallback) {
return instantiateBundle(baseName, localeName, root, disableFallback);
}
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.) This is public for compatibility with Java, whose compiler
* will generate public default constructors for an abstract class.
* @stable ICU 3.0
*/
public UResourceBundle() {
}
/**
* Creates a UResourceBundle for the locale specified, from which users can extract resources by using
* their corresponding keys.
* @param locale specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @return a resource bundle for the given locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(ULocale locale) {
if (locale==null) {
locale = ULocale.getDefault();
}
return getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
}
/**
* Creates a UResourceBundle for the default locale and specified base name,
* from which users can extract resources by using their corresponding keys.
* @param baseName specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @return a resource bundle for the given base name and default locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(String baseName) {
if (baseName == null) {
baseName = ICUResourceBundle.ICU_BASE_NAME;
}
ULocale uloc = ULocale.getDefault();
return getBundleInstance(baseName, uloc.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
}
/**
* Creates a UResourceBundle for the specified locale and specified base name,
* from which users can extract resources by using their corresponding keys.
* @param baseName specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @param locale specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(String baseName, Locale locale) {
if (baseName == null) {
baseName = ICUResourceBundle.ICU_BASE_NAME;
}
ULocale uloc = locale == null ? ULocale.getDefault() : ULocale.forLocale(locale);
return getBundleInstance(baseName, uloc.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
}
/**
* Creates a UResourceBundle, from which users can extract resources by using
* their corresponding keys.
* @param baseName string containing the name of the data package.
* If null the default ICU package name is used.
* @param locale specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
public static UResourceBundle getBundleInstance(String baseName, ULocale locale) {
if (baseName == null) {
baseName = ICUResourceBundle.ICU_BASE_NAME;
}
if (locale == null) {
locale = ULocale.getDefault();
}
return getBundleInstance(baseName, locale.toString(), ICUResourceBundle.ICU_DATA_CLASS_LOADER, false);
}
/**
* Creates a UResourceBundle for the specified locale and specified base name,
* from which users can extract resources by using their corresponding keys.
* @param baseName specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @param locale specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @param loader the loader to use
* @return a resource bundle for the given base name and locale
* @stable ICU 3.8
*/
public static UResourceBundle getBundleInstance(String baseName, Locale locale, ClassLoader loader) {
if (baseName == null) {
baseName = ICUResourceBundle.ICU_BASE_NAME;
}
ULocale uloc = locale == null ? ULocale.getDefault() : ULocale.forLocale(locale);
return getBundleInstance(baseName, uloc.toString(), loader, false);
}
/**
* Creates a UResourceBundle, from which users can extract resources by using
* their corresponding keys.
* Note: Please use this API for loading non-ICU resources. Java security does not
* allow loading of resources across jar files. You must provide your class loader
* to load the resources
* @param baseName string containing the name of the data package.
* If null the default ICU package name is used.
* @param locale specifies the locale for which we want to open the resource.
* If null the bundle for default locale is opened.
* @param loader the loader to use
* @return a resource bundle for the given base name and locale
* @stable ICU 3.8
*/
public static UResourceBundle getBundleInstance(String baseName, ULocale locale, ClassLoader loader) {
if (baseName == null) {
baseName = ICUResourceBundle.ICU_BASE_NAME;
}
if (locale == null) {
locale = ULocale.getDefault();
}
return getBundleInstance(baseName, locale.toString(), loader, false);
}
/**
* Returns the RFC 3066 conformant locale id of this resource bundle.
* This method can be used after a call to getBundleInstance() to
* determine whether the resource bundle returned really
* corresponds to the requested locale or is a fallback.
*
* @return the locale of this resource bundle
* @stable ICU 3.0
*/
public abstract ULocale getULocale();
/**
* Gets the localeID
* @return The string representation of the localeID
* @stable ICU 3.0
*/
protected abstract String getLocaleID();
/**
* Gets the base name of the resource bundle
* @return The string representation of the base name
* @stable ICU 3.0
*/
protected abstract String getBaseName();
/**
* Gets the parent bundle
* @return The parent bundle
* @stable ICU 3.0
*/
protected abstract UResourceBundle getParent();
/**
* Get the locale of this bundle
* @return the locale of this resource bundle
* @stable ICU 3.0
*/
public Locale getLocale(){
return getULocale().toLocale();
}
// Cache for ResourceBundle instantiation
private static SoftReference BUNDLE_CACHE;
private static void addToCache(ResourceCacheKey key, UResourceBundle b) {
Map m = null;
if (BUNDLE_CACHE != null) {
m = (Map)BUNDLE_CACHE.get();
}
if (m == null) {
m = new HashMap();
BUNDLE_CACHE = new SoftReference(m);
}
m.put(key, b);
}
/**
* Method used by subclasses to add the a particular resource bundle object to the managed cache
* @internal revisit for ICU 3.6
* @deprecated This API is ICU internal only.
*/
protected static void addToCache(ClassLoader cl, String fullName, ULocale defaultLocale, UResourceBundle b){
synchronized(cacheKey){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
addToCache((ResourceCacheKey)cacheKey.clone(), b);
}
}
/**
* Method used by sub classes to load a resource bundle object from the managed cache
* @internal revisit for ICU 3.6
* @deprecated This API is ICU internal only.
*/
protected static UResourceBundle loadFromCache(ClassLoader cl, String fullName, ULocale defaultLocale){
synchronized(cacheKey){
cacheKey.setKeyValues(cl, fullName, defaultLocale);
return loadFromCache(cacheKey);
}
}
private static UResourceBundle loadFromCache(ResourceCacheKey key) {
if (BUNDLE_CACHE != null) {
Map m = (Map)BUNDLE_CACHE.get();
if (m != null) {
return (UResourceBundle)m.get(key);
}
}
return null;
}
/**
* Key used for cached resource bundles. The key checks
* the resource name, the class root, and the default
* locale to determine if the resource is a match to the
* requested one. The root may be null, but the
* searchName and the default locale must have a non-null value.
* Note that the default locale may change over time, and
* lookup should always be based on the current default
* locale (if at all).
*/
private static final class ResourceCacheKey implements Cloneable {
private SoftReference loaderRef;
private String searchName;
private ULocale defaultLocale;
private int hashCodeCache;
///CLOVER:OFF
public boolean equals(Object other) {
if (this == other) {
return true;
}
try {
final ResourceCacheKey otherEntry = (ResourceCacheKey) other;
//quick check to see if they are not equal
if (hashCodeCache != otherEntry.hashCodeCache) {
return false;
}
//are the names the same?
if (!searchName.equals(otherEntry.searchName)) {
return false;
}
// are the default locales the same?
if (defaultLocale == null) {
if (otherEntry.defaultLocale != null) {
return false;
}
} else {
if (!defaultLocale.equals(otherEntry.defaultLocale)) {
return false;
}
}
//are refs (both non-null) or (both null)?
if (loaderRef == null) {
return otherEntry.loaderRef == null;
} else {
return (otherEntry.loaderRef != null)
&& (loaderRef.get() == otherEntry.loaderRef.get());
}
} catch (NullPointerException e) {
return false;
} catch (ClassCastException e) {
return false;
}
}
public int hashCode() {
return hashCodeCache;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
//this should never happen
throw new IllegalStateException();
}
}
///CLOVER:ON
private synchronized void setKeyValues(ClassLoader root, String searchName, ULocale defaultLocale) {
this.searchName = searchName;
hashCodeCache = searchName.hashCode();
this.defaultLocale = defaultLocale;
if (defaultLocale != null) {
hashCodeCache ^= defaultLocale.hashCode();
}
if (root == null) {
this.loaderRef = null;
} else {
loaderRef = new SoftReference(root);
hashCodeCache ^= root.hashCode();
}
}
/*private void clear() {
setKeyValues(null, "", null);
}*/
}
private static final ResourceCacheKey cacheKey = new ResourceCacheKey();
private static final int ROOT_MISSING = 0;
private static final int ROOT_ICU = 1;
private static final int ROOT_JAVA = 2;
private static SoftReference ROOT_CACHE;
private static int getRootType(String baseName, ClassLoader root)
{
Map m = null;
Integer rootType;
if (ROOT_CACHE != null) {
m = (Map) ROOT_CACHE.get();
}
if (m == null) {
m = new HashMap();
ROOT_CACHE = new SoftReference(m);
}
rootType = (Integer) m.get(baseName);
if (rootType == null) {
String rootLocale = (baseName.indexOf('.')==-1) ? "root" : "";
int rt = ROOT_MISSING; // value set on success
try{
ICUResourceBundle.getBundleInstance(baseName, rootLocale, root, true);
rt = ROOT_ICU;
}catch(MissingResourceException ex){
try{
ResourceBundleWrapper.getBundleInstance(baseName, rootLocale, root, true);
rt = ROOT_JAVA;
}catch(MissingResourceException e){
//throw away the exception
}
}
rootType = new Integer(rt);
m.put(baseName, rootType);
}
return rootType.intValue();
}
private static void setRootType(String baseName, int rootType)
{
Integer rt = new Integer(rootType);
Map m = null;
if (ROOT_CACHE != null) {
m = (Map) ROOT_CACHE.get();
} else {
m = new HashMap();
ROOT_CACHE = new SoftReference(m);
}
m.put(baseName, rt);
}
/**
* Loads a new resource bundle for the give base name, locale and class loader.
* Optionally will disable loading of fallback bundles.
* @param baseName the base name of the resource bundle, a fully qualified class name
* @param localeName the locale for which a resource bundle is desired
* @param root the class object from which to load the resource bundle
* @param disableFallback disables loading of fallback lookup chain
* @exception MissingResourceException
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
* @stable ICU 3.0
*/
protected static UResourceBundle instantiateBundle(String baseName, String localeName,
ClassLoader root, boolean disableFallback){
UResourceBundle b = null;
int rootType = getRootType(baseName, root);
ULocale defaultLocale = ULocale.getDefault();
switch (rootType)
{
case ROOT_ICU:
if(disableFallback) {
String fullName = ICUResourceBundleReader.getFullName(baseName, localeName);
synchronized(cacheKey){
cacheKey.setKeyValues(root, fullName, defaultLocale);
b = loadFromCache(cacheKey);
}
if (b == null) {
b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
//cacheKey.setKeyValues(root, fullName, defaultLocale);
addToCache(cacheKey, b);
}
} else {
b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
}
return b;
case ROOT_JAVA:
return ResourceBundleWrapper.getBundleInstance(baseName, localeName, root, disableFallback);
default:
try{
b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, disableFallback);
setRootType(baseName, ROOT_ICU);
}catch(MissingResourceException ex){
b = ResourceBundleWrapper.getBundleInstance(baseName, localeName, root, disableFallback);
setRootType(baseName, ROOT_JAVA);
}
return b;
}
}
/**
* Returns a binary data from a binary resource.
*
* @return a pointer to a chuck of unsigned bytes which live in a memory mapped/DLL file.
* @see #getIntVector
* @see #getInt
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public ByteBuffer getBinary() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a string from a string resource type
*
* @return a string
* @see #getBinary()
* @see #getIntVector
* @see #getInt
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public String getString() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a string array from a array resource type
*
* @return a string
* @see #getString()
* @see #getIntVector
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public String[] getStringArray() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a binary data from a binary resource.
*
* @param ba The byte array to write the bytes to. A null variable is OK.
* @return an array bytes containing the binary data from the resource.
* @see #getIntVector
* @see #getInt
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public byte[] getBinary(byte[] ba) {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a 32 bit integer array from a resource.
*
* @return a pointer to a chunk of unsigned bytes which live in a memory mapped/DLL file.
* @see #getBinary()
* @see #getInt
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public int[] getIntVector() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a signed integer from a resource.
*
* @return an integer value
* @see #getIntVector
* @see #getBinary()
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public int getInt() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a unsigned integer from a resource.
* This integer is originally 28 bit and the sign gets propagated.
*
* @return an integer value
* @see #getIntVector
* @see #getBinary()
* @throws MissingResourceException
* @throws UResourceTypeMismatchException
* @stable ICU 3.8
*/
public int getUInt() {
throw new UResourceTypeMismatchException("");
}
/**
* Returns a resource in a given resource that has a given key.
*
* @param aKey a key associated with the wanted resource
* @return a resource bundle object representing the resource
* @throws MissingResourceException
* @stable ICU 3.8
*/
public UResourceBundle get(String aKey) {
UResourceBundle obj = handleGet(aKey, null, this);
if (obj == null) {
UResourceBundle res = this;
while ((res = res.getParent()) != null && obj == null) {
//call the get method to recursively fetch the resource
obj = res.handleGet(aKey, null, this);
}
if (obj == null) {
String fullName = ICUResourceBundleReader.getFullName(
getBaseName(), getLocaleID());
throw new MissingResourceException(
"Can't find resource for bundle " + fullName + ", key "
+ aKey, this.getClass().getName(), aKey);
}
}
((ICUResourceBundle)obj).setLoadingStatus(getLocaleID());
return obj;
}
/**
* Returns the size of a resource. Size for scalar types is always 1,
* and for vector/table types is the number of child resources.
*
Warning: Integer array is treated as a scalar type. There are no
* APIs to access individual members of an integer array. It
* is always returned as a whole.
* @return number of resources in a given resource.
* @stable ICU 3.8
*/
public int getSize() {
return size;
}
/**
* Return the version number associated with this UResourceBundle as an
* VersionInfo object.
* @return VersionInfo object containing the version of the bundle
* @stable ICU 3.8
*/
public VersionInfo getVersion() {
return null;
}
/**
* Returns the key associated with a given resource. Not all the resources have a key - only
* those that are members of a table.
* @return a key associated to this resource, or null if it doesn't have a key
* @stable ICU 3.8
*/
public String getKey() {
return key;
}
/**
* Resource type constant for "no resource".
* @stable ICU 3.8
*/
public static final int NONE = -1;
/**
* Resource type constant for strings.
* @stable ICU 3.8
*/
public static final int STRING = 0;
/**
* Resource type constant for binary data.
* @stable ICU 3.8
*/
public static final int BINARY = 1;
/**
* Resource type constant for tables of key-value pairs.
* @stable ICU 3.8
*/
public static final int TABLE = 2;
/**
* Resource type constant for aliases;
* internally stores a string which identifies the actual resource
* storing the data (can be in a different resource bundle).
* Resolved internally before delivering the actual resource through the API.
* @internal ICU 3.8
* @deprecated This API is ICU internal only.
*/
protected static final int ALIAS = 3;
/**
* Internal use only.
* Alternative resource type constant for tables of key-value pairs.
* Never returned by getType().
* @internal ICU 3.8
* @deprecated This API is ICU internal only.
*/
protected static final int TABLE32 = 4;
/**
* Resource type constant for a single 28-bit integer, interpreted as
* signed or unsigned by the getInt() function.
* @see #getInt
* @stable ICU 3.8
*/
public static final int INT = 7;
/**
* Resource type constant for arrays of resources.
* @stable ICU 3.8
*/
public static final int ARRAY = 8;
/**
* Resource type constant for vectors of 32-bit integers.
* @see #getIntVector
* @stable ICU 3.8
*/
public static final int INT_VECTOR = 14;
//====== protected members ==============
/**
* Data member where the subclasses store the key
* @internal
* @deprecated This API is ICU internal only.
*/
protected String key;
/**
* Data member where the subclasses store the size of resources
* @internal
* @deprecated This API is ICU internal only.
*/
protected int size = 1;
/**
* Data member where the subclasses store the offset within resource data
* @internal
* @deprecated This API is ICU internal only.
*/
protected long resource = RES_BOGUS;
/**
* Data member where the subclasses store whether the resource is top level
* @internal
* @deprecated This API is ICU internal only.
*/
protected boolean isTopLevel = false;
private static final long RES_BOGUS = 0xffffffff;
/**
* Actual worker method for fetching a resource based on the given key.
* Sub classes must override this method if they support resources with keys.
* @param aKey the key string of the resource to be fetched
* @param table hashtable object to hold references of resources already seen
* @param requested the original resource bundle object on which the get method was invoked.
* The requested bundle and the bundle on which this method is invoked
* are the same, except in the cases where aliases are involved.
* @return UResourceBundle a resource associated with the key
* @stable ICU 3.8
*/
protected UResourceBundle handleGet(String aKey, HashMap table, UResourceBundle requested) {
return null;
}
/**
* Actual worker method for fetching a resource based on the given index.
* Sub classes must override this method if they support arrays of resources.
* @param index the index of the resource to be fetched
* @param table hashtable object to hold references of resources already seen
* @param requested the original resource bundle object on which the get method was invoked.
* The requested bundle and the bundle on which this method is invoked
* are the same, except in the cases where aliases are involved.
* @return UResourceBundle a resource associated with the index
* @stable ICU 3.8
*/
protected UResourceBundle handleGet(int index, HashMap table, UResourceBundle requested) {
return null;
}
/**
* Actual worker method for fetching the array of strings in a resource.
* Sub classes must override this method if they support arrays of strings.
* @return String[] An array of strings containing strings
* @stable ICU 3.8
*/
protected String[] handleGetStringArray() {
return null;
}
/**
* This method is for setting the loading status of the resource.
* The status is analogous to the warning status in ICU4C.
* @internal ICU 3.8
* @deprecated This API is ICU internal only.
*/
protected abstract void setLoadingStatus(int newStatus);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy