package org.springframework.content.commons.operations;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.content.commons.annotations.ContentId;
import org.springframework.content.commons.annotations.ContentLength;
import org.springframework.content.commons.utils.BeanUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.WritableResource;

public abstract class AbstractResourceTemplate implements ResourceOperations, ContentOperations {
	
	private static Log logger = LogFactory.getLog(AbstractResourceTemplate.class);
	
	private ResourceLoader resourceLoader;
	
	public AbstractResourceTemplate(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}
	
	@Override
	public <S> void setContent(S property, InputStream content) {
		Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);
		if (contentId == null) {
			contentId = UUID.randomUUID();
			BeanUtils.setFieldWithAnnotation(property, ContentId.class, contentId.toString());
		}

		Resource resource = this.get(this.getLocation(contentId));
		OutputStream os = null;
		try {
			if (resource instanceof WritableResource) {
				os = ((WritableResource)resource).getOutputStream();
				IOUtils.copy(content, os);
			}
		} catch (IOException e) {
			logger.error(String.format("Unexpected error setting content %s", contentId.toString()), e);
		} finally {
	        try {
	            if (os != null) {
	                os.close();
	            }
	        } catch (IOException ioe) {
	            // ignore
	        }
		}
			
		try {
			BeanUtils.setFieldWithAnnotation(property, ContentLength.class, resource.contentLength());
		} catch (IOException e) {
			logger.error(String.format("Unexpected error setting content length for content %s", contentId.toString()), e);
		}
	}

	@Override
	public <S> InputStream getContent(S property) {
		if (property == null)
			return null;
		Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);
		if (contentId == null)
			return null;

		Resource resource = this.get(this.getLocation(contentId));
		try {
			if (resource.exists()) {
				return resource.getInputStream();
			}
		} catch (IOException e) {
			logger.error(String.format("Unexpected error getting content %s", contentId.toString()), e);
		}
		
		return null;
	}

	@Override
	public <S> void unsetContent(S property) {
		if (property == null)
			return;
		Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);
		if (contentId == null)
			return;

		// delete any existing content object
		try {
			Resource resource = this.get(this.getLocation(contentId));
			if (resource.exists()) {
				this.delete(resource);

				// reset content fields
		        BeanUtils.setFieldWithAnnotation(property, ContentId.class, null);
		        BeanUtils.setFieldWithAnnotation(property, ContentLength.class, 0);
			}
		} catch (Exception ase) {
			logger.error(String.format("Unexpected error unsetting content %s", contentId.toString()), ase);
		}
	}

    @Override
	public Resource get(String location) {
		Resource resource = resourceLoader.getResource(location);
		return resource;
	}

	@Override
	public void delete(Resource resource) {
		try {
			if (resource.exists()) {
				this.deleteResource(resource);
			}
		} catch (Exception ase) {
			logger.error(String.format("Unexpected error unsetting content %s", resource.getFilename()), ase);
		}
	}


	// hook for our placement strategy
	protected abstract String getLocation(Object contentId);


	// todo: remove this
	protected abstract void deleteResource(Resource resource) throws Exception;

}

@@ -70,418 +70,104 @@
 io.I
-OException;%0Aimport java.io.InputStream;%0Aimport java.io.OutputStream;%0Aimport java.util.UUID;%0A%0Aimport org.apache.commons.io.IOUtils;%0Aimport org.apache.commons.logging.Log;%0Aimport org.apache.commons.logging.LogFactory;%0Aimport org.springframework.content.commons.annotations.ContentId;%0Aimport org.springframework.content.commons.annotations.ContentLength;%0Aimport org.springframework.content.commons.utils.BeanUtils
+nputStream;%0A%0Aimport org.apache.commons.logging.Log;%0Aimport org.apache.commons.logging.LogFactory
 ;%0Aim
@@ -263,61 +263,8 @@
 der;
-%0Aimport org.springframework.core.io.WritableResource;
 %0A%0Apu
@@ -676,2243 +676,179 @@
 %7B%0A%09%09
-Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);%0A%09%09if (contentId == null) %7B%0A%09%09%09contentId = UUID.randomUUID();%0A%09%09%09BeanUtils.setFieldWithAnnotation(property, ContentId.class, contentId.toString());%0A%09%09%7D%0A%0A%09%09Resource resource = this.get(this.getLocation(contentId));%0A%09%09OutputStream os = null;%0A%09%09try %7B%0A%09%09%09if (resource instanceof WritableResource) %7B%0A%09%09%09%09os = ((WritableResource)resource).getOutputStream();%0A%09%09%09%09IOUtils.copy(content, os);%0A%09%09%09%7D%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09logger.error(String.format(%22Unexpected error setting content %25s%22, contentId.toString()), e);%0A%09%09%7D finally %7B%0A%09        try %7B%0A%09            if (os != null) %7B%0A%09                os.close();%0A%09            %7D%0A%09        %7D catch (IOException ioe) %7B%0A%09            // ignore%0A%09        %7D%0A%09%09%7D%0A%09%09%09%0A%09%09try %7B%0A%09%09%09BeanUtils.setFieldWithAnnotation(property, ContentLength.class, resource.contentLength());%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09logger.error(String.format(%22Unexpected error setting content length for content %25s%22, contentId.toString()), e);%0A%09%09%7D%0A%09%7D%0A%0A%09@Override%0A%09public %3CS%3E InputStream getContent(S property) %7B%0A%09%09if (property == null)%0A%09%09%09return null;%0A%09%09Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);%0A%09%09if (contentId == null)%0A%09%09%09return null;%0A%0A%09%09Resource resource = this.get(this.getLocation(contentId));%0A%09%09try %7B%0A%09%09%09if (resource.exists()) %7B%0A%09%09%09%09return resource.getInputStream();%0A%09%09%09%7D%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09logger.error(String.format(%22Unexpected error getting content %25s%22, contentId.toString()), e);%0A%09%09%7D%0A%09%09%0A%09%09return null;%0A%09%7D%0A%0A%09@Override%0A%09public %3CS%3E void unsetContent(S property) %7B%0A%09%09if (property == null)%0A%09%09%09return;%0A%09%09Object contentId = BeanUtils.getFieldWithAnnotation(property, ContentId.class);%0A%09%09if (contentId == null)%0A%09%09%09return;%0A%0A%09%09// delete any existing content object%0A%09%09try %7B%0A%09%09%09Resource resource = this.get(this.getLocation(contentId));%0A%09%09%09if (resource.exists()) %7B%0A%09%09%09%09this.delete(resource);%0A%0A%09%09%09%09// reset content fields%0A%09%09        BeanUtils.setFieldWithAnnotation(property, ContentId.class, null);%0A%09%09        BeanUtils.setFieldWithAnnotation(property, ContentLength.class, 0);%0A%09%09%09%7D%0A%09%09%7D catch (Exception ase) %7B%0A%09%09%09logger.error(String.format(%22Unexpected error unsetting content %25s%22, contentId.toString()), ase);%0A%09%09%7D
+// unused%0A%09%7D%0A%0A%09@Override%0A%09public %3CS%3E InputStream getContent(S property) %7B%0A%09%09// unused%0A%09%09return null;%0A%09%7D%0A%0A%09@Override%0A%09public %3CS%3E void unsetContent(S property) %7B%0A%09%09// unused
 %0A%09%7D%0A

Remove unused code - in lieu of removing the ContentOeprations iface