text:
package hydra;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.CacheListener;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheWriter;
import com.gemstone.gemfire.cache.CustomExpiry;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.MembershipAttributes;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.cache.util.ObjectSizer;

/**
 * Encodes information needed to describe and create a region.
 */
public class RegionDescription extends AbstractDescription
implements Serializable {

  private static final long serialVersionUID = 1L;
  private static final String PARTITION = "PARTITION";

  /** Map of logical region configuration names to maps of cache listeners. */
  private static Map cacheListenerInstanceMaps = new HashMap();

  /** Map of logical region configuration names to cache loaders. */
  private static Map cacheLoaderInstances = new HashMap();

  /** Map of logical region configuration names to cache writers. */
  private static Map cacheWriterInstances = new HashMap();

  /** The logical name of this region description */
  private String name;

  /** Remaining parameters, in alphabetical order */
  private List<AsyncEventQueueDescription> asyncEventQueueDescriptions; // from asyncEventQueueNames
  private List<String> asyncEventQueueNames;
  private List cacheListeners;
  private Boolean cacheListenersSingleton;
  private String cacheLoader;
  private Boolean cacheLoaderSingleton;
  private String cacheWriter;
  private Boolean cacheWriterSingleton;
  private Boolean cloningEnabled;
  private Boolean concurrencyChecksEnabled;
  private Integer concurrencyLevel;
  private String customEntryIdleTimeout;
  private String customEntryTimeToLive;
  private DataPolicy dataPolicy;
  private DiskStoreDescription diskStoreDescription; // from diskStoreName
  private String diskStoreName;
  private Boolean diskSynchronous;
  private Boolean enableAsyncConflation;
  private Boolean enableGateway;
  private Boolean enableOffHeapMemory;
  private Boolean enableSubscriptionConflation;
  private ExpirationAttributes entryIdleTimeout;
  private ExpirationAttributes entryTimeToLive;
  private EvictionAttributes evictionAttributes;
  private List<GatewaySenderDescription> gatewaySenderDescriptions; // from gatewaySenderNames
  private List<String> gatewaySenderNames;
  private HDFSStoreDescription hdfsStoreDescription; // from hdfsStoreName
  private String hdfsStoreName;
  private Boolean hdfsWriteOnly;
  private Boolean ignoreJTA;
  private Boolean indexMaintenanceSynchronous;
  private Integer initialCapacity;
  private SubscriptionAttributes interestPolicy;
  private Class keyConstraint;
  private Float loadFactor;
  private Boolean lockGrantor;
  private MembershipAttributes membershipAttributes;
  private Boolean multicastEnabled; // can inherit from distributed system
  private PartitionDescription partitionDescription; // from partitionName
  private String partitionDescriptionName;
  private PoolDescription poolDescription; // from poolName
  private String poolDescriptionName;
  private ExpirationAttributes regionIdleTimeout;
  private String regionName;
  private ExpirationAttributes regionTimeToLive;
  private Scope scope;
  private Boolean statisticsEnabled;
  private Class valueConstraint;

//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------

  public RegionDescription() {
  }

//------------------------------------------------------------------------------
// Accessors, in aphabetical order after name
//------------------------------------------------------------------------------

  /**
   * Returns the logical name of this region description.
   */
  public String getName() {
    return this.name;
  }

  /**
   * Sets the logical name of this region description.
   */
  private void setName(String str) {
    this.name = str;
  }

  /**
   * Returns the async event queue descriptions.
   */
  public List<AsyncEventQueueDescription> getAsyncEventQueueDescriptions() {
    return this.asyncEventQueueDescriptions;
  }

  /**
   * Sets the async event queue descriptions.
   */
  private void setAsyncEventQueueDescriptions(List<AsyncEventQueueDescription> aeqds) {
    this.asyncEventQueueDescriptions = aeqds;
  }

  /**
   * Returns the async event queue names.
   */
  public List<String> getAsyncEventQueueNames() {
    return this.asyncEventQueueNames;
  }

  /**
   * Sets the async event queue names.
   */
  private void setAsyncEventQueueNames(List<String> strs) {
    this.asyncEventQueueNames = strs;
  }

  /**
   * Returns the classnames of the cache listeners.
   */
  private List getCacheListeners() {
    return this.cacheListeners;
  }

  /**
   * Sets the classnames of the cache listeners.
   */
  private void setCacheListeners(List classnames) {
    this.cacheListeners = classnames;
  }

  /**
   * Returns the cache listeners singleton.
   */
  private Boolean getCacheListenersSingleton() {
    return this.cacheListenersSingleton;
  }

  /**
   * Sets the cache listeners singleton.
   */
  private void setCacheListenersSingleton(Boolean bool) {
    this.cacheListenersSingleton = bool;
  }

  /**
   * Returns the cache loader classname.
   */
  private String getCacheLoader() {
    return this.cacheLoader;
  }

  /**
   * Sets the cache loader classname.
   */
  private void setCacheLoader(String s) {
    this.cacheLoader = s;
  }

  /**
   * Returns the cache loader singleton.
   */
  private Boolean getCacheLoaderSingleton() {
    return this.cacheLoaderSingleton;
  }

  /**
   * Sets the cache loader singleton.
   */
  private void setCacheLoaderSingleton(Boolean bool) {
    this.cacheLoaderSingleton = bool;
  }

  /**
   * Returns the cache writer classname.
   */
  private String getCacheWriter() {
    return this.cacheWriter;
  }

  /**
   * Sets the cache writer classname.
   */
  private void setCacheWriter(String  s) {
    this.cacheWriter = s;
  }

  /**
   * Returns the cache writer singleton.
   */
  private Boolean getCacheWriterSingleton() {
    return this.cacheWriterSingleton;
  }

  /**
   * Sets the cache writer singleton.
   */
  private void setCacheWriterSingleton(Boolean bool) {
    this.cacheWriterSingleton = bool;
  }

  /**
   * Returns the cloning enabled.
   */
  private Boolean getCloningEnabled() {
    return this.cloningEnabled;
  }

  /**
   * Sets the cloning enabled.
   */
  private void setCloningEnabled(Boolean bool) {
    this.cloningEnabled = bool;
  }

  /**
   * Returns concurrencyChecksEnabled
   */
  private Boolean getConcurrencyChecksEnabled() {
    return this.concurrencyChecksEnabled;
  }

  /**
   * Sets concurrencyChecksEnabled
   */
  private void setConcurrencyChecksEnabled(Boolean bool) {
    this.concurrencyChecksEnabled = bool;
  }

  /**
   * Returns the concurrency level.
   */
  private Integer getConcurrencyLevel() {
    return this.concurrencyLevel;
  }

  /**
   * Sets the concurrency level.
   */
  private void setConcurrencyLevel(Integer i) {
    this.concurrencyLevel = i;
  }

  /**
   * Returns the classname for the custom entry idle timeout.
   */
  private String getCustomEntryIdleTimeout() {
    return this.customEntryIdleTimeout;
  }

  /**
   * Sets the classname for the custom entry idle timeout.
   */
  private void setCustomEntryIdleTimeout(String str) {
    this.customEntryIdleTimeout = str;
  }

  /**
   * Returns the classname for the custom entry time to live.
   */
  private String getCustomEntryTimeToLive() {
    return this.customEntryTimeToLive;
  }

  /**
   * Sets the classname for the custom entry time to live.
   */
  private void setCustomEntryTimeToLive(String str) {
    this.customEntryTimeToLive = str;
  }

  /**
   * Returns the data policy.
   */
  public DataPolicy getDataPolicy() {
    return this.dataPolicy;
  }

  /**
   * Sets the data policy.
   */
  private void setDataPolicy(DataPolicy aDataPolicy) {
    this.dataPolicy = aDataPolicy;
  }

  /**
   * Returns the disk store description name.
   */
  public String getDiskStoreName() {
    return this.diskStoreName;
  }

  /**
   * Sets the disk store description name.
   */
  private void setDiskStoreName(String str) {
    this.diskStoreName = str;
  }

  /**
   * Returns the disk store description.
   */
  public DiskStoreDescription getDiskStoreDescription() {
    return this.diskStoreDescription;
  }

  /**
   * Sets the disk store description.
   */
  private void setDiskStoreDescription(DiskStoreDescription dsd) {
    this.diskStoreDescription = dsd;
  }

  /**
   * Returns the disk synchronous.
   */
  private Boolean getDiskSynchronous() {
    return this.diskSynchronous;
  }

  /**
   * Sets the disk synchronous.
   */
  private void setDiskSynchronous(Boolean bool) {
    this.diskSynchronous = bool;
  }

  /**
   * Returns the enable async conflation.
   */
  private Boolean getEnableAsyncConflation() {
    return this.enableAsyncConflation;
  }

  /**
   * Sets the enable async conflation.
   */
  private void setEnableAsyncConflation(Boolean bool) {
    this.enableAsyncConflation = bool;
  }

  /**
   * Returns the enable gateway.
   */
  private Boolean getEnableGateway() {
    return this.enableGateway;
  }

  /**
   * Sets the enable gateway.
   */
  private void setEnableGateway(Boolean bool) {
    this.enableGateway = bool;
  }

  /**
   * Returns enable off-heap memory.
   */
  private Boolean getEnableOffHeapMemory() {
    return this.enableOffHeapMemory;
  }

  /**
   * Sets enable off-heap memory.
   */
  private void setEnableOffHeapMemory(Boolean bool) {
    this.enableOffHeapMemory = bool;
  }

  /**
   * Returns the enable subscription conflation.
   */
  private Boolean getEnableSubscriptionConflation() {
    return this.enableSubscriptionConflation;
  }

  /**
   * Sets the enable subscription conflation.
   */
  private void setEnableSubscriptionConflation(Boolean bool) {
    this.enableSubscriptionConflation = bool;
  }

  /**
   * Returns the expiration attributes for the entry idle timeout.
   */
  private ExpirationAttributes getEntryIdleTimeout() {
    return this.entryIdleTimeout;
  }

  /**
   * Sets the expiration attributes for the entry idle timeout.
   */
  private void setEntryIdleTimeout(ExpirationAttributes attributes) {
    this.entryIdleTimeout = attributes;
  }

  /**
   * Returns the expiration attributes for the entry time to live.
   */
  private ExpirationAttributes getEntryTimeToLive() {
    return this.entryTimeToLive;
  }

  /**
   * Sets the expiration attributes for the entry time to live.
   */
  private void setEntryTimeToLive(ExpirationAttributes attributes) {
    this.entryTimeToLive = attributes;
  }

  /**
   * Returns the eviction attributes.
   */
  public EvictionAttributes getEvictionAttributes() {
    return this.evictionAttributes;
  }

  /**
   * Sets the eviction attributes.
   */
  private void setEvictionAttributes(EvictionAttributes attributes) {
    this.evictionAttributes = attributes;
  }

  /**
   * Returns the gateway sender descriptions.
   */
  public List<GatewaySenderDescription> getGatewaySenderDescriptions() {
    return this.gatewaySenderDescriptions;
  }

  /**
   * Sets the gateway sender descriptions.
   */
  private void setGatewaySenderDescriptions(List<GatewaySenderDescription> gsds) {
    this.gatewaySenderDescriptions = gsds;
  }

  /**
   * Returns the gateway sender names.
   */
  public List<String> getGatewaySenderNames() {
    return this.gatewaySenderNames;
  }

  /**
   * Sets the gateway sender names.
   */
  private void setGatewaySenderNames(List<String> strs) {
    this.gatewaySenderNames = strs;
  }

  /**
   * Returns the HDFS store description name.
   */
  public String getHDFSStoreName() {
    return this.hdfsStoreName;
  }

  /**
   * Sets the HDFS store description name.
   */
  private void setHDFSStoreName(String str) {
    this.hdfsStoreName = str;
  }

  /**
   * Returns the HDFS store description.
   */
  public HDFSStoreDescription getHDFSStoreDescription() {
    return this.hdfsStoreDescription;
  }

  /**
   * Sets the HDFS store description.
   */
  private void setHDFSStoreDescription(HDFSStoreDescription hsd) {
    this.hdfsStoreDescription = hsd;
  }

  /**
   * Returns the HDFS write-only.
   */
  private Boolean getHDFSWriteOnly() {
    return this.hdfsWriteOnly;
  }

  /**
   * Sets the HDFS write-only.
   */
  private void setHDFSWriteOnly(Boolean bool) {
    this.hdfsWriteOnly = bool;
  }

  /**
   * Returns the ignore JTA.
   */
  private Boolean getIgnoreJTA() {
    return this.ignoreJTA;
  }

  /**
   * Sets the ignore JTA.
   */
  private void setIgnoreJTA(Boolean bool) {
    this.ignoreJTA = bool;
  }

  /**
   * Returns the index maintenance synchronous.
   */
  private Boolean getIndexMaintenanceSynchronous() {
    return this.indexMaintenanceSynchronous;
  }

  /**
   * Sets the index maintenance synchronous.
   */
  private void setIndexMaintenanceSynchronous(Boolean bool) {
    this.indexMaintenanceSynchronous = bool;
  }

  /**
   * Returns the initial capacity.
   */
  private Integer getInitialCapacity() {
    return this.initialCapacity;
  }

  /**
   * Sets the initial capacity.
   */
  private void setInitialCapacity(Integer i) {
    this.initialCapacity = i;
  }

  /**
   * Returns the interest policy (really subscription attributes).
   */
  private SubscriptionAttributes getInterestPolicy() {
    return this.interestPolicy;
  }

  /**
   * Sets the interest policy (really subscription attributes).
   */
  private void setInterestPolicy(SubscriptionAttributes attributes) {
    this.interestPolicy = attributes;
  }

  /**
   * Returns the class of the key constraint.
   */
  private Class getKeyConstraint() {
    return this.keyConstraint;
  }

  /**
   * Sets the class of the key constraint.
   */
  private void setKeyConstraint(Class cls) {
    this.keyConstraint = cls;
  }

  /**
   * Returns the load factor.
   */
  private Float getLoadFactor() {
    return this.loadFactor;
  }

  /**
   * Sets the load factor.
   */
  private void setLoadFactor(Float f) {
    this.loadFactor = f;
  }

  /**
   * Returns the lock grantor.
   */
  private Boolean getLockGrantor() {
    return this.lockGrantor;
  }

  /**
   * Sets the lock grantor.
   */
  private void setLockGrantor(Boolean bool) {
    this.lockGrantor = bool;
  }

  /**
   * Returns the membership attributes.
   */
  private MembershipAttributes getMembershipAttributes() {
    return this.membershipAttributes;
  }

  /**
   * Sets the membership attributes.
   */
  private void setMembershipAttributes(MembershipAttributes attributes) {
    this.membershipAttributes = attributes;
  }

  /**
   * Returns the multicast enabled.
   * <p>
   * If the field was not configured with an explicit boolean, the value is
   * inherited from the distributed system configured for this VM.
   *
   * @throws HydraRuntimeException if inheritance is used but this VM has no
   *         distributed system configured.
   */
  private Boolean getMulticastEnabled() {
    if (this.multicastEnabled == null) {
      String gemfire = System.getProperty(GemFirePrms.GEMFIRE_NAME_PROPERTY);
      if (gemfire == null) {
        String s = "This VM is not configured for a distributed system: "
                 + "missing property " + GemFirePrms.GEMFIRE_NAME_PROPERTY;
        throw new HydraRuntimeException(s);
      }
      this.multicastEnabled = TestConfig.getInstance()
                                        .getGemFireDescription(gemfire)
                                        .getEnableMcast();
    }
    return this.multicastEnabled;
  }

  /**
   * Sets the multicast enabled.
   */
  private void setMulticastEnabled(Boolean bool) {
    this.multicastEnabled = bool;
  }

  /**
   * Returns the partition description name.
   */
  private String getPartitionDescriptionName() {
    return this.partitionDescriptionName;
  }

  /**
   * Sets the partition description name.
   */
  private void setPartitionDescriptionName(String str) {
    this.partitionDescriptionName = str;
  }

  /**
   * Returns the partition description.
   */
  public PartitionDescription getPartitionDescription() {
    return this.partitionDescription;
  }

  /**
   * Sets the partition description.
   */
  private void setPartitionDescription(PartitionDescription pd) {
    this.partitionDescription = pd;
  }

  /**
   * Returns the pool description name.
   */
  private String getPoolDescriptionName() {
    return this.poolDescriptionName;
  }

  /**
   * Sets the pool description name.
   */
  private void setPoolDescriptionName(String str) {
    this.poolDescriptionName = str;
  }

  /**
   * Returns the pool description.
   */
  public PoolDescription getPoolDescription() {
    return this.poolDescription;
  }

  /**
   * Sets the pool description.
   */
  private void setPoolDescription(PoolDescription pd) {
    this.poolDescription = pd;
  }

  /**
   * Returns the expiration attributes for the region idle timeout.
   */
  private ExpirationAttributes getRegionIdleTimeout() {
    return this.regionIdleTimeout;
  }

  /**
   * Sets the expiration attributes for the region idle timeout.
   */
  private void setRegionIdleTimeout(ExpirationAttributes attributes) {
    this.regionIdleTimeout = attributes;
  }

  /**
   * Returns the actual name of this region.
   */
  public String getRegionName() {
    return this.regionName;
  }

  /**
   * Sets the actual name of this region.
   */
  private void setRegionName(String str) {
    this.regionName = str;
  }

  /**
   * Returns the expiration attributes for the region time to live.
   */
  private ExpirationAttributes getRegionTimeToLive() {
    return this.regionTimeToLive;
  }

  /**
   * Sets the expiration attributes for the region time to live.
   */
  private void setRegionTimeToLive(ExpirationAttributes attributes) {
    this.regionTimeToLive = attributes;
  }

  /**
   * Returns the scope.
   */
  private Scope getScope() {
    return this.scope;
  }

  /**
   * Sets the scope.
   */
  private void setScope(Scope aScope) {
    this.scope = aScope;
  }

  /**
   * Returns the statistics enabled.
   */
  private Boolean getStatisticsEnabled() {
    return this.statisticsEnabled;
  }

  /**
   * Sets the statistics enabled.
   */
  private void setStatisticsEnabled(Boolean bool) {
    this.statisticsEnabled = bool;
  }

  /**
   * Returns the class of the value constraint.
   */
  private Class getValueConstraint() {
    return this.valueConstraint;
  }

  /**
   * Sets the class of the value constraint.
   */
  private void setValueConstraint(Class cls) {
    this.valueConstraint = cls;
  }

//------------------------------------------------------------------------------
// Region configuration
//------------------------------------------------------------------------------

  /**
   * Configures the attributes factory using this region description.  Has the
   * option to skip instantiating cache listeners, loaders, and writers when
   * creating dummy regions to generate cache XML files.  Passes the default
   * region name to the fixed partition attributes mapping algorithm, if any.
   */
  public void configure(AttributesFactory f, boolean instantiate) {
    configure(RegionPrms.DEFAULT_REGION_NAME, f, instantiate);
  }

  /**
   * Configures the attributes factory using this region description.  Has the
   * option to skip instantiating cache listeners, loaders, and writers when
   * creating dummy regions to generate cache XML files.  Passes the region
   * name, if any, to the fixed partition attributes mapping algorithm, if any.
   */
  protected void configure(String regionName, AttributesFactory f,
                                              boolean instantiate) {
    // configure the factory
    List<AsyncEventQueueDescription> aeqds =
                        this.getAsyncEventQueueDescriptions();
    if (aeqds != null) {
      for (AsyncEventQueueDescription aeqd : aeqds) {
        f.addAsyncEventQueueId(aeqd.getName());
      }
    }
    f.setCacheLoader(this.getCacheLoaderInstance(instantiate));
    f.setCacheWriter(this.getCacheWriterInstance(instantiate));
    f.initCacheListeners(this.getCacheListenerInstances(instantiate));
    f.setCloningEnabled(this.getCloningEnabled().booleanValue());
    f.setConcurrencyChecksEnabled(this.getConcurrencyChecksEnabled().booleanValue());
    f.setConcurrencyLevel(this.getConcurrencyLevel().intValue());
    f.setCustomEntryIdleTimeout(this.getCustomEntryIdleTimeoutInstance());
    f.setCustomEntryTimeToLive(this.getCustomEntryTimeToLiveInstance());
    f.setDataPolicy(this.getDataPolicy());
    if (this.getDiskStoreDescription() != null) {
      f.setDiskStoreName(this.getDiskStoreDescription().getName());
    }
    f.setDiskSynchronous(this.getDiskSynchronous().booleanValue());
    f.setEnableAsyncConflation(this.getEnableAsyncConflation().booleanValue());
    f.setEnableGateway(this.getEnableGateway().booleanValue());
    f.setEnableOffHeapMemory(this.getEnableOffHeapMemory().booleanValue());
    f.setEnableSubscriptionConflation(this.getEnableSubscriptionConflation().booleanValue());
    f.setEntryIdleTimeout(this.getEntryIdleTimeout());
    f.setEntryTimeToLive(this.getEntryTimeToLive());
    f.setEvictionAttributes(this.getEvictionAttributes());
    List<GatewaySenderDescription> gsds = this.getGatewaySenderDescriptions();
    if (gsds != null) {
      for (GatewaySenderDescription gsd : gsds) {
        Set<String> serIds =
          GatewaySenderHelper.getSerialGatewaySenderIds(gsd.getName());
        for (String serId : serIds) {
          f.addGatewaySenderId(serId);
        }
        Set<String> parIds =
          GatewaySenderHelper.getParallelGatewaySenderIds(gsd.getName());
        for (String parId : parIds) {
          f.addGatewaySenderId(parId);
        }
      }
    }
    if (this.getHDFSStoreDescription() != null) {
      f.setHDFSStoreName(this.getHDFSStoreDescription().getName());
    }
    f.setHDFSWriteOnly(this.getHDFSWriteOnly().booleanValue());
    f.setIgnoreJTA(this.getIgnoreJTA().booleanValue());
    f.setIndexMaintenanceSynchronous(this.getIndexMaintenanceSynchronous().booleanValue());
    f.setInitialCapacity(this.getInitialCapacity().intValue());
    f.setSubscriptionAttributes(this.getInterestPolicy());
    f.setKeyConstraint(this.getKeyConstraint());
    f.setLoadFactor(this.getLoadFactor().floatValue());
    f.setLockGrantor(this.getLockGrantor().booleanValue());
    f.setMembershipAttributes(this.getMembershipAttributes());
    f.setMulticastEnabled(this.getMulticastEnabled().booleanValue());
    if (this.getPartitionDescription() != null) {
      f.setPartitionAttributes(this.getPartitionDescription()
                                   .getPartitionAttributes(this.regionName));
    }
    if (this.getPoolDescription() != null) {
      f.setPoolName(this.getPoolDescription().getName());
    }
    f.setRegionIdleTimeout(this.getRegionIdleTimeout());
    f.setRegionTimeToLive(this.getRegionTimeToLive());
    if (!isPartitioned(this.getDataPolicy())) {
      f.setScope(this.getScope());
    }
    f.setStatisticsEnabled(this.getStatisticsEnabled().booleanValue());
    f.setValueConstraint(this.getValueConstraint());
  }

  /**
   * Returns the region attributes as a string.  For use only by {@link
   * RegionHelper#regionAttributesToString(RegionAttributes)}.
   */
  protected static synchronized String regionAttributesToString(
                                             RegionAttributes r) {
    StringBuffer buf = new StringBuffer();
    buf.append("\n  asyncEventQueues: " + (new TreeSet(r.getAsyncEventQueueIds())));
    buf.append("\n  cacheListeners: " + cacheListenersFor(r.getCacheListeners()));
    buf.append("\n  cacheLoader: " + cacheLoaderFor(r.getCacheLoader()));
    buf.append("\n  cacheWriter: " + cacheWriterFor(r.getCacheWriter()));
    buf.append("\n  cloningEnabled: " + r.getCloningEnabled());
    buf.append("\n  concurrencyChecksEnabled: " + r.getConcurrencyChecksEnabled());
    buf.append("\n  concurrencyLevel: " + r.getConcurrencyLevel());
    buf.append("\n  customEntryIdleTimeout: " + customExpiryFor(r.getCustomEntryIdleTimeout()));
    buf.append("\n  customEntryTimeToLive: " + customExpiryFor(r.getCustomEntryTimeToLive()));
    buf.append("\n  dataPolicy: " + r.getDataPolicy());
    buf.append("\n  diskStoreName: " + r.getDiskStoreName());
    buf.append("\n  diskSynchronous: " + r.isDiskSynchronous());
    buf.append("\n  enableAsyncConflation: " + r.getEnableAsyncConflation());
    buf.append("\n  enableGateway: " + r.getEnableGateway());
    buf.append("\n  enableOffHeapMemory: " + r.getEnableOffHeapMemory());
    buf.append("\n  enableSubscriptionConflation: " + r.getEnableSubscriptionConflation());
    buf.append("\n  entryIdleTimeout: " + r.getEntryIdleTimeout());
    buf.append("\n  entryTimeToLive: " + r.getEntryTimeToLive());
    buf.append("\n  evictionAttributes: " + r.getEvictionAttributes());
    buf.append("\n  gatewaySenders: " + (new TreeSet(r.getGatewaySenderIds())));
    buf.append("\n  hdfsStoreName: " + r.getHDFSStoreName());
    buf.append("\n  hdfsWriteOnly: " + r.getHDFSWriteOnly());
    buf.append("\n  ignoreJTA: " + r.getIgnoreJTA());
    buf.append("\n  indexMaintenanceSynchronous: " + r.getIndexMaintenanceSynchronous());
    buf.append("\n  initialCapacity: " + r.getInitialCapacity());
    buf.append("\n  interestPolicy: " + r.getSubscriptionAttributes());
    buf.append("\n  keyConstraint: " + r.getKeyConstraint());
    buf.append("\n  loadFactor: " + r.getLoadFactor());
    buf.append("\n  lockGrantor: " + r.isLockGrantor());
    buf.append("\n  membershipAttributes: " + r.getMembershipAttributes());
    buf.append("\n  multicastEnabled: " + r.getMulticastEnabled());
    buf.append("\n  partitionAttributes: " + PartitionDescription
       .partitionAttributesToString(r.getPartitionAttributes()));
    buf.append("\n  poolName: " + r.getPoolName());
    buf.append("\n  regionIdleTimeout: " + r.getRegionIdleTimeout());
    buf.append("\n  regionTimeToLive: " + r.getRegionTimeToLive());
    buf.append("\n  scope: " + r.getScope());
    buf.append("\n  statisticsEnabled: " + r.getStatisticsEnabled());
    buf.append("\n  valueConstraint: " + r.getValueConstraint());
    return buf.toString();
  }

  /**
   * Returns the partial region attributes as a string. Omits possibly HDFS
   * side-effected attributes. For use only by {@link RegionHelper
   * #regionAttributesToString(RegionAttributes)}.
   */
  protected static synchronized String regionAttributesToStringPartial(
                                       RegionAttributes r) {
    StringBuffer buf = new StringBuffer();
    //buf.append("\n  asyncEventQueues: " + (new TreeSet(r.getAsyncEventQueueIds()))); // HDFS
    buf.append("\n  cacheListeners: " + cacheListenersFor(r.getCacheListeners()));
    buf.append("\n  cacheLoader: " + cacheLoaderFor(r.getCacheLoader()));
    buf.append("\n  cacheWriter: " + cacheWriterFor(r.getCacheWriter()));
    buf.append("\n  cloningEnabled: " + r.getCloningEnabled());
    buf.append("\n  concurrencyChecksEnabled: " + r.getConcurrencyChecksEnabled());
    buf.append("\n  concurrencyLevel: " + r.getConcurrencyLevel());
    buf.append("\n  customEntryIdleTimeout: " + customExpiryFor(r.getCustomEntryIdleTimeout()));
    buf.append("\n  customEntryTimeToLive: " + customExpiryFor(r.getCustomEntryTimeToLive()));
    buf.append("\n  dataPolicy: " + r.getDataPolicy());
    buf.append("\n  diskSynchronous: " + r.isDiskSynchronous());
    buf.append("\n  enableAsyncConflation: " + r.getEnableAsyncConflation());
    buf.append("\n  enableGateway: " + r.getEnableGateway());
    buf.append("\n  enableOffHeapMemory: " + r.getEnableOffHeapMemory());
    buf.append("\n  enableSubscriptionConflation: " + r.getEnableSubscriptionConflation());
    buf.append("\n  entryIdleTimeout: " + r.getEntryIdleTimeout());
    buf.append("\n  entryTimeToLive: " + r.getEntryTimeToLive());
    //buf.append("\n  evictionAttributes: " + r.getEvictionAttributes()); // HDFS
    buf.append("\n  gatewaySenders: " + (new TreeSet(r.getGatewaySenderIds())));
    buf.append("\n  hdfsStoreName: " + r.getHDFSStoreName());
    buf.append("\n  hdfsWriteOnly: " + r.getHDFSWriteOnly());
    buf.append("\n  ignoreJTA: " + r.getIgnoreJTA());
    buf.append("\n  indexMaintenanceSynchronous: " + r.getIndexMaintenanceSynchronous());
    buf.append("\n  initialCapacity: " + r.getInitialCapacity());
    buf.append("\n  interestPolicy: " + r.getSubscriptionAttributes());
    buf.append("\n  keyConstraint: " + r.getKeyConstraint());
    buf.append("\n  loadFactor: " + r.getLoadFactor());
    buf.append("\n  lockGrantor: " + r.isLockGrantor());
    buf.append("\n  membershipAttributes: " + r.getMembershipAttributes());
    buf.append("\n  multicastEnabled: " + r.getMulticastEnabled());
    buf.append("\n  partitionAttributes: " + PartitionDescription
       .partitionAttributesToString(r.getPartitionAttributes()));
    buf.append("\n  poolName: " + r.getPoolName());
    buf.append("\n  regionIdleTimeout: " + r.getRegionIdleTimeout());
    buf.append("\n  regionTimeToLive: " + r.getRegionTimeToLive());
    buf.append("\n  scope: " + r.getScope());
    buf.append("\n  statisticsEnabled: " + r.getStatisticsEnabled());
    buf.append("\n  valueConstraint: " + r.getValueConstraint());
    return buf.toString();
  }

  /**
   * Returns the cache listener class names.
   */
  private static List cacheListenersFor(CacheListener[] listeners) {
    List classnames = new ArrayList();
    for (int i = 0; i < listeners.length; i++) {
      classnames.add(listeners[i].getClass().getName());
    }
    return classnames;
  }

  /**
   * Returns the cache loader class name.
   */
  private static String cacheLoaderFor(CacheLoader loader) {
    if (loader == null) {
      return null;
    } else {
      return loader.getClass().getName();
    }
  }

  /**
   * Returns the cache writer class name.
   */
  private static String cacheWriterFor(CacheWriter writer) {
    if (writer == null) {
      return null;
    } else {
      return writer.getClass().getName();
    }
  }

  /**
   * Returns the custom expiry class name.
   */
  private static String customExpiryFor(CustomExpiry expiry) {
    if (expiry == null) {
      return null;
    } else {
      return expiry.getClass().getName();
    }
  }

//------------------------------------------------------------------------------
// Printing
//------------------------------------------------------------------------------

  public SortedMap toSortedMap() {
    SortedMap map = new TreeMap();
    String header = this.getClass().getName() + "." + this.getName() + ".";
    map.put(header + "asyncEventQueueNames", this.getAsyncEventQueueNames());
    map.put(header + "cacheListeners", this.getCacheListeners());
    map.put(header + "cacheListenersSingleton", this.getCacheListenersSingleton());
    map.put(header + "cacheLoader", this.getCacheLoader());
    map.put(header + "cacheLoaderSingleton", this.getCacheLoaderSingleton());
    map.put(header + "cacheWriter", this.getCacheWriter());
    map.put(header + "cacheWriterSingleton", this.getCacheWriterSingleton());
    map.put(header + "concurrencyChecksEnabled", this.getConcurrencyChecksEnabled());
    map.put(header + "cloningEnabled", this.getCloningEnabled());
    map.put(header + "concurrencyLevel", this.getConcurrencyLevel());
    map.put(header + "customEntryIdleTimeout", this.getCustomEntryIdleTimeout());
    map.put(header + "customEntryTimeToLive", this.getCustomEntryTimeToLive());
    map.put(header + "dataPolicy", this.getDataPolicy());
    map.put(header + "diskStoreName", this.getDiskStoreName());
    map.put(header + "diskSynchronous", this.getDiskSynchronous());
    map.put(header + "enableAsyncConflation", this.getEnableAsyncConflation());
    map.put(header + "enableGateway", this.getEnableGateway());
    map.put(header + "enableOffHeapMemory", this.getEnableOffHeapMemory());
    map.put(header + "enableSubscriptionConflation", this.getEnableSubscriptionConflation());
    map.put(header + "entryIdleTimeout", this.getEntryIdleTimeout());
    map.put(header + "entryTimeToLive", this.getEntryTimeToLive());
    map.put(header + "evictionAttributes", this.getEvictionAttributes());
    map.put(header + "gatewaySenderNames", this.getGatewaySenderNames());
    map.put(header + "hdfsStoreName", this.getHDFSStoreName());
    map.put(header + "hdfsWriteOnly", this.getHDFSWriteOnly());
    map.put(header + "ignoreJTA", this.getIgnoreJTA());
    map.put(header + "indexMaintenanceSynchronous", this.getIndexMaintenanceSynchronous());
    map.put(header + "initialCapacity", this.getInitialCapacity());
    map.put(header + "interestPolicy", this.getInterestPolicy());
    map.put(header + "keyConstraint", this.getKeyConstraint());
    map.put(header + "loadFactor", this.getLoadFactor());
    map.put(header + "lockGrantor", this.getLockGrantor());
    map.put(header + "membershipAttributes", this.getMembershipAttributes());
    if (this.multicastEnabled == null) {
      map.put(header + "multicastEnabled", "inherited from distributed system");
    } else {
      map.put(header + "multicastEnabled", this.getMulticastEnabled());
    }
    map.put(header + "partitionName", this.getPartitionDescriptionName());
    map.put(header + "poolName", this.getPoolDescriptionName());
    map.put(header + "regionIdleTimeout", this.getRegionIdleTimeout());
    map.put(header + "regionName", this.getRegionName());
    map.put(header + "regionTimeToLive", this.getRegionTimeToLive());
    map.put(header + "scope", this.getScope());
    map.put(header + "statisticsEnabled", this.getStatisticsEnabled());
    map.put(header + "valueConstraint", this.getValueConstraint());
    return map;
  }

//------------------------------------------------------------------------------
// Configuration
//------------------------------------------------------------------------------

  /**
   * Creates region attributes from the region description, setting only those
   * that are not null.  Picks up product defaults and side-effects, and does
   * product-level validation.
   */
  private static RegionAttributes createRegionAttributes(RegionDescription rd) {
    AttributesFactory f = new AttributesFactory();
    // defer asyncEventQueueDescriptions
    // defer asyncEventQueueNames
    // defer cacheListeners
    // defer cacheLoader
    // defer cacheWriter
    if (rd.cloningEnabled != null) {
      f.setCloningEnabled(rd.getCloningEnabled().booleanValue());
    }
    if (rd.concurrencyLevel != null) {
      f.setConcurrencyLevel(rd.getConcurrencyLevel().intValue());
    }
    // defer customEntryIdleTimeout
    // defer customEntryTimeToLive
    if (rd.dataPolicy != null) {
      f.setDataPolicy(rd.getDataPolicy());
    }
    if (rd.diskStoreDescription != null) {
      f.setDiskStoreName(rd.getDiskStoreDescription().getName());
    }
    if (rd.diskSynchronous != null) {
      f.setDiskSynchronous(rd.getDiskSynchronous().booleanValue());
    }
    if (rd.enableAsyncConflation != null) {
      f.setEnableAsyncConflation(rd.getEnableAsyncConflation().booleanValue());
    }
    if (rd.enableGateway != null) {
      f.setEnableGateway(rd.getEnableGateway().booleanValue());
    }
    if (rd.enableOffHeapMemory != null) {
      f.setEnableOffHeapMemory(rd.getEnableOffHeapMemory().booleanValue());
    }
    if (rd.enableSubscriptionConflation != null) {
      f.setEnableSubscriptionConflation(rd.getEnableSubscriptionConflation().booleanValue());
    }
    if (rd.entryIdleTimeout != null) {
      f.setEntryIdleTimeout(rd.getEntryIdleTimeout());
    }
    if (rd.entryTimeToLive != null) {
      f.setEntryTimeToLive(rd.getEntryTimeToLive());
    }
    if (rd.evictionAttributes != null) {
      f.setEvictionAttributes(rd.getEvictionAttributes());
    }
    // defer gatewaySenderDescriptions
    // defer gatewaySenderNames
    if (rd.hdfsStoreDescription != null) {
      f.setHDFSStoreName(rd.getHDFSStoreDescription().getName());
    }
    if (rd.hdfsWriteOnly != null) {
      f.setHDFSWriteOnly(rd.getHDFSWriteOnly().booleanValue());
    }
    if (rd.ignoreJTA != null) {
      f.setIgnoreJTA(rd.getIgnoreJTA().booleanValue());
    }
    if (rd.indexMaintenanceSynchronous != null) {
      f.setIndexMaintenanceSynchronous(rd.getIndexMaintenanceSynchronous().booleanValue());
    }
    if (rd.initialCapacity != null) {
      f.setInitialCapacity(rd.getInitialCapacity().intValue());
    }
    if (rd.interestPolicy != null) {
      f.setSubscriptionAttributes(rd.getInterestPolicy());
    }
    if (rd.keyConstraint != null) {
      f.setKeyConstraint(rd.getKeyConstraint());
    }
    if (rd.loadFactor != null) {
      f.setLoadFactor(rd.getLoadFactor().floatValue());
    }
    if (rd.lockGrantor != null) {
      f.setLockGrantor(rd.getLockGrantor().booleanValue());
    }
    if (rd.membershipAttributes != null) {
      f.setMembershipAttributes(rd.getMembershipAttributes());
    }
    if (rd.multicastEnabled != null) {
      f.setMulticastEnabled(rd.getMulticastEnabled().booleanValue());
    }
    // defer partitionAttributes
    if (rd.poolDescription != null) {
      f.setPoolName(rd.getPoolDescription().getName());
    }
    if (rd.regionIdleTimeout != null) {
      f.setRegionIdleTimeout(rd.getRegionIdleTimeout());
    }
    if (rd.regionTimeToLive != null) {
      f.setRegionTimeToLive(rd.getRegionTimeToLive());
    }
    if (rd.scope != null && !isPartitioned(rd.dataPolicy)) {
      f.setScope(rd.getScope());
    }
    if (rd.statisticsEnabled != null) {
      f.setStatisticsEnabled(rd.getStatisticsEnabled().booleanValue());
    }
    if (rd.valueConstraint != null) {
      f.setValueConstraint(rd.getValueConstraint());
    }
    return f.create();
  }

  /**
   * Resets the region description based on region attributes, to pick up
   * product defaults and side-effects.
   */
  private static void resetRegionDescription(RegionDescription rd,
                                             RegionAttributes ra) {
    // defer asyncEventQueueDescriptions
    // defer asyncEventQueueNames
    // defer cacheListeners
    // defer cacheLoader
    // defer cacheWriter
    rd.setCloningEnabled(Boolean.valueOf(ra.getCloningEnabled()));
    rd.setConcurrencyChecksEnabled(Boolean.valueOf(ra.getConcurrencyChecksEnabled()));
    rd.setConcurrencyLevel(Integer.valueOf(ra.getConcurrencyLevel()));
    // defer customEntryIdleTimeout
    // defer customEntryTimeToLive
    rd.setDataPolicy(ra.getDataPolicy());
    rd.setDiskSynchronous(Boolean.valueOf(ra.isDiskSynchronous()));
    rd.setEnableAsyncConflation(Boolean.valueOf(ra.getEnableAsyncConflation()));
    rd.setEnableGateway(Boolean.valueOf(ra.getEnableGateway()));
    rd.setEnableOffHeapMemory(Boolean.valueOf(ra.getEnableOffHeapMemory()));
    rd.setEnableSubscriptionConflation(Boolean.valueOf(ra.getEnableSubscriptionConflation()));
    rd.setEntryIdleTimeout(ra.getEntryIdleTimeout());
    rd.setEntryTimeToLive(ra.getEntryTimeToLive());
    rd.setEvictionAttributes(ra.getEvictionAttributes());
    // defer gatewaySenderDescriptions
    // defer gatewaySenderNames
    rd.setHDFSStoreName(ra.getHDFSStoreName());
    rd.setHDFSWriteOnly(Boolean.valueOf(ra.getHDFSWriteOnly()));
    rd.setIgnoreJTA(Boolean.valueOf(ra.getIgnoreJTA()));
    rd.setIndexMaintenanceSynchronous(Boolean.valueOf(ra.getIndexMaintenanceSynchronous()));
    rd.setInitialCapacity(Integer.valueOf(ra.getInitialCapacity()));
    rd.setInterestPolicy(ra.getSubscriptionAttributes());
    rd.setKeyConstraint(ra.getKeyConstraint());
    rd.setLoadFactor(Float.valueOf(ra.getLoadFactor()));
    rd.setLockGrantor(Boolean.valueOf(ra.isLockGrantor()));
    rd.setMembershipAttributes(ra.getMembershipAttributes());
    if (rd.multicastEnabled != null) {
      rd.setMulticastEnabled(Boolean.valueOf(ra.getMulticastEnabled()));
    } // else leave null to defer to distributed system
    rd.setRegionIdleTimeout(ra.getRegionIdleTimeout());
    // regionName is not a region attribute
    rd.setRegionTimeToLive(ra.getRegionTimeToLive());
    rd.setScope(ra.getScope());
    rd.setStatisticsEnabled(Boolean.valueOf(ra.getStatisticsEnabled()));
    rd.setValueConstraint(ra.getValueConstraint());
  }

//------------------------------------------------------------------------------
// Cache listeners configuration support
//------------------------------------------------------------------------------

  /**
   * Returns a cache listener instance for each cache listener classname.
   * <p>
   * Manages singletons if instantiate is true, which means that these are real
   * runtime instances rather than test configuration instances.
   *
   * @throws HydraConfigException if instantiation fails or a class does not
   *                              implement CacheListener.
   */
  private synchronized CacheListener[] getCacheListenerInstances(
                                                       boolean instantiate) {
    List classnames = this.getCacheListeners();
    if (classnames == null) {
      return null;
    } else {
      Map instanceMap = (Map)cacheListenerInstanceMaps.get(this.getName());
      Long key = RegionPrms.cacheListeners;
      List listeners = new ArrayList();
      for (Iterator i = classnames.iterator(); i.hasNext();) {
        String classname = (String)i.next();
        if (instantiate && this.getCacheListenersSingleton().booleanValue()) {
          // singleton case
          if (instanceMap == null) {
            instanceMap = new HashMap();
          }
          Object instance = instanceMap.get(classname);
          if (instance == null) { // create and save a new instance
            CacheListener listener = getAppCacheListenerInstance(classname);
            instanceMap.put(classname, listener);
            listeners.add(listener);
          } else { // use the existing instance
            listeners.add(instance);
          }
        } else {
          // non-singleton case, create a new instance
          listeners.add(getAppCacheListenerInstance(classname));
        }
      }
      CacheListener[] result = new CacheListener[listeners.size()];
      for (int i = 0; i < listeners.size(); i++) {
        result[i] = (CacheListener)listeners.get(i);
      }
      return result;
    }
  }

  /**
   * Returns an application-defined cache listener instance for the classname.
   * @throws HydraConfigException if instantiation fails or the class does not
   *                              implement CacheListener.
   */
  private static CacheListener getAppCacheListenerInstance(String classname) {
    Long key = RegionPrms.cacheListeners;
    Object obj = getInstance(key, classname);
    try {
      return (CacheListener)obj;
    } catch (ClassCastException e) {
      String s = BasePrms.nameForKey(key)
        + " does not implement CacheListener: " + classname;
      throw new HydraConfigException(s);
    }
  }

//------------------------------------------------------------------------------
// Cache loader configuration support
//------------------------------------------------------------------------------

  /**
   * Returns a cache loader instance.
   * <p>
   * Manages singletons if instantiate is true, which means that this is a real
   * runtime instance rather than a test configuration instance.
   */
  private synchronized CacheLoader getCacheLoaderInstance(boolean instantiate) {
    String s = this.getCacheLoader();
    if (s == null) {
      return null;
    } else {
      if (instantiate && this.getCacheLoaderSingleton().booleanValue()) {
        // singleton case
        Object instance = cacheLoaderInstances.get(this.getName());
        if (instance == null) { // create and save a new instance
          CacheLoader loader = getCacheLoaderInstance(s);
          cacheLoaderInstances.put(this.getName(), loader);
          return loader;
        } else { // use the existing instance
          return (CacheLoader)instance;
        }
      } else {
        // non-singleton case, create a new instance
        return getCacheLoaderInstance(s);
      }
    }
  }

  /**
   * Returns an application-defined cache loader instance for the classname.
   * @throws HydraConfigException if instantiation fails or the class does not
   *                              implement CacheLoader.
   */
  private static CacheLoader getCacheLoaderInstance(String classname) {
    Long key = RegionPrms.cacheLoader;
    Object obj = getInstance(key, classname);
    try {
      return (CacheLoader)obj;
    } catch (ClassCastException e) {
      String s = BasePrms.nameForKey(key)
        + " does not implement CacheLoader: " + classname;
      throw new HydraConfigException(s);
    }
  }

//------------------------------------------------------------------------------
// Cache writer configuration support
//------------------------------------------------------------------------------

  /**
   * Returns a cache writer instance.
   * <p>
   * Manages singletons if instantiate is true, which means that this is a real
   * runtime instance rather than a test configuration instance.
   * <p>
   * This method is public to support DynamicRegionFactory configuration only.
   */
  public synchronized CacheWriter getCacheWriterInstance(boolean instantiate) {
    String s = this.getCacheWriter();
    if (s == null) {
      return null;
    } else {
      if (instantiate && this.getCacheWriterSingleton().booleanValue()) {
        // singleton case
        Object instance = cacheWriterInstances.get(this.getName());
        if (instance == null) { // create and save a new instance
          CacheWriter writer = getCacheWriterInstance(s);
          cacheWriterInstances.put(this.getName(), writer);
          return writer;
        } else { // use the existing instance
          return (CacheWriter)instance;
        }
      } else {
        // non-singleton case, create a new instance
        return getCacheWriterInstance(s);
      }
    }
  }

  /**
   * Returns an application-defined cache writer instance for the classname.
   * @throws HydraConfigException if instantiation fails or the class does not
   *                              implement CacheWriter.
   */
  private static CacheWriter getCacheWriterInstance(String classname) {
    Long key = RegionPrms.cacheWriter;
    Object obj = getInstance(key, classname);
    try {
      return (CacheWriter)obj;
    } catch (ClassCastException e) {
      String s = BasePrms.nameForKey(key)
        + " does not implement CacheWriter: " + classname;
      throw new HydraConfigException(s);
    }
  }

//------------------------------------------------------------------------------
// Custom entry idle timeout and entry time to live support
//------------------------------------------------------------------------------

  /**
   * Returns a custom expiry instance for the custom entry idle timeout.
   */
  private synchronized CustomExpiry getCustomEntryIdleTimeoutInstance() {
    String classname = this.getCustomEntryIdleTimeout();
    if (classname == null) {
      return null;
    } else {
      return getCustomExpiry(classname, RegionPrms.customEntryIdleTimeout);
    }
  }

  /**
   * Returns a custom expiry instance for the custom entry time to live.
   */
  private synchronized CustomExpiry getCustomEntryTimeToLiveInstance() {
    String classname = this.getCustomEntryTimeToLive();
    if (classname == null) {
      return null;
    } else {
      return getCustomExpiry(classname, RegionPrms.customEntryTimeToLive);
    }
  }

  /**
   * Returns the CustomExpiry instance for the given string.
   */
  private static CustomExpiry getCustomExpiry(String classname, Long key) {
    if (classname.equalsIgnoreCase(BasePrms.NONE)) {
      return null;
    } else {
      try {
        return (CustomExpiry)getInstance(key, classname);
      } catch (ClassCastException e) {
        String s = BasePrms.nameForKey(key)
                 + " does not implement CustomExpiry: " + classname;
        throw new HydraConfigException(s);
      }
    }
  }

//------------------------------------------------------------------------------
// Data policy configuration support
//------------------------------------------------------------------------------

  private static boolean isPartitioned(DataPolicy policy) {
    return policy != null && policy.toString().contains(PARTITION);
  }

//------------------------------------------------------------------------------
// Version support
//------------------------------------------------------------------------------

  /**
   * Custom deserialization.
   */
  private void readObject(java.io.ObjectInputStream in)
  throws IOException, ClassNotFoundException {
    this.asyncEventQueueDescriptions = (List<AsyncEventQueueDescription>)in.readObject();
    this.asyncEventQueueNames = (List<String>)in.readObject();
    this.cacheListeners = (List)in.readObject();
    this.cacheListenersSingleton = (Boolean)in.readObject();
    this.cacheLoader = (String)in.readObject();
    this.cacheLoaderSingleton = (Boolean)in.readObject();
    this.cacheWriter = (String)in.readObject();
    this.cacheWriterSingleton = (Boolean)in.readObject();
    this.cloningEnabled = (Boolean)in.readObject();
    /* this.compressor = */ in.readObject();
    /* this.compressorSingleton = */ in.readObject();
    this.concurrencyChecksEnabled = (Boolean)in.readObject();
    this.concurrencyLevel = (Integer)in.readObject();
    this.customEntryIdleTimeout = (String)in.readObject();
    this.customEntryTimeToLive = (String)in.readObject();
    this.dataPolicy = readDataPolicy(in);
    this.diskStoreName = (String)in.readObject();
    this.diskStoreDescription = (DiskStoreDescription)in.readObject();
    this.diskSynchronous = (Boolean)in.readObject();
    this.enableAsyncConflation = (Boolean)in.readObject();
    this.enableGateway = (Boolean)in.readObject();
    this.enableOffHeapMemory = (Boolean)in.readObject();
    this.enableSubscriptionConflation = (Boolean)in.readObject();
    this.entryIdleTimeout = readExpirationAttributes(in);
    this.entryTimeToLive = readExpirationAttributes(in);
    this.evictionAttributes = readEvictionAttributes(in);
    this.gatewaySenderDescriptions = (List<GatewaySenderDescription>)in.readObject();
    this.gatewaySenderNames = (List<String>)in.readObject();
    this.hdfsStoreName = (String)in.readObject();
    this.hdfsStoreDescription = (HDFSStoreDescription)in.readObject();
    this.hdfsWriteOnly = (Boolean)in.readObject();
    this.ignoreJTA = (Boolean)in.readObject();
    this.indexMaintenanceSynchronous = (Boolean)in.readObject();
    this.initialCapacity = (Integer)in.readObject();
    this.interestPolicy = (SubscriptionAttributes)in.readObject();
    this.keyConstraint = (Class)in.readObject();
    this.loadFactor = (Float)in.readObject();
    this.lockGrantor = (Boolean)in.readObject();
    this.membershipAttributes = (MembershipAttributes)in.readObject();
    this.multicastEnabled = (Boolean)in.readObject();
    this.name = (String)in.readObject();
    this.partitionDescription = (PartitionDescription)in.readObject();
    this.partitionDescriptionName = (String)in.readObject();
    this.poolDescription = (PoolDescription)in.readObject();
    this.poolDescriptionName = (String)in.readObject();
    this.regionIdleTimeout = readExpirationAttributes(in);
    this.regionName = (String)in.readObject();
    this.regionTimeToLive = readExpirationAttributes(in);
    this.scope = readScope(in);
    this.statisticsEnabled = (Boolean)in.readObject();
    this.valueConstraint = (Class)in.readObject();

    // create region attributes from non-default region description fields
    // and do product-level validation
    RegionAttributes ra = createRegionAttributes(this);

    // reset region description based on region attributes to pick up product
    // defaults and side-effects
    resetRegionDescription(this, ra);
  }

  /**
   * Required to throw better error messages when using a data policy that is
   * unsupported in a given version.
   */
  private DataPolicy readDataPolicy(ObjectInputStream in)
  throws IOException, ClassNotFoundException {
    String str = (String)in.readObject();
    if (str == null) {
      return null;
    } else {
      if (str.equals(DataPolicy.EMPTY.toString())) {
        return DataPolicy.EMPTY;
      } else if (str.equals(DataPolicy.NORMAL.toString())) {
        return DataPolicy.NORMAL;
      } else if (str.equals(DataPolicy.HDFS_PARTITION.toString())) {
        return DataPolicy.HDFS_PARTITION;
      } else if (str.equals(DataPolicy.HDFS_PERSISTENT_PARTITION.toString())) {
        return DataPolicy.HDFS_PERSISTENT_PARTITION;
      } else if (str.equals(DataPolicy.PRELOADED.toString())) {
        return DataPolicy.PRELOADED;
      } else if (str.equals(DataPolicy.PARTITION.toString())) {
        return DataPolicy.PARTITION;
      } else if (str.equals(DataPolicy.PERSISTENT_PARTITION.toString())) {
        return DataPolicy.PERSISTENT_PARTITION;
      } else if (str.equals(DataPolicy.PERSISTENT_REPLICATE.toString())) {
        return DataPolicy.PERSISTENT_REPLICATE;
      } else if (str.equals(DataPolicy.REPLICATE.toString())) {
        return DataPolicy.REPLICATE;
      } else {
        String s = BasePrms.nameForKey(RegionPrms.dataPolicy)
                 + " has illegal value: " + str;
        throw new HydraConfigException(s);
      }
    }
  }

  /**
   * Required for 5.7 due to change from Serializable to DataSerializable.
   */
  private ExpirationAttributes readExpirationAttributes(ObjectInputStream in)
  throws IOException, ClassNotFoundException {
    Object obj = in.readObject();
    if (obj == null) {
      return null;
    }
    else {
      return new ExpirationAttributes(
          /* timeout */ ((Integer)obj).intValue(),
          /* action */ (ExpirationAction)in.readObject());
    }
  }

  /**
   * Required for 5.7 due to change from Serializable to DataSerializable.
   */
  private EvictionAttributes readEvictionAttributes(ObjectInputStream in)
  throws IOException, ClassNotFoundException {
    EvictionAlgorithm algorithm = (EvictionAlgorithm)in.readObject();
    if (algorithm == null) {
      return null;
    }
    else {
      if (algorithm.isNone()) {
        return null; // rely on the product to reset
      }
      else if (algorithm.isLRUEntry()) {
        return EvictionAttributes.createLRUEntryAttributes(
          /* maximum */ ((Integer)in.readObject()).intValue(),
          /* action */ (EvictionAction)in.readObject());
      }
      else if (algorithm.isLRUHeap()) {
        return EvictionAttributes.createLRUHeapAttributes(
          /* sizer */ (ObjectSizer)in.readObject(),
          /* action */ (EvictionAction)in.readObject());
      }
      else if (algorithm.isLRUMemory()) {
        return EvictionAttributes.createLRUMemoryAttributes(
          /* maximum */ ((Integer)in.readObject()).intValue(),
          /* sizer */ (ObjectSizer)in.readObject(),
          /* action */ (EvictionAction)in.readObject());
      }
      else {
        String s = "Unknown eviction algorithm: " + algorithm;
        throw new HydraInternalException(s);
      }
    }
  }

  /**
   * Required for 5.7 due to change from 1.4 source compatibility to pure 1.5.
   */
  private Scope readScope(ObjectInputStream in)
  throws IOException, ClassNotFoundException {
    String s = (String)in.readObject();
    if (s == null) {
      return null;
    }
    else {
      return Scope.fromString(s);
    }
  }
}


