package com.uas.report.axis.repository;

import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import javax.activation.DataHandler;
import javax.activation.DataSource;

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.attachments.AttachmentPart;
import org.apache.axis.attachments.Attachments;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;

import com.uas.report.axis.Argument;
import com.uas.report.axis.ListItem;
import com.uas.report.axis.OperationResult;
import com.uas.report.axis.Request;
import com.uas.report.axis.Resource;
import com.uas.report.axis.ResourceDescriptor;
import com.uas.report.axis.BasicResourceHandler;
import com.uas.report.axis.ResourceHandlerRegistry;
import com.uas.report.axis.ValidationError;
import com.uas.report.axis.ValidationErrors;
import com.uas.report.axis.WSException;
import com.uas.report.axis.WSValidationException;
import com.uas.report.axis.util.Marshaller;
import com.uas.report.axis.util.Unmarshaller;
import com.uas.report.util.FileUtils;

@Service
public class RepositoryManagementServiceImpl implements RepositoryManagementService, InitializingBean {

	private static final String VERSION = "2.0.1";

	// @Autowired
	// private SpecialProperties specialProperties;

	private Locale locale = null; // Default locale....

	private ResourceHandlerRegistry resourceHandlerRegistry;

	private BasicResourceHandler basicResourceHandler = new BasicResourceHandler();

	private ReloadableResourceBundleMessageSource messageSource;

	// private String attachmentsPath;

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public void afterPropertiesSet() throws Exception {
		resourceHandlerRegistry = new ResourceHandlerRegistry();
		messageSource = new ReloadableResourceBundleMessageSource();
		messageSource.setUseCodeAsDefaultMessage(true);
		messageSource.setFallbackToSystemLocale(false);
		messageSource.setBasenames("bundlePathsListCe");
		// attachmentsPath = specialProperties.getLocalBaseDir() +
		// "/tmp/jasperserver/axis_attachments";
	}

