public class ContainerExistException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public ContainerExistException(String message) {
        super(message);
    }
} public class ContainerNotEmptyException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public ContainerNotEmptyException(String message) {
        super(message);
    }

} public class ContainerNotFoundException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = -4662162990209727136L;
    
    public ContainerNotFoundException() {
        super(null);
    }
    public ContainerNotFoundException(String message) {
        super(message);
    }
} public class ObjectExistException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public ObjectExistException(String message) {
        super(message);
    }

} public class ObjectNotFoundException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = -2995680181164449256L;

    public ObjectNotFoundException() {
        super(null);
    }

    public ObjectNotFoundException(String message) {
        super(message);
    }
} @SuppressWarnings("deprecation")
public class OioException extends SdsException {

    /**
     * 
     */
    private static final long serialVersionUID = 3270900242235005338L;

    public OioException(String message) {
        super(message);
    }

    public OioException(String message, Throwable t) {
        super(message, t);
    }
} public class OioSystemException extends OioException {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public OioSystemException(String message) {
        super(message);
    }

    public OioSystemException(String message, Throwable t) {
        super(message, t);
    }
} public class ContainerInfo {

    private String name;
    private String account;
    private Long ctime;
    private Long init;
    private Long usage;
    private Long version;
    private String id;
    private String ns;
    private String type;
    private String user;
    private String schemavers;
    private String versionMainAdmin;
    private String versionMainAliases;
    private String versionMainChunks;
    private String versionMainContents;
    private String versionMainProperties;

    public ContainerInfo(String name) {
        this.name = name;
    }

    public String name() {
        return name;
    }

    public ContainerInfo name(String name) {
        this.name = name;
        return this;
    }

    public String account() {
        return account;
    }

    public ContainerInfo account(String account) {
        this.account = account;
        return this;
    }

    public Long ctime() {
        return ctime;
    }

    public ContainerInfo ctime(Long ctime) {
        this.ctime = ctime;
        return this;
    }

    public Long init() {
        return init;
    }

    public ContainerInfo init(Long init) {
        this.init = init;
        return this;
    }

    public Long usage() {
        return usage;
    }

    public ContainerInfo usage(Long usage) {
        this.usage = usage;
        return this;
    }

    public Long version() {
        return version;
    }

    public ContainerInfo version(Long version) {
        this.version = version;
        return this;
    }

    public String id() {
        return id;
    }

    public ContainerInfo id(String id) {
        this.id = id;
        return this;
    }

    public String ns() {
        return ns;
    }

    public ContainerInfo ns(String ns) {
        this.ns = ns;
        return this;
    }

    public String type() {
        return type;
    }

    public ContainerInfo type(String type) {
        this.type = type;
        return this;
    }

    public String user() {
        return user;
    }

    public ContainerInfo user(String user) {
        this.user = user;
        return this;
    }

    public String schemavers() {
        return schemavers;
    }

    public ContainerInfo schemavers(String schemavers) {
        this.schemavers = schemavers;
        return this;
    }

    public String versionMainAdmin() {
        return versionMainAdmin;
    }

    public ContainerInfo versionMainAdmin(String versionMainAdmin) {
        this.versionMainAdmin = versionMainAdmin;
        return this;
    }

    public String versionMainAliases() {
        return versionMainAliases;
    }

    public ContainerInfo versionMainAliases(String versionMainAliases) {
        this.versionMainAliases = versionMainAliases;
        return this;
    }

    public String versionMainChunks() {
        return versionMainChunks;
    }

    public ContainerInfo versionMainChunks(String versionMainChunks) {
        this.versionMainChunks = versionMainChunks;
        return this;
    }

    public String versionMainContents() {
        return versionMainContents;
    }

    public ContainerInfo versionMainContents(String versionMainContents) {
        this.versionMainContents = versionMainContents;
        return this;
    }

    public String versionMainProperties() {
        return versionMainProperties;
    }

    public ContainerInfo versionMainProperties(
            String versionMainProperties) {
        this.versionMainProperties = versionMainProperties;
        return this;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .omitNullValues()
                .add("name", name)
                .add("account", account)
                .add("m2-ctime", ctime)
                .add("m2-init", init)
                .add("m2-usage", usage)
                .add("id", id)
                .add("ns", ns)
                .add("type", type)
                .add("user-name", user)
                .toString();
    }
} public class ListOptions {

    private int limit = -1;
    private String delimiter;
    private String prefix;
    private String marker;

    public ListOptions() {
    }

    public Integer limit() {
        return limit;
    }

    public ListOptions limit(int limit) {
        this.limit = limit;
        return this;
    }

    public String delimiter() {
        return delimiter;
    }

    public ListOptions delimiter(String delimiter) {
        this.delimiter = delimiter;
        return this;
    }

    public String prefix() {
        return prefix;
    }

    public ListOptions prefix(String prefix) {
        this.prefix = prefix;
        return this;
    }

    public String marker() {
        return marker;
    }

    public ListOptions marker(String marker) {
        this.marker = marker;
        return this;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("prefix", prefix)
                .add("delimiter", delimiter)
                .add("marker", marker)
                .add("limit", limit)
                .toString();
    }
} public class NamespaceInfo {

    private String ns;
    private Long chunksize;
    private Map<String, String> options;
    @SerializedName("storage_policy")
    private Map<String, String> storagePolicies;
    @SerializedName("storage_class")
    private Map<String, String> storageClasses;
    @SerializedName("data_security")
    private Map<String, String> dataSecurities;
    @SerializedName("data_treatments")
    private Map<String, String> dataTreatments;

    public NamespaceInfo() {
    }

    public String ns() {
        return ns;
    }

    public NamespaceInfo ns(String ns) {
        this.ns = ns;
        return this;
    }

    public Long chunksize() {
        return chunksize;
    }

    public NamespaceInfo chunksize(Long chunksize) {
        this.chunksize = chunksize;
        return this;
    }

    public Map<String, String> options() {
        return options;
    }

    public NamespaceInfo options(Map<String, String> options) {
        this.options = options;
        return this;
    }

    public Map<String, String> storagePolicies() {
        return storagePolicies;
    }

    public NamespaceInfo storagePolicies(Map<String, String> storagePolicies) {
        this.storagePolicies = storagePolicies;
        return this;
    }

    public Map<String, String> storageClasses() {
        return storageClasses;
    }

    public NamespaceInfo storageClasses(Map<String, String> storageClasses) {
        this.storageClasses = storageClasses;
        return this;
    }

    public Map<String, String> dataSecurities() {
        return dataSecurities;
    }

    public NamespaceInfo dataSecurities(Map<String, String> dataSecurities) {
        this.dataSecurities = dataSecurities;
        return this;
    }

    public Map<String, String> dataTreatments() {
        return dataTreatments;
    }

    public NamespaceInfo dataTreatments(Map<String, String> dataTreatments) {
        this.dataTreatments = dataTreatments;
        return this;
    }

} public class ObjectCreationOptions {

    private Long version;
    private Map<String, String> properties;
    private String policy;
    private String mimeType;
    private boolean simulateVersioning = false;

    public Long version() {
        return version;
    }

    public ObjectCreationOptions version(Long version) {
        this.version = version;
        return this;
    }

    public Map<String, String> properties() {
        return properties;
    }

    public ObjectCreationOptions properties(Map<String, String> properties) {
        this.properties = properties;
        return this;
    }

    public String policy() {
        return policy;
    }

    public ObjectCreationOptions policy(String policy) {
        this.policy = policy;
        return this;
    }

    public String mimeType() {
        return mimeType;
    }

    public ObjectCreationOptions mimeType(String mimeType) {
        this.mimeType = mimeType;
        return this;
    }

    public boolean simulateVersioning() {
        return simulateVersioning;
    }

    public ObjectCreationOptions simulateVersioning(boolean simulateVersioning) {
        this.simulateVersioning = simulateVersioning;
        return this;
    }

} public class ObjectDeletionOptions {

    private Long version;
    private boolean simulateVersioning = false;
    private boolean deleteMarker = false;

    public Long version() {
        return version;
    }

    public ObjectDeletionOptions version(Long version) {
        this.version = version;
        return this;
    }

    public boolean simulateVersioning() {
        return simulateVersioning;
    }

    public ObjectDeletionOptions simulateVersioning(boolean simulateVersioning) {
        this.simulateVersioning = simulateVersioning;
        return this;
    }

    public boolean deleteMarker() {
        return deleteMarker;
    }

    public ObjectDeletionOptions deleteMarker(boolean deleteMarker) {
        this.deleteMarker = deleteMarker;
        return this;
    }

} public class ObjectInfo {

    private OioUrl url;
    private String oid;
    private Long ctime;
    private Boolean deleted = false;
    private String policy;
    private String hash;
    private String hashMethod;
    private String chunkMethod;
    private Long size;
    private Long version;
    private String mimeType;
    private Map<String, String> properties;
    private List<ChunkInfo> chunks;
    private ECInfo ecinfo;
    private RequestContext reqCtx;

    private transient Map<Integer, List<ChunkInfo>> sortedChunks;

    private static final Comparator<ChunkInfo> comparator = new Comparator<ChunkInfo>() {

        @Override
        public int compare(ChunkInfo c1, ChunkInfo c2) {
            return c1.pos()
                    .compare(c2.pos());
        }
    };

    public ObjectInfo() {
        // TODO: content hash
        this.properties = new HashMap<String, String>();
        this.hash = Hash.md5()
                .hashBytes("".getBytes(OIO_CHARSET))
                .toString();
    }

    public List<ChunkInfo> chunks() {
        return chunks;
    }

    public Map<Integer, List<ChunkInfo>> sortedChunks() {
        return sortedChunks;
    }

    public ObjectInfo chunks(List<ChunkInfo> chunks) {
        this.sortedChunks = sortChunks(chunks);
        this.chunks = chunks;
        return this;
    }

    public ObjectInfo size(Long size) {
        this.size = size;
        return this;
    }

    public ObjectInfo hash(String hash) {
        this.hash = hash;
        return this;
    }

    public ObjectInfo url(OioUrl url) {
        this.url = url;
        return this;
    }

    public OioUrl url() {
        return url;
    }

    public String oid() {
        return oid;
    }

    public ObjectInfo oid(String oid) {
        this.oid = oid;
        return this;
    }

    public String hash() {
        return hash;
    }

    public Long size() {
        return size;
    }

    public String policy() {
        return policy;
    }

    public ObjectInfo policy(String policy) {
        this.policy = policy;
        return this;
    }

    public boolean deleted() {
        return deleted;
    }

    public Long ctime() {
        return ctime;
    }

    public ObjectInfo ctime(Long ctime) {
        this.ctime = ctime;
        return this;
    }

    public String hashMethod() {
        return hashMethod;
    }

    public ObjectInfo hashMethod(String hashMethod) {
        this.hashMethod = hashMethod;
        return this;
    }

    public String chunkMethod() {
        return chunkMethod;
    }

    public ObjectInfo chunkMethod(String chunkMethod) {
        this.chunkMethod = chunkMethod;
        this.ecinfo = ECInfo.fromString(chunkMethod);
        return this;
    }

    public Long version() {
        return version;
    }

    public ObjectInfo version(Long version) {
        this.version = version;
        return this;
    }

    @Deprecated
    public String mtype() {
        return mimeType();
    }

    @Deprecated
    public ObjectInfo mtype(String mimeType) {
        return mimeType(mimeType);
    }

    public String mimeType() {
        return mimeType;
    }

    public ObjectInfo mimeType(String mimeType) {
        this.mimeType = mimeType;
        return this;
    }

    public Integer nbchunks() {
        return isEC() ? chunks.size() : sortedChunks.size();
    }

    public Long chunksize(Integer pos) {
        return sortedChunks.get(pos).get(0).size();
    }

    public Map<String, String> properties() {
        return properties;
    }

    public ObjectInfo properties(Map<String, String> properties) {
        this.properties = properties;
        return this;
    }

    public ECInfo ecinfo(){
    	return ecinfo;
    }

    public boolean isEC(){
    	return null != ecinfo;
    }

    public long metachunksize(int pos) {
        if (!isEC())
            return -1;
        long maxmcsize = ecinfo.k() * sortedChunks.get(pos).get(0).size();
        long remaining = size - (pos * maxmcsize);
        return Math.min(maxmcsize, remaining);
    }

    /**
     * @return a string suitable to be sent as {@code CHUNK_META_FULL_PATH} header value.
     */
    public String fullpath() {
        if (this.url.account() == null || this.url.account().isEmpty()
                || this.url.container() == null || this.url.container().isEmpty()
                || this.url.object() == null || this.url.object().isEmpty()
                || this.version() == null || this.version() == 0
                || this.oid() == null || this.oid().isEmpty()) {
            throw new IllegalArgumentException("Can't encode fullpath");
        }
        StringBuilder sb = new StringBuilder();
        sb.append(Strings.quote(this.url.account()));
        sb.append('/');
        sb.append(Strings.quote(this.url.container()));
        sb.append('/');
        sb.append(Strings.quote(this.url.object()));
        sb.append('/');
        sb.append(Strings.quote(this.version()));
        sb.append('/');
        sb.append(Strings.quote(this.oid()));
        return sb.toString();
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .omitNullValues()
                .add("url", url)
                .add("ctime", ctime)
                .add("mime-type", mimeType)
                .add("deleted", deleted)
                .add("policy", policy)
                .add("hash", hash)
                .add("hash-method", hashMethod)
                .add("chunk-method", chunkMethod)
                .add("size", size)
                .add("version", version)
                .add("props", properties)
                .add("chunks", chunks)
                .toString();
    }

    public RequestContext requestContext() {
        return this.reqCtx;
    }

    /**
     * Set the context of the request that lead to this object's creation.
     *
     * @param reqCtx
     *            the request context
     * @return {@code this}
     */
    public ObjectInfo withRequestContext(RequestContext reqCtx) {
        this.reqCtx = reqCtx;
        return this;
    }

    /* -- INTERNAL -- */

    private Map<Integer, List<ChunkInfo>> sortChunks(
            List<ChunkInfo> chunks) {

        Map<Integer, List<ChunkInfo>> res = new HashMap<Integer, List<ChunkInfo>>();
        for (ChunkInfo ci : chunks) {
            List<ChunkInfo> l = res.get(ci.pos().meta());
            if (null == l) {
                l = new ArrayList<ChunkInfo>();
                res.put(ci.pos().meta(), l);
            }
            l.add(ci);
        }
        for (List<ChunkInfo> l : res.values())
            Collections.sort(l, comparator);

        return res;
    }

} public class ObjectList {

    private List<ObjectView> objects;
    private List<String> prefixes;
    private ListOptions listOptions;
    private boolean truncated;
    private String nextMarker;

    /**
     * 
     */
    public ObjectList() {
    }

    /**
     * List of {@link ObjectView} found in the container
     * 
     * @return a list of {@link ObjectView}
     */
    public List<ObjectView> objects() {
        return objects;
    }

    /**
     * Specifies the listing objects
     *
     * @param objects
     *            the value to set
     * @return this
     */
    public ObjectList objects(List<ObjectView> objects) {
        this.objects = objects;
        return this;
    }

    /**
     * Returns {@code true} if this listing does not contains all objects
     * matching the specified {@code ListOptions}, {@code false} otherwise
     * 
     * @return {@code true} if this listing does not contains all objects
     *         matching the specified {@code ListOptions}, {@code false}
     *         otherwise
     */
    public boolean truncated() {
        return truncated;
    }

    /**
     * Returns the prefixes
     * 
     * @return the prefixes
     */
    public List<String> prefixes() {
        return prefixes;
    }

    /**
     * Returns the options
     * 
     * @return the options
     */
    public ListOptions listOptions() {
        return listOptions;
    }

    /**
     * When a listing is {@link #truncated()}, to get the rest of the list, you
     * have to run the request again with a marker. This method returns this
     * marker (usually the last element of the previous listing).
     *
     * @return the {@link String} to use as {@link ListOptions#marker(String)}
     *         input to get the next page of results
     * @since 1.0.0
     */
    public String nextMarker() {
        return this.nextMarker;
    }

    /**
     * Specifies the listing prefixes
     * 
     * @param prefixes
     *            the value to set
     * @return this
     */
    public ObjectList prefixes(List<String> prefixes) {
        this.prefixes = prefixes;
        return this;
    }

    /**
     * Specifies the listing options
     * 
     * @param listOptions
     *            the value to set
     * @return this
     */
    public ObjectList listOptions(ListOptions listOptions) {
        this.listOptions = listOptions;
        return this;
    }

    /**
     * Specify the next marker.
     *
     * @param nextMarker
     *            the value to set
     * @return this
     * @since 1.0.0
     */
    public ObjectList nextMarker(String nextMarker) {
        this.nextMarker = nextMarker;
        return this;
    }

    /**
     * Specifies if the listing is truncated
     * 
     * @param truncated
     *            the value to set
     * @return this
     */
    public ObjectList truncated(boolean truncated) {
        this.truncated = truncated;
        return this;
    }

    /**
     * Representation of an object inside a container.
     * 
     * Here is a description of all fields meaning.
     * <ul>
     * <li>Name: the name of the object</li>
     * <li>Version: the current object version</li>
     * <li>Creation time: Timestamp where the object was created</li>
     * <li>System metadata: Meta informations about the object</li>
     * <li>deleted: {@code true} if the object is deleted, {@code false}
     * otherwise</li>
     * <li>policy: the storage policy used to store the object</li>
     * <li>hash: the object data md5sum</li>
     * <li>size: the total size of the object</li>
     * </ul>
     */
    public static class ObjectView {

        private String name;
        private String ver;
        private String ctime;
        // @SerializedName("system_metadata")
        private String sysmd;
        private Boolean deleted;
        private String policy;
        private String hash;
        private Long size;

        public ObjectView() {
        }

        /**
         * Returns the name of the object
         * 
         * @return the name of the object
         */
        public String name() {
            return name;
        }

        /**
         * Specifies the name of the object
         * 
         * @param name
         *            the value to set
         * @return this
         */
        public ObjectView name(String name) {
            this.name = name;
            return this;
        }

        /**
         * Returns the object version
         * 
         * @return the object version
         */
        public String version() {
            return ver;
        }

        /**
         * Specifies the object version
         * 
         * @param version
         *            the version to set
         * @return this
         */
        public ObjectView version(String version) {
            this.ver = version;
            return this;
        }

        /**
         * Returns the object creation time
         * 
         * @return the object creation time
         */
        public String ctime() {
            return ctime;
        }

        /**
         * Specifies the object creation time
         * 
         * @param ctime
         *            the value to set
         * @return this
         */
        public ObjectView ctime(String ctime) {
            this.ctime = ctime;
            return this;
        }

        /**
         * Returns the system metadata
         * 
         * @return the system metadata
         */
        public String sysmd() {
            return sysmd;
        }

        /**
         * Specifies the object system metadata
         * 
         * @param sysmd
         *            the metadata to set
         * @return this
         */
        public ObjectView sysmd(String sysmd) {
            this.sysmd = sysmd;
            return this;
        }

        /**
         * Returns {@code true} if the object is deleted, {@code false}
         * otherwise
         * 
         * @return {@code true} if the object is deleted, {@code false}
         *         otherwise
         */
        public Boolean deleted() {
            return deleted;
        }

        /**
         * Specifies if content is deleted or not
         * 
         * @param deleted
         *            the value to set
         * @return this
         */
        public ObjectView deleted(Boolean deleted) {
            this.deleted = deleted;
            return this;
        }

        /**
         * Returns the policy
         * 
         * @return the policy
         */
        public String policy() {
            return policy;
        }

        /**
         * Specifies the policy
         * 
         * @param policy
         *            the policy to set
         * @return this
         */
        public ObjectView policy(String policy) {
            this.policy = policy;
            return this;
        }

        /**
         * Returns the hash
         * 
         * @return the hash
         */
        public String hash() {
            return hash;
        }

        /**
         * Specifies the hash
         * 
         * @param hash
         *            the hash to set
         * @return this
         */
        public ObjectView hash(String hash) {
            this.hash = hash;
            return this;
        }

        /**
         * Returns the size
         * 
         * @return the size
         */
        public Long size() {
            return size;
        }

        /**
         * Specifies the size
         * 
         * @param size
         *            the size to set
         * @return this
         */
        public ObjectView size(Long size) {
            this.size = size;
            return this;
        }

    }
} public class OioUrl {

    private static final byte[] BACK_ZERO = { '\0' };

    private String ns;
    private String account;
    private String container;
    private String cid;
    private String object;

    private OioUrl(String ns, String account, String container, String cid,
            String object) {
        this.ns = ns;
        this.account = account;
        this.container = container;
        this.cid = cid;
        this.object = object;
    }
    
    
    
    public static OioUrl url(String account, String container) {
        return url(account, container, null);
    }

    public static OioUrl url(String account, String container,
            String object) {
        checkArgument(!nullOrEmpty(account),
                "account cannot be null or empty");
        checkArgument(!nullOrEmpty(container),
                "container cannot be null or empty");
        return new OioUrl(null,
                account,
                container,
                cid(account, container),
                object);
    }
    
    public static OioUrl url(String ns, String account, String container,
            String object) {
        checkArgument(!nullOrEmpty(account),
                "account cannot be null or empty");
        checkArgument(!nullOrEmpty(container),
                "container cannot be null or empty");
        return new OioUrl(ns, 
                account,
                container,
                cid(account, container),
                object);
    }

    public String namespace() {
        return ns;
    }

    public OioUrl namespace(String namespace) {
        this.ns = namespace;
        return this;
    }

    public String account() {
        return account;
    }

    public OioUrl account(String account) {
        this.account = account;
        return this;
    }

    public String container() {
        return container;
    }

    public OioUrl container(String container) {
        this.container = container;
        return this;
    }

    public String object() {
        return object;
    }

    public OioUrl object(String object) {
        this.object = object;
        return this;
    }

    public String cid() {
        return cid;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .omitNullValues()
                .add("namespace", ns)
                .add("account", account)
                .add("container", container)
                .add("object", object)
                .toString();
    }

    /**
     * Generates the container id from the specified account and container name
     * 
     * @param account
     *            the name of the account
     * @param container
     *            the name of the container
     * @return the generated id
     */
    public static String cid(String account, String container) {
        return Hash.sha256()
                .putBytes(account.getBytes(OIO_CHARSET))
                .putBytes(BACK_ZERO)
                .putBytes(container.getBytes(OIO_CHARSET))
                .hash().toString();
    }

} public class Range {

    private static final Pattern RANGE_PATTERN = Pattern
            .compile("^([\\d]+)?-([\\d]+)?$");

    private long from = 0;
    private long to = -1;

    private Range(long from, long to) {
        this.from = from;
        this.to = to;
    }

    public static Range upTo(long to) {
        checkArgument(0 < to);
        return new Range(0, to);
    }

    public static Range from(long from) {
        checkArgument(0 <= from);
        return new Range(from, -1);
    }

    public static Range between(long from, long to) {
        checkArgument(from >= 0 && to > 0 && to >= from,
                "Invalid range");
        return new Range(from, to);
    }

    public static Range parse(String str) {
        Matcher m = RANGE_PATTERN.matcher(str);
        checkArgument(m.matches());
        if (null == m.group(1)) {
            checkArgument(null != m.group(2), "useless range");
            return upTo(parseInt(m.group(2)));
        }
        return (null == m.group(2)) ? from(parseInt(m.group(1)))
                : between(parseInt(m.group(1)), parseInt(m.group(2)));
    }

    public long from() {
        return from;
    }

    public long to() {
        return to;
    }

    public String headerValue() {
        return to < 0
                ? format("bytes=%d-", from)
                : format("bytes=%d-%d", from, to);
    }

    public String rangeValue() {
        return to < 0
                ? format("%d-", from)
                : format("%d-%d", from, to);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("from", from)
                .add("to", to)
                .toString();
    }
}
import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import io.openio.sds.exceptions.ContainerExistException;
import io.openio.sds.exceptions.ContainerNotEmptyException;
import io.openio.sds.exceptions.ContainerNotFoundException;
import io.openio.sds.exceptions.ObjectExistException;
import io.openio.sds.exceptions.ObjectNotFoundException;
import io.openio.sds.exceptions.OioException;
import io.openio.sds.exceptions.OioSystemException;
import io.openio.sds.models.ContainerInfo;
import io.openio.sds.models.ListOptions;
import io.openio.sds.models.NamespaceInfo;
import io.openio.sds.models.ObjectCreationOptions;
import io.openio.sds.models.ObjectDeletionOptions;
import io.openio.sds.models.ObjectInfo;
import io.openio.sds.models.ObjectList;
import io.openio.sds.models.OioUrl;
import io.openio.sds.models.Range;
package io.openio.sds;