text:
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>W28586_text</title>
        <link rel="stylesheet" type="text/css" href="style.css" />

                «

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">MUD

    <p class="styleSans16.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans12.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans20.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Ed

    <p class="styleSans6.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">UU< mm: Era—Q

    <p class="styleSans29.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans11.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">exam ov mm oi? ofw m: ova": 33w 9» w: 8.3» cod cmN 31: Omb 9» cm 00.5» 00.: ome owwA:
mmm.w

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Qt 35m 5: 9mm: 006w 0E6 omme

    <p class="styleSans7.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">283— :m

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">JET

    <p class="styleSans22.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">dalmm—w

    <p class="styleSans16.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">NO.

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">BIT

    <p class="styleSans25.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">waif—L

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">BIT

    <p class="styleSans29.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">
£052

    <p class="styleSans21.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">5.0 ooom WE - o owd owom N.N-o

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">wd ooom oo-w.o_

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Bo oowv m'ow

    <p class="styleSans3.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">NQMZS

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">mm\w_xm

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">QOi m

    <p class="styleSans3.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">onfi x m

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">030:.

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">mmwmm:

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">EONVWNH

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">wocmm:

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">EEmD—Z

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">womb

    <p class="styleSans6.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">2392—2

    <p class="styleSans2.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">X039

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">aim

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">BH]

    <p class="styleSans3.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">btsoum

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">bme

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">im w

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Em w

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">«\m w

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">wk m

    <p class="styleSans3.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">(\I

    <p class="styleSans1.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans3.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

redpajama_set_name: RedPajamaGithub


text:
package org.pentaho.di.core.database;

import java.util.Collection;
import java.util.HashSet;

import org.pentaho.di.core.Const;
import org.pentaho.di.core.row.ValueMetaInterface;

/**
 * Contains Generic Database Connection information through static final members
 *
 * @author Matt
 * @since  11-mrt-2005
 */

public class MonetDBDatabaseMeta extends BaseDatabaseMeta implements DatabaseInterface
{

    public static ThreadLocal<Boolean> safeModeLocal = new ThreadLocal<Boolean>();

	public static final int DEFAULT_VARCHAR_LENGTH = 100;

	private static final String FIELDNAME_PROTECTOR = "_";

	private static Collection<String> reservedWordAlt = new HashSet<String>();

	static {
		reservedWordAlt.add("IS");
		reservedWordAlt.add("ISNULL");
		reservedWordAlt.add("NOTNULL");
		reservedWordAlt.add("IN");
		reservedWordAlt.add("BETWEEN");
		reservedWordAlt.add("OVERLAPS");
		reservedWordAlt.add("LIKE");
		reservedWordAlt.add("ILIKE");
		reservedWordAlt.add("NOT");
		reservedWordAlt.add("AND");
		reservedWordAlt.add("OR");
		reservedWordAlt.add("CHAR");
		reservedWordAlt.add("VARCHAR");
		reservedWordAlt.add("CLOB");
		reservedWordAlt.add("BLOB");
		reservedWordAlt.add("DECIMAL");
		reservedWordAlt.add("DEC");
		reservedWordAlt.add("NUMERIC");
		reservedWordAlt.add("TINYINT");
		reservedWordAlt.add("SMALLINT");
		reservedWordAlt.add("INT");
		reservedWordAlt.add("BIGINT");
		reservedWordAlt.add("REAL");
		reservedWordAlt.add("DOUBLE");
		reservedWordAlt.add("BOOLEAN");
		reservedWordAlt.add("DATE");
		reservedWordAlt.add("TIME");
		reservedWordAlt.add("TIMESTAMP");
		reservedWordAlt.add("INTERVAL");
		reservedWordAlt.add("YEAR");
		reservedWordAlt.add("MONTH");
		reservedWordAlt.add("DAY");
		reservedWordAlt.add("HOUR");
		reservedWordAlt.add("MINUTE");
		reservedWordAlt.add("SECOND");
		reservedWordAlt.add("TIMEZONE");
		reservedWordAlt.add("EXTRACT");
		reservedWordAlt.add("CURRENT_DATE");
		reservedWordAlt.add("CURRENT_TIME");
		reservedWordAlt.add("CURRENT_TIMESTAMP");
		reservedWordAlt.add("LOCALTIME");
		reservedWordAlt.add("LOCALTIMESTAMP");
		reservedWordAlt.add("CURRENT_TIME");
		reservedWordAlt.add("SERIAL");
		reservedWordAlt.add("START");
		reservedWordAlt.add("WITH");
		reservedWordAlt.add("INCREMENT");
		reservedWordAlt.add("CACHE");
		reservedWordAlt.add("CYCLE");
		reservedWordAlt.add("SEQUENCE");
		reservedWordAlt.add("GETANCHOR");
		reservedWordAlt.add("GETBASENAME");
		reservedWordAlt.add("GETCONTENT");
		reservedWordAlt.add("GETCONTEXT");
		reservedWordAlt.add("GETDOMAIN");
		reservedWordAlt.add("GETEXTENSION");
		reservedWordAlt.add("GETFILE");
		reservedWordAlt.add("GETHOST");
		reservedWordAlt.add("GETPORT");
		reservedWordAlt.add("GETPROTOCOL");
		reservedWordAlt.add("GETQUERY");
		reservedWordAlt.add("GETUSER");
		reservedWordAlt.add("GETROBOTURL");
		reservedWordAlt.add("ISURL");
		reservedWordAlt.add("NEWURL");
		reservedWordAlt.add("BROADCAST");
		reservedWordAlt.add("MASKLEN");
		reservedWordAlt.add("SETMASKLEN");
		reservedWordAlt.add("NETMASK");
		reservedWordAlt.add("HOSTMASK");
		reservedWordAlt.add("NETWORK");
		reservedWordAlt.add("TEXT");
		reservedWordAlt.add("ABBREV");
		reservedWordAlt.add("CREATE");
		reservedWordAlt.add("TYPE");
		reservedWordAlt.add("NAME");
		reservedWordAlt.add("DROP");
		reservedWordAlt.add("USER");
	}

	public int[] getAccessTypeList()
	{
		return new int[] { DatabaseMeta.TYPE_ACCESS_NATIVE, DatabaseMeta.TYPE_ACCESS_ODBC, DatabaseMeta.TYPE_ACCESS_JNDI };
	}

	/**
	 * @see DatabaseInterface#getNotFoundTK(boolean)
	 */
	public int getNotFoundTK(boolean use_autoinc)
	{
		if ( supportsAutoInc() && use_autoinc)
		{
			return 1;
		}
		return super.getNotFoundTK(use_autoinc);
	}

	public String getDriverClass()
	{
        if (getAccessType()==DatabaseMeta.TYPE_ACCESS_NATIVE)
        {
            return "nl.cwi.monetdb.jdbc.MonetDriver";
        }
        else
        {
            return "sun.jdbc.odbc.JdbcOdbcDriver"; // always ODBC!
        }

	}

    public String getURL(String hostname, String port, String databaseName)
    {
        if (getAccessType()==DatabaseMeta.TYPE_ACCESS_NATIVE)
        {
        	if (Const.isEmpty(port)) {
        		return "jdbc:monetdb://"+hostname+"/"+databaseName;
        	} else {
        		return "jdbc:monetdb://"+hostname+":"+port+"/"+databaseName;
        	}
        } else {
            return "jdbc:odbc:"+databaseName;
        }
	}

	/**
	 * Checks whether or not the command setFetchSize() is supported by the JDBC driver...
	 * @return true is setFetchSize() is supported!
	 */
	public boolean isFetchSizeSupported()
	{
		return false;
	}

	/**
	 * @return true if the database supports bitmap indexes
	 */
	public boolean supportsBitmapIndex()
	{
		return true;
	}

	public boolean supportsAutoInc() {
		return true;
	}

	public boolean supportsBatchUpdates() {
		return true;
	}

	public boolean supportsSetMaxRows() {
		return true;
	}

	/**
	 * @return true if Kettle can create a repository on this type of database.
	 */
	public boolean supportsRepository()
	{
		return false;
	}

	/**
	 * @param tableName The table to be truncated.
	 * @return The SQL statement to truncate a table: remove all rows from it without a transaction
	 */
	public String getTruncateTableStatement(String tableName)
	{
	    return "DELETE FROM "+tableName;
	}

	/**
	 * Generates the SQL statement to add a column to the specified table
	 * For this generic type, i set it to the most common possibility.
	 *
	 * @param tablename The table to add
	 * @param v The column defined as a value
	 * @param tk the name of the technical key field
	 * @param use_autoinc whether or not this field uses auto increment
	 * @param pk the name of the primary key field
	 * @param semicolon whether or not to add a semi-colon behind the statement.
	 * @return the SQL statement to add a column to the specified table
	 */
	public String getAddColumnStatement(String tablename, ValueMetaInterface v, String tk, boolean use_autoinc, String pk, boolean semicolon)
	{
		return "ALTER TABLE "+tablename+" ADD "+getFieldDefinition(v, tk, pk, use_autoinc, true, false);
	}

	/**
	 * Generates the SQL statement to modify a column in the specified table
	 * @param tablename The table to add
	 * @param v The column defined as a value
	 * @param tk the name of the technical key field
	 * @param use_autoinc whether or not this field uses auto increment
	 * @param pk the name of the primary key field
	 * @param semicolon whether or not to add a semi-colon behind the statement.
	 * @return the SQL statement to modify a column in the specified table
	 */
	public String getModifyColumnStatement(String tablename, ValueMetaInterface v, String tk, boolean use_autoinc, String pk, boolean semicolon)
	{
		return "ALTER TABLE "+tablename+" MODIFY "+getFieldDefinition(v, tk, pk, use_autoinc, true, false);
	}

	public String getSafeFieldname( String fieldname ) {

		if( reservedWordAlt.contains(fieldname.toUpperCase() ) ) {
			fieldname = fieldname + FIELDNAME_PROTECTOR;
		}
		fieldname = fieldname.replace(" ", "_");
		return fieldname;
	}

	public String getFieldDefinition(ValueMetaInterface v, String tk, String pk, boolean use_autoinc, boolean add_fieldname, boolean add_cr )
	{
		StringBuffer retval = new StringBuffer();

		String fieldname = v.getName();
		int    length    = v.getLength();
		int    precision = v.getPrecision();

		Boolean mode = MonetDBDatabaseMeta.safeModeLocal.get();
		boolean safeMode = mode != null && mode.booleanValue();

		if (add_fieldname)
		{
			// protect the fieldname
			if( safeMode ) {
				fieldname = getSafeFieldname(fieldname);
			}

			retval.append(fieldname+" ");
		}

		int type         = v.getType();
		switch(type)
		{
		case ValueMetaInterface.TYPE_DATE   : retval.append("TIMESTAMP"); break;
		case ValueMetaInterface.TYPE_BOOLEAN:
			if (supportsBooleanDataType()) {
				retval.append("BOOLEAN");
			} else {
				retval.append("CHAR(1)");
			}
			break;
		case ValueMetaInterface.TYPE_NUMBER    :
		case ValueMetaInterface.TYPE_INTEGER   :
        case ValueMetaInterface.TYPE_BIGNUMBER :
			if (fieldname.equalsIgnoreCase(tk) || // Technical key
			    fieldname.equalsIgnoreCase(pk)    // Primary key
			    )
			{
				if (use_autoinc)
				{
					retval.append("SERIAL");
				}
				else
				{
					retval.append("BIGINT");
				}
			}
			else
			{
				// Integer values...
				if (precision==0)
				{
					if (length>9)
					{
						if (length<19) {
							// can hold signed values between -9223372036854775808 and 9223372036854775807
							// 18 significant digits
							retval.append("BIGINT");
						} else {
							retval.append("DECIMAL(").append(length).append(")");
						}
					}
					else if (type == ValueMetaInterface.TYPE_NUMBER )
					{
						retval.append("DOUBLE");
					}
					else
					{
						retval.append("BIGINT");
					}
				}
				// Floating point values...
				else
				{
					if (length>15)
					{
						retval.append("DECIMAL(").append(length);
						if (precision>0) retval.append(", ").append(precision);
						retval.append(")");
					}
					else
					{
						// A double-precision floating-point number is accurate to approximately 15 decimal places.
						// http://mysql.mirrors-r-us.net/doc/refman/5.1/en/numeric-type-overview.html
						retval.append("DOUBLE");
					}
				}
			}
			break;
		case ValueMetaInterface.TYPE_STRING:
			if (length>=DatabaseMeta.CLOB_LENGTH)
			{
				retval.append("CLOB");
			}
			else
			{
				retval.append("VARCHAR(");
				if (length>0)
				{
					retval.append(length);
				}
				else
				{
					if( safeMode ) {
						retval .append( DEFAULT_VARCHAR_LENGTH );
				}
			}
				retval.append(")");
			}
			break;
		default:
			retval.append(" UNKNOWN");
			break;
		}

		if (add_cr) retval.append(Const.CR);

		return retval.toString();
	}

    public String[] getUsedLibraries()
    {
        return new String[] { "monetdb-jdbc-2.1.jar", };
    }

	/**
	 * Returns the minimal SQL to launch in order to determine the layout of the resultset for a given database table
	 * @param tableName The name of the table to determine the layout for
	 * @return The SQL to launch.
	 */
    @Override
	public String getSQLQueryFields(String tableName)
	{
	    return "SELECT * FROM "+tableName+";";
  }

  @Override
  public boolean supportsResultSetMetadataRetrievalOnly() {
    return true;
  }

}


text:
cordova-plugin-wizpurchase
===========================

A cross-platform mobile application payment API for iOS IAP and Android Billing.

- PhoneGap Version : 3.3

-----
## Major API changes warning
***API changed since v1.x.x. Please be sure you target the right version. There are no API changes except on new major versions.
If your plugin dependency points directly to Github, make sure to have the right version by adding it at the end of the URL, e.g.:***
https://github.com/Wizcorp/cordova-plugin-wizpurchase#v1.2.0

-----

**NOTE:**
- **Not currently supporting subscriptions.**
- **Receipts on iOS use API ```appStoreReceiptURL``` available from iOS 7**

***A lot of work from the Android side of this plugin must be credited to @[poiuytrez](https://github.com/poiuytrez)'s [AndroidInAppBilling](https://github.com/poiuytrez/AndroidInAppBilling/) plugin. We re-used some plugin class code and all the utility classes, but replaced a lot of the API to be usable in a cross-platform manner with iOS. Many thanks goes to him for his hard work.***

## Install

### via CLI

	cordova plugin add https://github.com/Wizcorp/cordova-plugin-wizpurchase --variable BILLING_KEY="YOUR_BILLING_KEY"

### via config.xml

	<plugin name="cordova-plugin-wizpurchase" spec="2.2.0">
	    <variable name="BILLING_KEY" value="YOUR_BILLING_KEY" />
	</plugin>

### via Phonegap Build (PGB)

	<plugin name="cordova-plugin-wizpurchase" spec="2.2.0">
			<param name="BILLING_KEY" value="YOUR_BILLING_KEY" />
	</plugin>

You need to specify your billing key **only** if you need Android support.

## Setup

#### iOS

- In iTunes Connect create: your application, any items and an IAP test user (on the main screen see "Manage Users").

- Test on a real device (not simulator).

- Log out of any existing Apple iTunes accounts on the device before testing.

- Make sure your application has a version number (do not leave it blank).

#### Android

- Set `debuggable` to `false` and upload a signed version of you application to the Google Play Developer Console.

- Add items to the Google Play Developer Console.

- Upload your apk to Alpha or Beta environment.

- Add your list of test users (Google Group), in the same screen you should see a link ** *1 **

- ** *1 download the application from the link above [important!] **

- Be sure you are logged in to a Google Developer Account on your device.

- Be sure to use a real device (not emulator).

## Purchase Flow

![image](purchase_flow.png)

## Purchase object

Purchase objects contain product information that can be used for verification.

```
{
	platform: "ios" or "android",
	orderId: transaction identifier for iOS or order ID for Android,
	receipt: purchaseToken or ios receipt as String,
	productId: "sword001",
	packageName: "jp.wizcorp.game",
	purchaseTime: Android-specific, time the product was purchased in ms since the epoch (Jan 1, 1970),
	purchaseState: Android-specific, "0" (purchased), "1" (canceled) or "2" (refunded),
	json: Android-specific, original JSON purchase data,
	developerPayload: Android-specific, string specified by the developer in the purchase request,
	signature: Android-specific, signature of the purchase data signed with the private key of the developer
}
```

## JavaScript APIs

### getPendingPurchases(Function success, Function failure)

Get a list of purchases which have not been ended yet using ```finishPurchase```.

- *Return* success with an Array of zero or more ```Purchase``` objects.
- *Return* failure with error

Developers should check any returned items with server APIs and complete their purchase using ```finishPurchase```.

### restoreAllPurchases(Function success, Function failure)

Get a list of previous purchases of non-consumable and not yet finished purchases.

- *Return* success with an Array of zero or more ```Purchase``` objects.
- *Return* failure with error

Developers should check any returned items with server APIs. If any items that exist are consumables but have not been consumed, the developer should consume them using ```finishPurchase``` because it is likely that a previous purchase was not completed.

### makePurchase(String productId, Function success, Function failure)

Make a purchase given a product ID (Quantity is not settable with the API, it is always 1 to be cross-platform complete).

(ANDROID: A NON-CONSUMABLE CANNOT BE PURCHASED IF IT IS ALREADY OWNED [not-consumed], this applies to any product ID that has not been consumed with ```finishPurchase```).

** See security notes below **

- *Return* success with a ```Purchase``` Object
- *Return* failure with error

On success do a receipt verification (if server API exists) gift the user.

|  Android Verification API |
| --------- |:--------:| ------:|
|  URIs relative to *https://www.googleapis.com/androidpublisher/v1.1/applications*, unless otherwise note |
| **GET**  |
| / **[packageName]**/inapp/**[productId]**/purchases/**[token]** |
| Checks the purchase and consumption status of an inapp item. |

|  iOS Verification API |
| --------- |:--------:| ------:|
|  Base64 encode the receipt and create a JSON object as follows: `{ "receipt-data" : "receipt bytes here" }`
| **POST**  |
| https://buy.itunes.apple.com/verifyReceipt |
| JSON is returned. If the value of the `status` key is 0, this is a valid receipt. |

NOTE: Always verify your receipt for auto-renewable subscriptions first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.

### finishPurchase(String productId, Boolean isConsumable, Function success, Function failure)

Finish transaction of a purchase for given productId. Its associated product will be consumed if ```isConsumable``` is set to ```true```.

- *Return* success
- *Return* failure with error

### getProductDetails(String productId or Array of productIds, Function success, Function failure)

Get the details for a single productId or for an Array of productIds.

- *Return* success with Object containing country, currency code and key/value map of products
- *Return* failure with error

NB: Currently on Android the country code can not be guessed and as such, it is not returned.

```json
{
	"country": "GB",
	"currency": "GBP",
	"products": {
		"sword001": {
			"productId": "sword001",
			"name": "Sword of Truths",
			"description": "Very pointy sword. Sword knows if you are lying, so don't lie.",
			"price": "Formatted price of the item, including its currency sign.",
			"priceMicros": "Price in micro-units as an unformatted string, where 1,000,000 micro-units equal one unit of the currency."
		},
		"shield001": {
			"productId": "shield001",
			"name": "Shield of Peanuts",
			"description": "A shield made entirely of peanuts.",
			"price": "Formatted price of the item, including its currency sign.",
			"priceMicros": "Price in micro-units as an unformatted string, where 1,000,000 micro-units equal one unit of the currency."
		}
	}
}
```

or empty `{ }` if productIds was an empty array.

- *Return* failure with error as the only argument

### refreshReceipt(Function success, Function failure)

Refresh the receipt on iOS, do nothing on Android.

- *Return* success
- *Return* failure with error

### setApplicationUsername(String applicationUsername, Function success, Function failure)

On iOS, set the application username for all purchases following this call. More information [here](https://developer.apple.com/documentation/storekit/skmutablepayment/1506088-applicationusername).

Do nothing on Android.

- *Return* success
- *Return* failure with error

#### Security notes (Android)

*** You (the developer) should verify that the orderId is a unique value that you have not previously processed, and the developerPayload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server. ***

### Error Handling

Failure callbacks return an error as an integer. See the following error table:

| Code | Constant                    | Description                                                                                |
|-----:|:----------------------------|:-------------------------------------------------------------------------------------------------------|
|    1 | `UNKNOWN_ERROR`             |                                                                                |
|    2 | `ARGS_TYPE_MISMATCH`        |                                                                                |
|    3 | `ARGS_ARITY_MISMATCH`       |                                                                                |
|    4 | `IOS_VERSION_ERR`           |                                                                                |
|    5 | `INVALID_RECEIPT`           |                                                                                |
|    6 | `INVALID_TRANSACTION_STATE` |                                                                                |
|    7 | `PURCHASE_NOT_FOUND`        |                                                                                |
|    8 | `PURCHASE_NOT_PENDING`      |                                                                                |
|    9 | `REMOTE_EXCEPTION`          |                                                                                |
|   10 | `BAD_RESPONSE`              |                                                                                |
|   11 | `BAD_SIGNATURE`             |                                                                                |
|   12 | `SEND_INTENT_FAILED`        |                                                                                |
|   13 | `USER_CANCELLED`            | Indicates that the user cancelled a payment request                                                    |
|   14 | `INVALID_PURCHASE`          |                                                                                |
|   15 | `MISSING_TOKEN`             |                                                                                |
|   16 | `NO_SUBSCRIPTIONS`          |                                                                                |
|   17 | `INVALID_CONSUMPTION`       |                                                                                |
|   18 | `CANNOT_PURCHASE`           | Purchasing is not possible for the following reasons:
- purchase is being made on a simulator or emulator,
- the device has been identified as rooted |
|   19 | `UNKNOWN_PRODUCT_ID`        | Indicates that the requested product is not available or could not be found in the store               |
|   20 | `ALREADY_OWNED`             | [Android only] This item has already been bought. It cannot be bought again without consuming it first |
|   21 | `NOT_OWNED`                 |                                                                                |
|   22 | `INVALID_CLIENT`            | Indicates that the client is not allowed to perform the attempted action                               |
|   23 | `INVALID_PAYMENT`           | Indicates that one of the payment parameters was not recognized                                        |
|   24 | `UNAUTHORIZED`              | Indicates that the user is not allowed to authorise payments (e.g. parental lock)                      |
|   25 | `RECEIPT_REFRESH_FAILED`    |                                                                                |

======
Ref Links
======

### iOS

[http://docs.xamarin.com/guides/ios/application_fundamentals/in-app_purchasing/part_4_-_purchasing_non-consumable_products/](http://docs.xamarin.com/guides/ios/application_fundamentals/in-app_purchasing/part_4_-_purchasing_non-consumable_products/)

[https://github.com/Wizcorp/phonegap-plugin-inAppPurchaseManager/blob/v3.0/platforms/ios/HelloCordova/Plugins/InAppPurchaseManager/InAppPurchaseManager.m](https://github.com/Wizcorp/phonegap-plugin-inAppPurchaseManager/blob/v3.0/platforms/ios/HelloCordova/Plugins/InAppPurchaseManager/InAppPurchaseManager.m)

[http://stackoverflow.com/a/17734756/2206385](http://stackoverflow.com/a/17734756/2206385)

### Android

[http://developer.android.com/google/play/billing/api.html](http://developer.android.com/google/play/billing/api.html)

[http://developer.android.com/training/in-app-billing/purchase-iab-products.html](http://developer.android.com/training/in-app-billing/purchase-iab-products.html)

[https://github.com/poiuytrez/AndroidInAppBilling/blob/master/v3/src/android/com/smartmobilesoftware/util/IabHelper.java](https://github.com/poiuytrez/AndroidInAppBilling/blob/master/v3/src/android/com/smartmobilesoftware/util/IabHelper.java)

[https://github.com/poiuytrez/AndroidInAppBilling/blob/master/v3/src/android/com/smartmobilesoftware/inappbilling/InAppBillingPlugin.java](https://github.com/poiuytrez/AndroidInAppBilling/blob/master/v3/src/android/com/smartmobilesoftware/inappbilling/InAppBillingPlugin.java)

[https://developers.google.com/android-publisher/v1_1/](https://developers.google.com/android-publisher/v1_1/)


text:
module F00px
  module Connection
    def connection
      options = {
        :headers => {
          :accept => 'application/json',
          :user_agent => '500px gem'
        },
        :url => Config.url
      }
      Faraday.new(options) do |builder|
        builder.use F00px::Request, credentials
        builder.use F00px::Response::Json
        builder.adapter :net_http
      end
    rescue Exception => e
      puts "#{e.class.name}: #{e.message}"
    end
  end
end


text:
genie
=====

[![Build Status](https://travis-ci.org/teyosh/genie.png?branch=master)](https://travis-ci.org/teyosh/genie)

Genie is framework for [Express3.x](http://expressjs.com/) based to [Klass](https://github.com/ded/klass).

Installation
=====
### Get the CLI
  $ npm install genie-express -g

Quick Start
=====
### Create an app
  $ genie create my-app
  $ cd my-app $$ npm install genie-express

### Start your app
  $ node server.js

# Scaffold

  $ genie controller [name]
  $ genie model [name]
  $ genie service [name]
  $ genie factory [name]

Examples
=====
### Controller

```js
module.exports = function (app, config) {
  var ApplicationController = app.getController("Application", true);
  var IndexController = ApplicationController.extend(function(){
    this.routes = {
      "index" : "/"
    };
    this.addBeforeAction("action", function(res, req, next){
      var CheckFactory = app.getFactory("Check");
      CheckFactory.start(res, req, next);
    });
    this.addBeforeAction("get", function(res, req, next){
      var CheckFactory = app.getFactory("Check");
      CheckFactory.start(res, req, next);
    });
    this.addBeforeAction("get", function(res, req, next){
      var CheckService = app.getService("Check");
      CheckService.start(res, req, next);
    });
  }).methods({
    getIndex : function(req, res){
      res.render("index", {
        title : "Hello, Genie"
      });
    },
  });
  return IndexController;
}
```

### Model

```js
'use strict';
module.exports = function(app){
  var ApplicationModel = app.getModel('Application', true);
  var CheckModel = ApplicationModel.extend(function(){
    this.app = app;
    this.modelName = "Check";
    this.rooms = ['Apple', 'Orange', 'Grape'];
  }).methods({
    getRoom : function(id){
      console.log(this.rooms);
      return this.rooms[id];
    }
  });
  return CheckModel;
};
```

### Service

```js
'use strict';
module.exports = function(app){
  var ApplicationService = app.getService('Application', true);
  var CheckService = ApplicationService.extend(function(app){
    this.app = app;
    this.serviceName = "Check";
    this.config = this.Config();
    this.num = this.config.num;
  }).methods({
    start : function(req, res, next){
      this.supr();
      console.log("service: "+ this.num++);
      next();
    }
  });
  return CheckService;
};
```

### Factory

```js
'use strict';
module.exports = function(app){
  var ApplicationFactory = app.getFactory('Application', true);
  var CheckFactory = ApplicationFactory.extend(function(){
    this.factoryName = "Check";
    this.num = 0;
  }).methods({
    start : function(req, res, next){
      this.supr();
      console.log("factory: "+ this.num++);
      next();
    }
  });
  return CheckFactory;
};
```

### View

Uses [Twig](https://github.com/justjohn/twig.js) to render Template

```html
<div id="title">{% block content %}{% endblock %}</div>
```

``` html
{% extends "layout.twig" %}
{% block content %}
{{ title }}
{% endblock %}
```

### Routing

Routings are extract from method of controller.
Extract methods are GET, POST, PUT and DELETE.

#### get /index

```js
getIndex : function(req, res){
  res.render("index", {
    title : "Get index"
  });
}
```

#### post /create
```js
postCreate : function(req, res){
  res.render("index", {
    title : "Post create"
  });
}
```

Params are extract from property of controller.

#### get /test/member/:id

```js
// controllers/test/TestController.js

module.exports = function (app, config) {
  var ApplicationController = app.getController("Application", true);
  var TestController = ApplicationController.extend(function(){
    this.params = {
      "member" : [":id"]
    };
  }).methods({
    getMember : function(req, res){
      res.render("index", {
        title : "Genie is "+req.params.id
      });
    },
  });
  return TestController;
}

```

In the case of a different method?

```js
this.params = {
  "member" : {
    get : [":id"],
    post: [":test"]
  }
};

```

Routes change extract from property of controller.

### get /test/

```js
// controllers/test/TestController.js

module.exports = function (app, config) {
  var ApplicationController = app.getController("Application", true);
  var TestController = ApplicationController.extend(function(){
    this.routes = {
      "index": "/test/"
    };
  }).methods({
    getIndex : function(req, res){
      res.render("index", {
        title : "Genie is test"
      });
    },
  });
  return TestController;
}

```
### Service and Factory

Service will create an instance for each call.

```js
module.exports = function (app, config) {
  var ApplicationController = app.getController("Application", true);
  var TestController = ApplicationController.extend(function(){
    this.TestService = this.app.getService("Test");
  })
}
```

Factory will call the same instance.

```js
module.exports = function (app, config) {
  var ApplicationController = app.getController("Application", true);
  var TestController = ApplicationController.extend(function(){
    this.TestFactory = this.app.getFactory("Test");
  })
}
```


text:
package tech.aroma.client;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import tech.sirwellington.alchemy.test.junit.runners.*;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

@RunWith(AlchemyTestRunner.class)
public class AromaDoNothingClientTest
{

    @GenerateString
    private String title;

    @GenerateString
    private String body;

    @GenerateEnum
    private Priority priority;

    private AromaDoNothingClient instance;

    @Before
    public void setup()
    {
        instance = AromaDoNothingClient.Companion.getINSTANCE();
    }

    @Test
    public void begin() throws Exception
    {
        Aroma.Request request = instance.begin();
        assertThat(request, notNullValue());
    }

    @Test
    public void testSendMessage() throws Exception
    {
        instance.begin()
                .titled(title)
                .withBody(body, body)
                .withPriority(priority);
    }

}


text:
var static = require('node-static');
var http = require('http');
var file = new(static.Server)();

// cet objet là c'est pour que ca marche en local sur mon poste.
// C'est à adapter pour ta plateforme. Par exemple :
// var options = { hostname: 'computeengineondemand.appspot.com', port: 80, path: '/turn?username=41784574&key=4080218913&_=1384336940360', method: 'GET' };
var options = {
  host: "localhost",
  port: 3128,
  method: 'GET',
  path: "http://11.binomed-andshowtime-project-1.appspot.com/showtime/near?place=nantes&day=0&lang=fr&curenttime="+(new Date().getTime())+"&timezone=GMT+1&oe=UTF-8&ie=UTF-8&countryCode=FR&output=json",
  headers: {
    Host: "computeengineondemand.appspot.com"
  }
};

"http://11.binomed-andshowtime-project-1.appspot.com/"
        +"/showtime/near?place=nantes&day=0&lang=fr"
        +"&curenttime="+(new Date().getTime())
        +"&timezone=GMT+1"
        +"&oe=UTF-8&ie=UTF-8&countryCode=FR&output=json";

options = {
  hostname: '11.binomed-andshowtime-project-1.appspot.com',
  port: 80,
  path: "/showtime/near?place=nantes&day=0&lang=fr&curenttime="+(new Date().getTime())+"&timezone=GMT+1&oe=UTF-8&ie=UTF-8&countryCode=FR&output=json",
  method: 'GET'
};

var app = http.createServer(function (request, response) {
  console.log(request.url);
	if (request.method === 'GET' && request.url && request.url.indexOf('/search.json') != -1) {

      // c'est cette partie là qui t'intéresse :
      options.path = "/showtime/near?"+request.url.substr(13, request.url.length);
      console.log("Will Call : "+options.hostname+options.path);
      var req = http.request(options, function(res) {
        //res.setEncoding('utf8');
        var data = '';
        res.on('data', function(chunk) {
          data += chunk;
        });
        res.on('end', function(chunk) {
          response.writeHead(200, {'Content-Type': 'application/json'});
            response.end(data);
        });

      });

      req.on('error', function(e) {
        response.writeHead(500, {'Content-Type': 'text/plain'});
        response.end('ERROR: ' + e.message);
      });

      req.end();
  	} else {
		file.serve(request, response);
	}
}).listen(80);


text:
extern NSString * const NOTIFY_WEBIMAGELOADER_DOWNLOAD_DONE;
extern NSString * const NOTIFY_WEBIMAGELOADER_DOWNLOAD_ERROR;

@interface DCWebImageLoader : DCRevokableLoader

@property (nonatomic, copy) NSString *uid;
@property (nonatomic, copy) NSString *url;
@property (nonatomic, SAFE_ARC_PROP_STRONG) NSMutableData *downloadData;

@end


text:
package org.openqa.selenium.iphone;

import java.net.URL;

import org.openqa.selenium.Alert;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CommandExecutor;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.DriverCommand;
import org.openqa.selenium.remote.RemoteWebDriver;

/**
 * IPhoneDriver is a driver for running tests on Mobile Safari on the iPhone,
 * iPad and iPod Touch.
 *
 * The driver uses WebDriver's remote REST interface to communicate with the
 * iphone. The iphone (or iphone simulator) must be running the iWebDriver app.
 */
public class IPhoneDriver extends RemoteWebDriver implements TakesScreenshot {

  /**
   * This is the default port and URL for iWebDriver. Eventually it would
   * be nice to use DNS-SD to detect iWebDriver instances running non
   * locally or on non-default ports.
   */
  protected static final String DEFAULT_IWEBDRIVER_URL =
	  "http://localhost:3001/hub";

  /**
   * Create an IPhoneDriver that will use the given {@code executor} to
   * communicate with the iWebDriver app.
   *
   * @param executor The executor to use for communicating with the iPhone.
   */
  public IPhoneDriver(CommandExecutor executor) {
    super(executor, DesiredCapabilities.iphone());
  }

  /**
   * Create an IPhoneDriver connected to the remote address passed in.
   * @param remoteAddress The full URL of the remote client (device or
   *                      simulator).
   * @throws Exception
   * @see #IPhoneDriver(String)
   */
  public IPhoneDriver(URL remoteAddress) throws Exception {
    super(remoteAddress, DesiredCapabilities.iphone());
  }

  /**
   * Create an IPhoneDriver connected to the remote address passed in.
   * @param remoteAddress The full URL of the remote client running iWebDriver.
   * @throws Exception
   * @see #IPhoneDriver(URL)
   */
  public IPhoneDriver(String remoteAddress) throws Exception {
    this(new URL(remoteAddress));
  }

  /**
   * Create an IPhoneDriver connected to an iphone simulator running on the
   * local machine.
   *
   * @throws Exception
   */
  public IPhoneDriver() throws Exception {
    this(DEFAULT_IWEBDRIVER_URL);
  }

  @Override
  public void close() {
    throw new UnsupportedOperationException("Not yet implemented");
  }

  @Override
  public TargetLocator switchTo() {
    return new IPhoneTargetLocator();
  }

  private class IPhoneTargetLocator implements TargetLocator {

    public WebDriver frame(int frameIndex) {
      // is this even possible to do on the iphone?
      throw new UnsupportedOperationException(
    		  "Frame switching is not supported on the iPhone");
    }

    public WebDriver frame(String frameName) {
      // is this even possible to do on the iphone?
      throw new UnsupportedOperationException(
    		  "Frame switching is not supported on the iPhone");
    }

    public WebDriver frame(WebElement frameElement) {
      // is this even possible to do on the iphone?
      throw new UnsupportedOperationException(
    		  "Frame switching is not supported on the iPhone");
    }

    public WebDriver window(String windowName) {
      throw new UnsupportedOperationException(
    		  "Window switching is unsupported on the iPhone");
    }

    public WebDriver defaultContent() {
      // The iphone driver does not support frame switching, so we're always
      // focused on the default content.
      return IPhoneDriver.this;
    }

    public WebElement activeElement() {
      return (WebElement) executeScript(
    		  "return document.activeElement || document.body;");
    }

    public Alert alert() {
      throw new UnsupportedOperationException("alert()");
    }
  }

  public <X> X getScreenshotAs(OutputType<X> target) {
    byte[] base64Png = (byte[]) execute(DriverCommand.SCREENSHOT).getValue();
    String png = new String(base64Png);
	  // ... and convert it.
    return target.convertFromBase64Png(png);
  }
}