	@Override
	public String list(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		try {
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			setLocale(request.getLocale());

			List<ResourceDescriptor> list = null;

			if (request.getResourceDescriptor() == null) {
				list = new ArrayList<>();
				logger.debug("Null resourceDescriptor");
				// Look for specific list requests...
				if (getArgumentValue(Argument.LIST_DATASOURCES, request.getArguments()) != null
						&& getArgumentValue(Argument.LIST_DATASOURCES, request.getArguments())
								.equals(Argument.VALUE_TRUE)) {
					/*
					 * // List all datasources... FilterCriteria criteria =
					 * FilterCriteria.createFilter(ReportDataSource.class);
					 * logger.debug("Listing datasources...");
					 * 
					 * // This filters with object level security // Will only
					 * get resources the user has access to
					 * 
					 * List lookups = repository.loadClientResources(criteria);
					 * if (lookups != null && !lookups.isEmpty()) {
					 * 
					 * for (Iterator it = lookups.iterator(); it.hasNext();) {
					 * list.add(createResourceDescriptor((Resource) it.next()));
					 * } }
					 */
				} else if (request.hasArgument(Argument.LIST_RESOURCES)
						&& getArgumentValue(Argument.RESOURCE_TYPE, request.getArguments())
								.equals(Argument.REPORT_TYPE)) {
					/*
					 * // get list of reports from a certain directory
					 * recursively // List all datasources... logger.debug(
					 * "Listing all reports...");
					 * 
					 * String parentFolder =
					 * getArgumentValue(Argument.START_FROM_DIRECTORY,
					 * request.getArguments()); if ((parentFolder == null) ||
					 * (!(parentFolder.startsWith("/")))) { parentFolder = "/";
					 * } // all options List allSubFolders =
					 * repository.getAllFolders(null); for (int i = 0; i <
					 * allSubFolders.size(); i++) { String currentFolder =
					 * ((Folder) allSubFolders.get(i)).getURIString();
					 * FilterCriteria filterCriteria = new FilterCriteria();
					 * filterCriteria.addFilterElement(FilterCriteria.
					 * createParentFolderFilter(currentFolder)); List units =
					 * repository.loadClientResources(filterCriteria); for (int
					 * j = 0; j < units.size(); j++) { Resource currentRs =
					 * (Resource) units.get(j); if ((currentRs.getResourceType()
					 * != null) &&
					 * ((currentRs.getResourceType().contains("ReportOptions"))
					 * || (currentRs.getResourceType().contains("ReportUnit"))
					 * ||
					 * (currentRs.getResourceType().contains("AdhocReportUnit"))
					 * )) {
					 * 
					 * String temp = serviceConfiguration.getTempFolder(); if
					 * ("/".equals(parentFolder)) { if
					 * ((!(ADHOC_TOPICS.equals(currentRs.getParentFolder()))) &&
					 * (!(temp.equals(currentRs.getParentFolder())))) {
					 * list.add(createResourceDescriptor(currentRs)); } } else
					 * if ((currentRs.getURIString() +
					 * "/").startsWith(parentFolder + "/")) { if
					 * ((!(ADHOC_TOPICS.equals(currentRs.getParentFolder()))) &&
					 * (!(temp.equals(currentRs.getParentFolder())))) {
					 * list.add(createResourceDescriptor(currentRs)); } } } } }
					 */
				} else if (request.hasArgument(Argument.LIST_RESOURCES)) {
					/*
					 * String resourceType =
					 * request.getArgumentValue(Argument.RESOURCE_TYPE);
					 * 
					 * if (resourceType == null) { if (logger.isDebugEnabled())
					 * { logger.debug("No " + Argument.RESOURCE_TYPE +
					 * " argument, nothing to list"); } } else { ResourceHandler
					 * handler = handlerRegistry.getHandler(resourceType); if
					 * (handler == null) { throw new JSException(
					 * "No resource hander found for type " + resourceType); }
					 * 
					 * List resources = handler.listResources(request, this); if
					 * (resources != null) { list.addAll(resources); } }
					 */
				}
			} else if (request.getResourceDescriptor().getWsType().equals(ResourceDescriptor.TYPE_FOLDER)) {
				logger.debug("List folders");
				list = basicResourceHandler.listResourceDescriptors(request.getResourceDescriptor().getUriString());
			} else if (request.getResourceDescriptor().getWsType().equals(ResourceDescriptor.TYPE_REPORTUNIT)) {
				/*
				 * logger.debug("List report units"); list =
				 * createResourceDescriptor(request.getResourceDescriptor().
				 * getUriString()).getChildren();
				 */
			} else {
				logger.debug("Listed nothing");
			}

			if (logger.isDebugEnabled()) {
				logger.debug("Found " + list.size() + " things");
				for (Iterator<ResourceDescriptor> it = list.iterator(); it.hasNext();) {
					ResourceDescriptor rd = it.next();
					logger.debug(rd != null ? rd.getName() : "rd was null");
				}
			}

			operationResult.setResourceDescriptors(list);
			logger.debug("Marshalling response");

		} catch (Exception e) {
			logger.error("caught exception: " + e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
		} catch (Throwable e) {
			logger.error("caught exception: " + e.getMessage(), e);
		}

		return marshalResponse(operationResult);
	}

	@Override
	public String get(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		try {
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			// createAuditEvent(request.getOperationName(),
			// request.getResourceDescriptor().getWsType(),
			// request.getResourceDescriptor().isNew());
			setLocale(request.getLocale());

			List<Argument> args = request.getArguments();

			// List<ListItem> params = Collections.emptyList();
			// if (request.getResourceDescriptor() != null &&
			// request.getResourceDescriptor().getParameters() != null) {
			// params = request.getResourceDescriptor().getParameters();
			// }

			HashMap<String, String> specialOptions = new HashMap<>();
			if (args != null) {
				for (int i = 0; i < args.size(); ++i) {
					Argument arg = args.get(i);
					if (arg != null) {
						specialOptions.put(arg.getName(), arg.getValue());
					}
				}
			}
			// if (params.size() > 0 &&
			// specialOptions.containsKey(Argument.RU_REF_URI)) {
			// ResourceDescriptor reportDescriptior = createResourceDescriptor(
			// (String) specialOptions.get(Argument.RU_REF_URI));
			// specialOptions.put(Argument.PARAMS_ARG, buildParameterMap(params,
			// reportDescriptior));
			// }

			String resourceURI = request.getResourceDescriptor().getUriString();
			Resource resource = basicResourceHandler.locateResource(resourceURI);
			if (resource == null) {
				logger.warn("Get: null resourceDescriptor for " + resourceURI);
				operationResult.setReturnCode(2);
				// operationResult
				// .setMessage(messageSource.getMessage("webservices.error.resourceNotFound",
				// null, getLocale()));
			} else {
				// ResourceDescriptor rd = createResourceDescriptor(resource,
				// processDescriptorOptions(specialOptions));
				ResourceDescriptor rd = basicResourceHandler.toResourceDescriptor(resource);

				logger.debug("Get: " + resourceURI + ", wsType: " + rd.getWsType() + ", resourceType: "
						+ rd.getResourceType());
				operationResult.getResourceDescriptors().add(rd);

				// ResultAttachments attachments = new ResultAttachments();
				// attachments.setEncapsulationDime(getArgumentValue("USE_DIME_ATTACHMENTS",
				// request.getArguments()) != null);
				// ResourceHandler handler =
				// getHandlerRegistry().getHandler(rd.getWsType());
				// handler.getAttachments(resource, specialOptions, rd,
				// attachments, this);
				// if (operationResult.getReturnCode() != 0) {
				// addExceptionToAllAuditEvents(new
				// Exception(operationResult.getMessage()));
				// }
				// return marshalResponse(operationResult, attachments);
				BasicResourceHandler handler = resourceHandlerRegistry.getHandler(rd.getWsType());
				Map<String, DataSource> attachments = handler.getAttachments(specialOptions, rd);
				boolean isEncapsulationDime = getArgumentValue("USE_DIME_ATTACHMENTS", request.getArguments()) != null;
				return marshalResponse(operationResult, attachments, isEncapsulationDime);
			}
		} catch (Exception e) {
			logger.error("caught exception: " + e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		}
		logger.debug("Marshalling response");

		return marshalResponse(operationResult);
	}

	@Override
	public String put(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		try {
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			// createAuditEvent(request.getOperationName(),
			// request.getResourceDescriptor().getWsType(),
			// request.getResourceDescriptor().isNew());
			setLocale(request.getLocale());

			ResourceDescriptor newDescriptor = request.getResourceDescriptor();

			// 获取上传的数据
			AttachmentPart[] attachmentParts = getMessageAttachments();
			if (attachmentParts.length > 1) {
				throw new IllegalStateException("不可上传多个文件");
			} else if (attachmentParts.length == 1) {
				InputStream inputStream = attachmentParts[0].getDataHandler().getInputStream();
				byte[] data = FileUtils.readData(inputStream);
				newDescriptor.setData(data);
			}

			logger.debug("Put: for " + newDescriptor.getUriString());

			if (newDescriptor.getUriString() == null || newDescriptor.getUriString().length() == 0) {
				throw new WSException(WSException.GENERAL_REQUEST_ERROR,
						messageSource.getMessage("webservices.error.noUriGiven", null, getLocale()));
			}

			if (newDescriptor.getWsType() == null || newDescriptor.getWsType().length() == 0) {
				throw new WSException(WSException.GENERAL_REQUEST_ERROR,
						messageSource.getMessage("webservices.error.noTypeGiven", null, getLocale()));
			}

			String wsType = newDescriptor.getWsType();
			BasicResourceHandler handler = resourceHandlerRegistry.getHandler(wsType);
			operationResult.getResourceDescriptors().add(handler.put(request));

		} catch (WSValidationException e) {
			logger.error("caught validation exception: " + e.getMessage(), e);

			operationResult.setReturnCode(e.getErrorCode());
			operationResult.setMessage(getValidationErrorMessage(e.getObjectName(), e.getErrors()));
		} catch (WSException e) {
			operationResult.setReturnCode(e.getErrorCode());
			operationResult.setMessage(e.getMessage());
		} catch (Exception e) {
			// e.printStackTrace();
			logger.error("caught exception: " + e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
		}
		logger.debug("Marshalling response");

		return marshalResponse(operationResult);
	}

	@Override
	public String delete(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		// operationResult.setReturnCode( OperationResult.SUCCESS );
		try {
			// Iterator iter = element.getChildElements();
			// String requestXmlString = ((OMElement) iter.next()).getText();

			// Unmarshall xmlDescriptor request...
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			// createAuditEvent(request.getOperationName(),
			// request.getResourceDescriptor().getWsType(),
			// request.getResourceDescriptor().getIsNew());
			setLocale(request.getLocale());

			String reportUnitUrl = getArgumentValue(Argument.MODIFY_REPORTUNIT, request.getArguments());

			if (reportUnitUrl != null && reportUnitUrl.length() > 0) {
				logger.debug("Delete: resource in reportUnit: " + reportUnitUrl);

				// Report unit modification....
				// ReportUnit reportUnit = (ReportUnit)
				// repository.getResource(null, reportUnitUrl);
				// if (reportUnit == null) {
				// throw new
				// WSException(WSException.REFERENCED_RESOURCE_NOT_FOUND,
				// messageSource.getMessage("webservices.error.reportUnitNotFound",
				// null, getLocale()));
				// }
				//
				// SubResourceHandler handler = (SubResourceHandler)
				// getHandlerRegistry().getHandler(reportUnit);
				// handler.deleteSubResource(reportUnit,
				// request.getResourceDescriptor(), this);
				operationResult.setReturnCode(1);
				operationResult.setMessage("不支持该类型的资源！");
			} else {
				// ResourceDescriptor rd =
				// createResourceDescriptor(request.getResourceDescriptor().getUriString());
				ResourceDescriptor resourceDescriptor = basicResourceHandler
						.locateResourceDescriptor(request.getResourceDescriptor().getUriString());
				if (resourceDescriptor == null) {
					logger.error("Delete: no resource : " + request.getResourceDescriptor().getUriString());
					// or.setReturnCode(2);
					// or.setMessage("Resource not found");
					operationResult.setReturnCode(2);
					operationResult.setMessage("Resource not found");
				} else {
					String wsType = resourceDescriptor.getWsType();
					logger.debug("Delete: resource : " + wsType);
					// ResourceHandler handler =
					// getHandlerRegistry().getHandler(wsType);
					BasicResourceHandler handler = resourceHandlerRegistry.getHandler(wsType);
					// handler.delete(rd, this);
					handler.delete(resourceDescriptor);
				}
			}

			// if (operationResult.getReturnCode() != 0) {
			// addExceptionToAllAuditEvents(new
			// Exception(operationResult.getMessage()));
			// }
		} catch (WSException e) {
			operationResult.setReturnCode(e.getErrorCode());
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("caught exception: " + e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		}

		logger.debug("Marshalling response");
		return marshalResponse(operationResult);
	}

	@Override
	public String runReport(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		operationResult.setReturnCode(1);
		operationResult.setMessage("不支持该操作！");
		return marshalResponse(operationResult);
	}

	@Override
	public String move(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		// or.setReturnCode(OperationResult.SUCCESS);
		try {
			// Request request = (Request)
			// Unmarshaller.unmarshalXml(requestXmlString);
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			// createAuditEvent(request.getOperationName(),
			// request.getResourceDescriptor().getWsType(),
			// request.getResourceDescriptor().getIsNew());
			setLocale(request.getLocale());

			// ResourceDescriptor resource =
			// createRequestResourceDescriptor(request);
			ResourceDescriptor resourceDescriptor = basicResourceHandler
					.locateResourceDescriptor(request.getResourceDescriptor().getUriString());
			String wsType = resourceDescriptor.getWsType();
			if (logger.isDebugEnabled()) {
				logger.debug("Move WS type: " + wsType);
			}
			// ResourceHandler handler =
			// getHandlerRegistry().getHandler(wsType);
			// handler.move(request, this);
			BasicResourceHandler handler = resourceHandlerRegistry.getHandler(wsType);
			handler.move(resourceDescriptor, basicResourceHandler.getDestinationURI(request));
			// if (or.getReturnCode() != 0) {
			// addExceptionToAllAuditEvents(new Exception(or.getMessage()));
			// }
		} catch (WSException e) {
			operationResult.setReturnCode(e.getErrorCode());
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		}

		return marshalResponse(operationResult);
	}

	@Override
	public String copy(String requestXmlString) {
		OperationResult operationResult = new OperationResult();
		operationResult.setVersion(VERSION);
		// or.setReturnCode(OperationResult.SUCCESS);
		try {
			// Request request = (Request)
			// Unmarshaller.unmarshalXml(requestXmlString);
			StringReader xmlStringReader = new StringReader(requestXmlString);
			Request request = (Request) Unmarshaller.unmarshal(xmlStringReader);
			// createAuditEvent(request.getOperationName(),
			// request.getResourceDescriptor().getWsType(),
			// request.getResourceDescriptor().getIsNew());
			setLocale(request.getLocale());

			// ResourceDescriptor resource =
			// createRequestResourceDescriptor(request);
			ResourceDescriptor resourceDescriptor = basicResourceHandler
					.locateResourceDescriptor(request.getResourceDescriptor().getUriString());
			String wsType = resourceDescriptor.getWsType();
			if (logger.isDebugEnabled()) {
				logger.debug("Copy WS type: " + wsType);
			}
			// ResourceHandler handler =
			// getHandlerRegistry().getHandler(wsType);
			// handler.copy(request, this);
			BasicResourceHandler handler = resourceHandlerRegistry.getHandler(wsType);
			ResourceDescriptor copyDescriptor = handler.copy(resourceDescriptor,
					basicResourceHandler.getDestinationURI(request));
			operationResult.addResourceDescriptor(copyDescriptor);
			// if (or.getReturnCode() != 0) {
			// addExceptionToAllAuditEvents(new Exception(or.getMessage()));
			// }
		} catch (WSException e) {
			operationResult.setReturnCode(e.getErrorCode());
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			operationResult.setReturnCode(1);
			operationResult.setMessage(e.getMessage());
			// addExceptionToAllAuditEvents(e);
		}

		return marshalResponse(operationResult);
	}

	/**
	 * Function to get attachments from an Axis message
	 * 
	 * @throws WSException
	 * @throws NoSuchMessageException
	 * @throws AxisFault
	 *
	 */
	@Override
	public AttachmentPart[] getMessageAttachments() throws NoSuchMessageException, WSException, AxisFault {
		try {
			MessageContext msgContext = MessageContext.getCurrentContext();
			// File file = new File(attachmentsPath);
			// if (!file.exists()) {
			// file.mkdirs();
			// }
			// msgContext.setProperty(MessageContext.ATTACHMENTS_DIR,
			// attachmentsPath);
			Message reqMsg = msgContext.getRequestMessage();
			Attachments messageAttachments = reqMsg.getAttachmentsImpl();
			if (null == messageAttachments) {
				logger.error("no attachment support");
				return new AttachmentPart[0];
			}
			int attachmentCount = messageAttachments.getAttachmentCount();
			AttachmentPart attachments[] = new AttachmentPart[attachmentCount];

			Iterator<?> it = messageAttachments.getAttachments().iterator();
			int count = 0;
			while (it.hasNext()) {
				AttachmentPart part = (AttachmentPart) it.next();
				attachments[count++] = part;
			}
			return attachments;
		} catch (AxisFault e) {
			if (e.getFaultString().startsWith("java.io.IOException")) {
				// throw new JSExceptionWrapper(new
				// WSException(WSException.GENERAL_ERROR,
				// messageSource.getMessage("webservices.error.attachments.folder",null,getLocale())));
				throw new WSException(WSException.GENERAL_ERROR,
						messageSource.getMessage("webservices.error.attachments.folder", null, getLocale()));
			}
			// throw new JSExceptionWrapper(e);
			throw e;
		}
	}

	public Locale getLocale() {
		return locale;
	}

	// TODO fix
	public void setLocale(Locale locale) {
		this.locale = locale;
	}

	/**
	 * This method takes the Locale requested by the client. If the requested
	 * locale is null, the default locale is returned.
	 *
	 * A locale code can be in the form:
	 *
	 * langagecode[_countrycode]
	 *
	 * Ex: en_US, it_IT, it, en_UK
	 *
	 */
	private void setLocale(String requestedLocale) {
		try {
			if (requestedLocale != null) {
				String language = requestedLocale;
				String country = "";
				if (requestedLocale.indexOf("_") > 0) {
					language = requestedLocale.substring(0, requestedLocale.indexOf("_"));
					country = requestedLocale.substring(requestedLocale.indexOf("_") + 1);
					setLocale(new Locale(language, country));
				} else {
					setLocale(new Locale(language));
				}
			}
		} catch (Exception ex) {
			logger.error("Unable to get requested locale (" + requestedLocale + ")");
			setLocale(Locale.getDefault());
		}
	}

	private String marshalResponse(OperationResult operationResult) {
		return marshalResponse(operationResult, new HashMap<String, DataSource>(), false);
	}

	private String marshalResponse(OperationResult operationResult, Map<String, DataSource> datasources,
			boolean isEncapsulationDime) {

		String result = "";

		// First of all attach the attachments...
		if (datasources != null) {
			MessageContext msgContext = MessageContext.getCurrentContext();
			Message responseMessage = msgContext.getResponseMessage();

			logger.debug("Encapsulation DIME? : " + isEncapsulationDime);

			if (isEncapsulationDime) {
				responseMessage.getAttachmentsImpl().setSendType(Attachments.SEND_TYPE_DIME);
			}

			for (Iterator<Entry<String, DataSource>> it = datasources.entrySet().iterator(); it.hasNext();) {
				try {
					Entry<String, DataSource> entry = it.next();
					String name = (String) entry.getKey();
					DataSource datasource = (DataSource) entry.getValue();

					logger.debug("Adding attachment: " + name + ", type: " + datasource.getContentType());

					DataHandler expectedDH = new DataHandler(datasource);

					javax.xml.soap.AttachmentPart attachPart = null;
					attachPart = responseMessage.createAttachmentPart(expectedDH);

					// javax.xml.soap.AttachmentPart ap2 =
					// responseMessage.createAttachmentPart();
					// ap2.setContent( datasource.getInputStream(),
					// datasource.getContentType());
					attachPart.setContentId(name);
					responseMessage.addAttachmentPart(attachPart);

				} catch (Exception ex) {
					logger.error("caught exception marshalling an OperationResult: " + ex.getMessage(), ex);
					// What to do?
					operationResult.setReturnCode(1);
					operationResult.setMessage("Error attaching a resource to the SOAP message: " + ex.getMessage());
				}
			}

		}

		try {
			StringWriter xmlStringWriter = new StringWriter();
			Marshaller.marshal(operationResult, xmlStringWriter);
			if (logger.isDebugEnabled()) {
				logger.debug("Has descriptors: " + ((operationResult.getResourceDescriptors() == null
						|| operationResult.getResourceDescriptors().size() == 0) ? 0
								: operationResult.getResourceDescriptors().size()));
				logger.debug("marshalled response");
				logger.debug(xmlStringWriter.toString());
			}
			result = xmlStringWriter.toString();

		} catch (Exception ex) {
			logger.error("caught exception marshalling an OperationResult: " + ex.getMessage(), ex);
			// What to do?
		}

		return result;
	}

	protected String getArgumentValue(String argumentName, List<Argument> arguments) {
		for (int i = 0; i < arguments.size(); ++i) {
			Argument a = (Argument) arguments.get(i);
			if (a.getName() == null ? a.getName() == argumentName : a.getName().equals(argumentName)) {
				return a.getValue();
			}
		}

		return null;
	}

	protected String getValidationErrorMessage(String objectName, ValidationErrors errors) {
		StringBuffer message = new StringBuffer();
		List<ValidationError> errorList = errors.getErrors();
		message.append(getMessage("webservices.error.validation.errors.prefix",
				new Object[] { new Integer(errorList.size()) }));
		message.append("\n");
		for (Iterator<ValidationError> it = errorList.iterator(); it.hasNext();) {
			ValidationError error = (ValidationError) it.next();
			message.append(getValidationErrorMessage(objectName, error));
			message.append("\n");
		}
		return message.toString();
	}

	protected Object getValidationErrorMessage(String objectName, ValidationError error) {
		MessageCodesResolver codesResolver = new DefaultMessageCodesResolver();
		String[] codes;
		if (error.getField() == null) {
			codes = codesResolver.resolveMessageCodes(error.getErrorCode(), objectName);
		} else {
			codes = codesResolver.resolveMessageCodes(error.getErrorCode(), objectName, error.getField(), null);
		}
		MessageSourceResolvable messageResolvable = new DefaultMessageSourceResolvable(codes, error.getErrorArguments(),
				error.getDefaultMessage());
		String message = messageSource.getMessage(messageResolvable, getLocale());
		return message;
	}

	public String getMessage(String messageCode, Object[] args) {
		return messageSource.getMessage(messageCode, args, getLocale());
	}
}