public interface AdvancedClient extends Client {

    /**
     * Get OpenIO-SDS namespace configuration.
     *
     * @param reqCtx
     *            Common parameters to all requests
     *
     * @return the namespace configuration
     * @throws OioSystemException
     *             if any error occurs during request execution
     */
    public NamespaceInfo getNamespaceInfo(RequestContext reqCtx) throws OioException;

    /**
     * Create a container using the specified {@link OioUrl}. OioUrl objects are
     * built by using {@link OioUrl#url(String, String)} method, then you have
     * to specify the name of the account to use and the name of the future
     * container.
     * <p>
     * The container is available when the returned future is completed.
     *
     * @param url
     *            the URL of the container
     * @param reqCtx
     *            common parameters to all requests
     * @return a {@code ContainerInfo} with information about the created
     *         container
     * @throws ContainerExistException
     *             if the specified container is alreay present
     * @throws OioSystemException
     *             if any error occurs during request execution
     */
    public ContainerInfo createContainer(OioUrl url, RequestContext reqCtx) throws OioException;

    /**
     * Create a container using the specified {@link OioUrl}. OioUrl objects are
     * built by using {@link OioUrl#url(String, String)} method, then you have
     * to specify the name of the account to use and the name of the future
     * container.
     * <p>
     * The container is available when the returned future is completed.
     *
     * @param url
     *            the URL of the container
     * @param properties
     *            the user properties to set to the container.
     * @param reqCtx
     *            common parameters to all requests
     * @return a {@code ContainerInfo} with information about the created
     *         container
     * @throws ContainerExistException
     *             if the specified container is alreay present
     * @throws OioSystemException
     *             if any error occurs during request execution
     */
    public ContainerInfo createContainer(OioUrl url,
            Map<String, String> properties, RequestContext reqCtx)
            throws OioException;

