All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xerox.amazonws.simpledb.Domain Maven / Gradle / Ivy

//
// typica - A client library for Amazon Web Services
// Copyright (C) 2007 Xerox Corporation
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package com.xerox.amazonws.simpledb;

import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.JAXBException;
import org.xml.sax.SAXException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.HttpException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpGet;

import com.xerox.amazonws.common.AWSException;
import com.xerox.amazonws.common.AWSQueryConnection;
import com.xerox.amazonws.common.ListResult;
import com.xerox.amazonws.common.Result;
import com.xerox.amazonws.typica.sdb.jaxb.Attribute;
import com.xerox.amazonws.typica.sdb.jaxb.BatchPutAttributesResponse;
import com.xerox.amazonws.typica.sdb.jaxb.DeleteAttributesResponse;
import com.xerox.amazonws.typica.sdb.jaxb.DomainMetadataResponse;
import com.xerox.amazonws.typica.sdb.jaxb.GetAttributesResponse;
import com.xerox.amazonws.typica.sdb.jaxb.PutAttributesResponse;
import com.xerox.amazonws.typica.sdb.jaxb.SelectResponse;

/**
 * This class provides an interface with the Amazon SDB service. It provides methods for
 * listing and deleting items.
 *
 * @author D. Kavanagh
 * @author [email protected]
 */
public class Domain {

    private static Log logger = LogFactory.getLog(Domain.class);

	private AWSQueryConnection connection;	// connection delegate

	private String domainName;
	private ItemCache cache;

    protected Domain(String domainName, AWSQueryConnection connection) throws SDBException {
		this.domainName = domainName;
		this.connection = connection;
    }

	/**
	 * Returns connection object, so connection params can be tweaked
	 */
	public AWSQueryConnection getConnectionDelegate() {
		return connection;
	}

	/**
	 * Gets the name of the domain represented by this object.
	 *
     * @return the name of the domain
	 */
	public String getName() {
		return domainName;
	}

	/**
	 * Returns information about the domain.
	 *
     * @return the object containing metadata about this domain
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult getMetadata() throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		HttpGet method = new HttpGet();
		DomainMetadataResponse response =
					makeRequestInt(method, "DomainMetadata", params, DomainMetadataResponse.class);
		com.xerox.amazonws.typica.sdb.jaxb.DomainMetadataResult result =
								response.getDomainMetadataResult();
		return new SDBResult(response.getResponseMetadata().getRequestId(),
											response.getResponseMetadata().getBoxUsage(),
				new DomainMetadata(Integer.parseInt(result.getItemCount()),
					Integer.parseInt(result.getAttributeValueCount()),
					Integer.parseInt(result.getAttributeNameCount()),
					Long.parseLong(result.getItemNamesSizeBytes()),
					Long.parseLong(result.getAttributeValuesSizeBytes()),
					Long.parseLong(result.getAttributeNamesSizeBytes()),
					new Date(Long.parseLong(result.getTimestamp())*1000)));
	}

	/**
	 * Adds an item.
	 *
	 * @param item the item to add to this domain
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult addItem(Item item) throws SDBException {
		return addItem(item.getIdentifier(), item.getAttributes(), null);
	}

	/**
	 * Adds an item. This method also works to add attributes to an existing item.
	 *
	 * @param identifier the name of the item to be added
	 * @param attributes the attributes to associate with this item
	 * @param conditions the conditions under which attributes should be put
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult addItem(String identifier, Map> attributes, List conditions) throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		params.put("ItemName", identifier);
		int i=1;
		for (String key : attributes.keySet()) {
			Set vals = attributes.get(key);
			if (vals != null && vals.size() > 0) {
				Iterator iter = vals.iterator();
				while (iter.hasNext()) {
					String val = iter.next();
					params.put("Attribute."+i+".Name", key);
					params.put("Attribute."+i+".Value", val);
					i++;
				}
			}
		}
		if (conditions != null) {
			i=1;
			for (Condition cond : conditions) {
				params.put("Expected."+i+".Name", cond.getName());
				String value = cond.getValue();
				if (value != null) {
					params.put("Expected."+i+".Value", value);
				}
				else {
					params.put("Expected."+i+".Exists", cond.isExists()?"true":"false");
				}
				i++;
			}
		}
		HttpGet method = new HttpGet();
		PutAttributesResponse response =
			makeRequestInt(method, "PutAttributes", params, PutAttributesResponse.class);
		if (cache != null) {
			// create new item object
			Item newItem = new ItemVO(identifier);
			Map> attrs = newItem.getAttributes();
			// throw attrs into it
			attrs.putAll(attributes);
			Item old = cache.getItem(identifier);
			if (old != null) {
				// merge cached attrs with those just set
				for (String key: old.getAttributes().keySet()) {
					Set oldAttrs = old.getAttributes().get(key);
					Set newAttrs = attrs.get(key);
					if (newAttrs != null) {
						newAttrs.addAll(oldAttrs);
					}
					else {
						attrs.put(key, oldAttrs);
					}
				}
			}
			// place/replace item in cache
			cache.putItem(newItem);
		}
		return new SDBResult(response.getResponseMetadata().getRequestId(),
					response.getResponseMetadata().getBoxUsage());
	}

	/**
	 * Batch inserts multiple items w/ attributes
	 *
	 * @param attributes list of attributes to add
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult batchPutAttributes(List items) throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		int k=1;
		for (Item item : items) {
			params.put("Item."+k+".ItemName", item.getIdentifier());
			int i=1;
			for (String attr : item.getAttributes().keySet()) {
				Set vals = item.getAttributeValues(attr);
				if (vals != null && vals.size() > 0) {
					for (String val : vals) {
						params.put("Item."+k+".Attribute."+i+".Name", attr);
						params.put("Item."+k+".Attribute."+i+".Value", val);
						i++;
//						if (attr.isReplace()) {
//							params.put("Item."+k+".Attribute."+i+".Replace", "true");
//						}
					}
				}
			}
			k++;
		}
		HttpGet method = new HttpGet();
		BatchPutAttributesResponse response =
			makeRequestInt(method, "BatchPutAttributes", params, BatchPutAttributesResponse.class);
		return new SDBResult(response.getResponseMetadata().getRequestId(),
					response.getResponseMetadata().getBoxUsage());
	}

	/**
	 * Replace attributes on an item. Using this call will force attribute values to be
	 * with the new ones supplied.
	 *
	 * @param identifier the name of the item to be added
	 * @param attributes the attributes to associate with this item
	 * @param conditions the conditions under which attributes should be put
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult replaceAttributes(String identifier, Map> attributes, List conditions) throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		params.put("ItemName", identifier);
		int i=1;
		for (String key : attributes.keySet()) {
			Set vals = attributes.get(key);
			if (vals != null && vals.size() > 0) {
				Iterator iter = vals.iterator();
				while (iter.hasNext()) {
					String val = iter.next();
					params.put("Attribute."+i+".Name", key);
					params.put("Attribute."+i+".Value", val);
					params.put("Attribute."+i+".Replace", "true");
					i++;
				}
			}
		}
		if (conditions != null) {
			i=1;
			for (Condition cond : conditions) {
				params.put("Expected."+i+".Name", cond.getName());
				String value = cond.getValue();
				if (value != null) {
					params.put("Expected."+i+".Value", value);
				}
				else {
					params.put("Expected."+i+".Exists", cond.isExists()?"true":"false");
				}
				i++;
			}
		}
		HttpGet method = new HttpGet();
		PutAttributesResponse response =
			makeRequestInt(method, "PutAttributes", params, PutAttributesResponse.class);
		if (cache != null) {
			// create new item object
			Item newItem = new ItemVO(identifier);
			Map> attrs = newItem.getAttributes();
			// throw attrs into it
			attrs.putAll(attributes);
			Item old = cache.getItem(identifier);
			if (old != null) {
				// merge cached attrs
				attrs.putAll(old.getAttributes());
			}
			// place/replace item in cache
			cache.putItem(newItem);
		}
		return new SDBResult(response.getResponseMetadata().getRequestId(),
					response.getResponseMetadata().getBoxUsage());
	}

	/**
	 * Deletes attributes from an item
	 *
	 * @param identifier the name of the item
	 * @param attributes the names of the attributes to be deleted
	 * @param conditions the conditions under which attributes should be put
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult deleteAttributes(String identifier, Set attributes, List conditions) throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		params.put("ItemName", identifier);
		int i=1;
		if (attributes != null && attributes.size() > 0) {
			Iterator iter = attributes.iterator();
			while (iter.hasNext()) {
				String val = iter.next();
				params.put("Attribute."+i+".Name", val);
				i++;
			}
		}
		if (conditions != null) {
			i=1;
			for (Condition cond : conditions) {
				params.put("Expected."+i+".Name", cond.getName());
				String value = cond.getValue();
				if (value != null) {
					params.put("Expected."+i+".Value", value);
				}
				else {
					params.put("Expected."+i+".Exists", cond.isExists()?"true":"false");
				}
				i++;
			}
		}
		HttpGet method = new HttpGet();
		DeleteAttributesResponse response =
			makeRequestInt(method, "DeleteAttributes", params, DeleteAttributesResponse.class);
		if (cache != null) {
		//	cache.removeItem(identifier);
		}
		return new SDBResult(response.getResponseMetadata().getRequestId(),
					response.getResponseMetadata().getBoxUsage());
	}

	/**
	 * Deletes an item.
	 *
	 * @param identifier the name of the item to be deleted
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBResult deleteItem(String identifier) throws SDBException {
		Map params = new HashMap();
		params.put("DomainName", domainName);
		params.put("ItemName", identifier);
		HttpGet method = new HttpGet();
		DeleteAttributesResponse response =
			makeRequestInt(method, "DeleteAttributes", params, DeleteAttributesResponse.class);
		if (cache != null) {
			cache.removeItem(identifier);
		}
		return new SDBResult(response.getResponseMetadata().getRequestId(),
					response.getResponseMetadata().getBoxUsage());
	}

	/**
	 * This method returns an item object, which exists locally only.
	 * It must be persisted with addItem, batchPutAttributes or replaceAttributes
	 *
	 * @param identifier the name of the item to be deleted
	 * @return item object
	 * @throws SDBException wraps checked exceptions
	 */
	public Item createItem(String identifier) {
		return new ItemVO(identifier);
	}