    /**
     * Create a container using the specified {@link OioUrl}. OioUrl objects are
     * built by using {@link OioUrl#url(String, String)} method, then you have
     * to specify the name of the account to use and the name of the future
     * container.
     * <p>
     * The container is available when the returned future is completed.
     *
     * @param url
     *            the URL of the container
     * @param properties
     *            the user properties to set to the container.
     * @param system
     *            the system properties to set to the container.
     * @param reqCtx
     *            common parameters to all requests
     * @return a {@code ContainerInfo} with information about the created
     *         container
     * @throws ContainerExistException
     *             if the specified container is alreay present
     * @throws OioSystemException
     *             if any error occurs during request execution
     */
    public ContainerInfo createContainer(OioUrl url,
            Map<String, String> properties, Map<String, String> system,
            RequestContext reqCtx) throws OioException;

    /**
     * Return information about the specified container.
     *
     * @param url
     *            the URL of the container
     * @param reqCtx
     *            common parameters to all requests
     * @return a {@code ContainerInfo} with information about the created
     *         container
     * @throws ContainerNotFoundException
     *             if the specified container doesn't exist
     *
     * @throws OioSystemException
     *             if any error occurs during request execution
     */
    public ContainerInfo getContainerInfo(OioUrl url, RequestContext reqCtx) throws OioException;

    /**
     * List objects available in the specified container.
     *
     * @param url
     *            the url of the container
     * @param listOptions
     *            the listing option
     * @param reqCtx
     *            common parameters to all requests
     *
     * @return the ObjectList
     * @throws ContainerNotFoundException
     *             if the specified container doesn't exist
     * @throws OioSystemException
     *             if any error occurs during request execution
     * @since 1.0.0
     */
    public ObjectList listObjects(OioUrl url, final ListOptions listOptions, RequestContext reqCtx)