	/**
	 * Returns an named item.
	 *
	 * @param identifier the name of the item to be deleted
	 * @throws SDBException wraps checked exceptions
	 */
	public Result getItem(String identifier) throws SDBException {
		if (cache != null) {
			Item cached = cache.getItem(identifier);
			if (cached != null) {
				return new Result(null, cached);
			}
			// else, go fetch it anyway
		}
		Map params = new HashMap();
		params.put("DomainName", domainName);
		params.put("ItemName", identifier);
		HttpGet method = new HttpGet();
		GetAttributesResponse response =
					makeRequestInt(method, "GetAttributes", params, GetAttributesResponse.class);
		Item newItem = new ItemVO(identifier);
		Map> attrs = newItem.getAttributes();
		for (Attribute a : response.getGetAttributesResult().getAttributes()) {
			String name = a.getName().getValue();
			String encoding = a.getName().getEncoding();
			if (encoding != null && encoding.equals("base64")) {
				name = new String(Base64.decodeBase64(name.getBytes()));
			}
			String value = a.getValue().getValue();
			encoding = a.getValue().getEncoding();
			if (encoding != null && encoding.equals("base64")) {
				value = new String(Base64.decodeBase64(value.getBytes()));
			}
			Set vals = attrs.get(name);
			if (vals == null) {
				vals = Collections.synchronizedSet(new HashSet());
				attrs.put(name, vals);
			}
			vals.add(value);
		}
		if (cache != null) {
			cache.putItem(newItem);
		}
		return new Result(null, newItem);
	}

	/**
	 * Performs a query against this domain. A set of items is returned which may not be
	 * complete. If the nextToken in the result is set, this method can be called again
	 * with the same query and the supplied nextToken.
	 *
	 * @param selectExpression the query to be run
	 * @param nextToken an optional token to get more results
	 * @param consistent if true, consistency is assured
	 * @throws SDBException wraps checked exceptions
	 */
	public SDBListResult selectItems(String selectExpression, String nextToken, boolean consistent) throws SDBException {
		Map params = new HashMap();
		params.put("SelectExpression", selectExpression);
		if (nextToken != null) {
			params.put("NextToken", nextToken);
		}
		if (consistent) {
			params.put("ConsistentRead", "true");
		}
		HttpGet method = new HttpGet();
		SelectResponse response =
					makeRequestInt(method, "Select", params, SelectResponse.class);
		SDBListResult ret = new SDBListResult(
								response.getSelectResult().getNextToken(),
								response.getResponseMetadata().getRequestId(),
								response.getResponseMetadata().getBoxUsage());
		List results = ret.getItems();
		for (com.xerox.amazonws.typica.sdb.jaxb.Item i : response.getSelectResult().getItems()) {
			String iName = i.getName().getValue();
			String encoding = i.getName().getEncoding();
			if (encoding != null && encoding.equals("base64")) {
				iName = new String(Base64.decodeBase64(iName.getBytes()));
			}
			Item newItem = new ItemVO(iName);
			Map> attrs = newItem.getAttributes();
			for (Attribute a : i.getAttributes()) {
				String name = a.getName().getValue();
				encoding = a.getName().getEncoding();
				if (encoding != null && encoding.equals("base64")) {
					name = new String(Base64.decodeBase64(name.getBytes()));
				}
				String value = a.getValue().getValue();
				encoding = a.getValue().getEncoding();
				if (encoding != null && encoding.equals("base64")) {
					value = new String(Base64.decodeBase64(value.getBytes()));
				}
				Set vals = attrs.get(name);
				if (vals == null) {
					vals = Collections.synchronizedSet(new HashSet());
					attrs.put(name, vals);
				}
				vals.add(value);
			}
			results.add(newItem);
		}

		return ret;
	}

	public ItemCache getItemCache() {
		return this.cache;
	}

	public void setCacheProvider(ItemCache cache) {
		this.cache = cache;
	}

	static List createList(String [] domainNames, AWSQueryConnection connection)
			throws SDBException {
		ArrayList ret = new ArrayList();
		for (int i=0; i T makeRequestInt(HttpRequestBase method, String action, Map params, Class respType)
		throws SDBException {
		try {
			return connection.makeRequest(method, action, params, respType);
		} catch (AWSException ex) {
			throw new SDBException(ex);
		} catch (JAXBException ex) {
			throw new SDBException("Problem parsing returned message.", ex);
		} catch (SAXException ex) {
			throw new SDBException("Problem parsing returned message.", ex);
		} catch (HttpException ex) {
			throw new SDBException(ex.getMessage(), ex);
		} catch (IOException ex) {
			throw new SDBException(ex.getMessage(), ex);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy