/*
 * $Id: importData.java,v 1.1 2008/01/31 23:59:06 linkconsulting Exp $
 *
 *  Copyright (c) 2003-2005 The Open For Business Project - www.ofbiz.org
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
 *  OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 *  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.ofbiz.opentravelsystem;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.transaction.GenericTransactionException;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.LocalDispatcher;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.Ostermiller.util.Base64;

/**
 
 *
 * Product import  program which will read files in the following format:
 * 
 * ProductId, description, largeimage filename, smallimagefilename, category,  promo, price
 * 
 * it will also create the categories. The catalog should however already exist and should be the same name as the organizationPartyId.
 *
 * @author     <a href="mailto:support@opentravelsystem.org">Hans Bakker</a> 
 * @version    $Rev: 0000 $
 */
public class importData {
	
	static boolean debug = true;	// to show error messages or not.....
	
	static String module = importData.class.getName();
	// these variables are used by the getFile and getLine routines independant of the format
	static GenericDelegator delegator = null;
	static LocalDispatcher dispatcher = null;
	static FileItem localFile = null;
    static String localFileString = null;
	static int lineNumber;
	static int start = 0;
	static int end = 0;
	static String fileLine = null;
 	static java.sql.Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
	
 	static Transformer transformer; 
 	
	public static String importProduct(HttpServletRequest request, HttpServletResponse response) {
		delegator = (GenericDelegator) request.getAttribute("delegator");
		GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
		dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
		Locale loc = (Locale)request.getSession().getServletContext().getAttribute("locale");
		if (loc == null) loc = Locale.getDefault();
		String organizationPartyId = userLogin.getString("partyId");
        
		localFileString = localFile.getString();
        
		if (getFile(request).equals("error") || localFileString == null || localFileString.length() == 0) { // get the content of the uploaded file...
			request.setAttribute("_ERROR_MESSAGE_", "imPortProduct: Uploaded file not found or an empty file......");
			return "error";
		}
		if (debug) Debug.logInfo("File loaded...", module);
		
		List toBeStored = new LinkedList(); // file to keep all the values which need updating
		
		GenericValue catalog = null;
		GenericValue partyAcctgPreference = null;
		try {
			partyAcctgPreference = delegator.findByPrimaryKey("PartyAcctgPreference", UtilMisc.toMap("partyId",organizationPartyId));
			catalog = delegator.findByPrimaryKey("ProdCatalog", UtilMisc.toMap("prodCatalogId",organizationPartyId));
		} catch(GenericEntityException e2) {
			request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
			return "error";
		}
		
		if (catalog == null) {
			request.setAttribute("_ERROR_MESSAGE_", "Catalog not found with name: " + organizationPartyId);
			return "error";
		}
		
		if (partyAcctgPreference == null) {
			request.setAttribute("_ERROR_MESSAGE_", "Party logged on is not a organizationParty: " + organizationPartyId);
			return "error";
		}
		// create basis categories
		// promotion
		toBeStored.add(delegator.makeValue("ProductCategory",UtilMisc.toMap(
				"productCategoryId",organizationPartyId + "_PROMO",
				"productCategoryTypeId","CATALOG_CATEGORY",
				"primaryParentCategoryId",organizationPartyId,
				"description","Promotion Items")));
		
		// connect to catalog
		toBeStored.add(delegator.makeValue("ProdCatalogCategory",UtilMisc.toMap(
				"prodCatalogId",organizationPartyId,
				"productCategoryId",organizationPartyId + "_PROMO",
				"prodCatalogCategoryTypeId","PCCT_PROMOTIONS",
				"fromDate",nowTimestamp)));
		
		// browseroot
		toBeStored.add(delegator.makeValue("ProductCategory",UtilMisc.toMap(
				"primaryParentCategoryId",organizationPartyId,
				"productCategoryId",organizationPartyId + "_ROOT",
				"productCategoryTypeId","CATALOG_CATEGORY",
				"description","contain the categories to browse"	)));
		
		// connect to catalog
		toBeStored.add(delegator.makeValue("ProdCatalogCategory",UtilMisc.toMap(
				"prodCatalogId",organizationPartyId,
				"productCategoryId",organizationPartyId + "_ROOT",
				"prodCatalogCategoryTypeId","PCCT_BROWSE_ROOT",
				"fromDate",nowTimestamp)));

		List categories = new ArrayList(); // remember added categories, do not add links over and over
		while ((fileLine = getLine()) != null && lineNumber < 100) {
			if (debug) Debug.logInfo("Line read: " +fileLine, module);
			
			// prepare structures for updating
			GenericValue product =delegator.makeValue("Product",UtilMisc.toMap(
					"productTypeId","FINISHED_GOOD",
					"primaryProductCategoryId", organizationPartyId));
			GenericValue productPrice =delegator.makeValue("ProductPrice",UtilMisc.toMap(
					"productPricePurposeId","PURCHASE",
					"productPriceTypeId","DEFAULT_PRICE",
					"currencyUomId",partyAcctgPreference.getString("baseCurrencyUomId"),
					"productStoreGroupId","_NA_",
					"fromDate",nowTimestamp));
			GenericValue productCategory =delegator.makeValue("ProductCategory",UtilMisc.toMap(
					"primaryParentCategoryId",organizationPartyId,
					"productCategoryTypeId","CATALOG_CATEGORY")); // category itself
			GenericValue productCategoryMember = delegator.makeValue("ProductCategoryMember",UtilMisc.toMap( // connect product to category
					"fromDate",nowTimestamp));
			GenericValue productCategoryMemberPromo = delegator.makeValue("ProductCategoryMember",UtilMisc.toMap( // connect product to promo category
					"fromDate",nowTimestamp,
					"productCategoryId",organizationPartyId + "_PROMO"));
			GenericValue prodCatalogCategory =delegator.makeValue("ProdCatalogCategory",UtilMisc.toMap(  // category to productCatalog
					"prodCatalogId",organizationPartyId,
					"prodCatalogCategoryTypeId","PCCT_QUICK_ADD",  // dummy entry
					"fromDate",nowTimestamp));
			GenericValue productCategoryRollup =delegator.makeValue("ProductCategoryRollup",UtilMisc.toMap( // category to parent for browsing
					"fromDate",nowTimestamp,
					"parentProductCategoryId",organizationPartyId + "_ROOT"));
			
			int infoItemNr = 0;
			boolean promo = false;
			String prefix = partyAcctgPreference.getString("invoiceIdPrefix");
			String infoItem = null;
			// parse line from file
			while ((infoItem=getToken()) != null && infoItemNr != 7 ) {
				if (debug) Debug.logInfo("Token read: " + infoItem, module);
				switch(++infoItemNr) {
				case 1: // product number
					product.put("productId", prefix.concat("-").concat(infoItem));
					productPrice.put("productId", prefix.concat("-").concat(infoItem));
					productCategoryMemberPromo.put("productId",prefix.concat("-").concat(infoItem)); // connect to promocategory if required
					productCategoryMember.put("productId",prefix.concat("-").concat(infoItem)); // connect to browse category
					break;
				case 2: //description
					product.put("productName", infoItem);
					product.put("description", infoItem);
					break;
				case 3: // large image
					product.put("largeImageUrl", "/".concat(organizationPartyId).concat("/html/").concat(infoItem));
					break;
				case 4: //small image
					product.put("smallImageUrl","/".concat(organizationPartyId).concat("/html/").concat(infoItem));
					break;
				case 5: //price
						productPrice.put("price", new Double(Double.parseDouble(infoItem)));
					break;
				case 6: //category
					productCategory.put("productCategoryId", prefix.concat("-").concat(infoItem));
					productCategory.put("description",infoItem);
					prodCatalogCategory.put("productCategoryId", prefix.concat("-").concat(infoItem));
					productCategoryRollup.put("productCategoryId", prefix.concat("-").concat(infoItem));
					productCategoryMember.put("productCategoryId", prefix.concat("-").concat(infoItem));
					break;
				case 7: //promo (y/n)
					if (infoItem.equals("N") || infoItem.equals("n")|| infoItem.equals(" ")) {
						promo = false;
					}
					else  {
						promo=true;
					}
					break;
				}
			}


			// check is some already exists, do not create link again
			GenericValue prExist = null;
			GenericValue catExist = null;
			try {
				prExist = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId",product.getString("productId")));
				catExist = delegator.findByPrimaryKey("ProductCategory", UtilMisc.toMap("productCategoryId",productCategory.getString("productCategoryId")));
			} catch(GenericEntityException e2) {
				request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
				return "error";
			}
			
			// update/create
			toBeStored.add(productCategory); 				// category
			toBeStored.add(product); 							// product
			toBeStored.add(productPrice); 						// product price
			
			// create links only if items did not exist
			if(prExist == null) {
				toBeStored.add(productCategoryMember); 	// product link to category
			}
			if (catExist == null && categories.indexOf(productCategory.getString("productCategoryId")) == -1) {
				categories.add(productCategory.getString("productCategoryId"));  // add to the list so not recreated
				toBeStored.add(productCategoryRollup); 		// category to browseroot category
			}
			if (promo) 
				toBeStored.add(productCategoryMemberPromo); 	// product link to promotion category
		}
		
		try {	// create entities for this record
            delegator.storeAll(toBeStored);
		} catch(GenericEntityException e2) {
			request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
			return "error";
		}
		request.setAttribute("_EVENT_MESSAGE_", "Import successfull: " + toBeStored.size() + " records imported/updated.");
		return (String) "success";
	}		
	
	
	/**
	 * get the next token from the line 
	 * @return the content of the token or null when end of line
	 */
	private static String getToken() {
		if(fileLine.length() == 0) return null;
		int start = 0;int end = 0;
		String token = null;
		if (fileLine.charAt(0) == '"') 	{
			start = 1;
			// find next quote
			end = fileLine.substring(start).indexOf("\",")+1;
			if (end > 0)	{ // found?
				token = fileLine.substring(start,end);
				fileLine = fileLine.substring(end + 2);
			}
			else { // no...
				end = fileLine.length() - 1;
				token = fileLine.substring(start,end);
				fileLine = "";
			}
		}
		else	{ // not quoted field find next comma...
			end = fileLine.indexOf(",");
			if (end > 0)	{ // found?
				token = fileLine.substring(start,end);
				fileLine = fileLine.substring(end + 1);
			}
			else	{ // no...
				end = fileLine.length();
				token = fileLine.substring(start,end);
				fileLine = "";
			}
		}
		if (debug) Debug.logInfo("===start/end/length:" + start + "/" + end + "/" + fileLine.length() + "  token:>>" + token + "<<  rest on line:>>" +fileLine + "<<", module);
		return token;
	}
	
	/**
	 * get a line from the input file 
	 * Assuming the file has been opened by using getFile.
	 * @return the content of the line or null when no lines left
	 */
	private static String getLine() {
		String fLine = null;
		// find end of line	
		while (end < localFileString.length() && localFileString.charAt(end) != 0x0d && localFileString.charAt(end) != 0x0a) { 
//			if (end < localFile.length()-2) Debug.logInfo("char: [" +Integer.toHexString(localFile.charAt(end+1)) +  Integer.toHexString(localFile.charAt(end+2))+ "]", module);
			end++;
		}
		if (end >= localFileString.length())
			return null;
		if (debug) Debug.logInfo("Start: " + start + "    End: " + end + "  Filelength: " + localFileString.length(), module);
		fLine = localFileString.substring(start, end);
		lineNumber++;
		if (localFileString.charAt(end) == 0x0d && (localFileString.charAt(end+1) == 0x0a || localFileString.charAt(end+1) == 0x25 ))	{
			start = end + 2; // skip 0x0d and 0x0a / 0x25
			end++;  // skip the next 0x0a
		}
		else if (localFileString.charAt(end) == 0x0a) { // for a windows formatted file only 0x0a?
			start = end + 1;
		}
		end++; //look for next line
		if (debug) Debug.logInfo("Line: " + lineNumber + "  -->" + fLine, module);
		return fLine;
	}
	
	/**
	 * return content of file in static variable localFile
	 * @return 'error' is not successfull....
	 */
	private static String getFile(HttpServletRequest request)	{
		try {
			start = end = lineNumber = 0;
			
			DiskFileUpload dfu = new DiskFileUpload();
			java.util.List lst = null;
			try {
				lst = dfu.parseRequest(request);
			} catch (FileUploadException e4) {
				request.setAttribute("_ERROR_MESSAGE_", e4.getMessage());
				Debug.logError("[UploadContentAndImage.uploadContentAndImage] " + e4.getMessage(), module);
				return "error";
			}
			if (lst.size() == 0) {
				String errMsg = "Data Exchange: no files uploaded";                                                        
				request.setAttribute("_ERROR_MESSAGE_", errMsg);
				Debug.logWarning("[ImportProduct] No files uploaded", module);
				return "error";
			}
			FileItem fi = null;
             
			for (int i = 0; i < lst.size(); i++) {
				fi = (FileItem) lst.get(i);
				String fieldName = fi.getFieldName();
				Debug.logInfo("DataExchange fieldName: " + fieldName, module);
				Debug.logInfo("DataExchange in isInMem: " + fi.isInMemory(), module);
				//Debug.logInfo("DataExchange in getstring: " + fi.getString(), module);
				Debug.logInfo("DataExchange in getSize: " + fi.getSize(), module);
				Debug.logInfo("DataExchange in get: " + fi.get(), module);
				Debug.logInfo("DataExchange in getContentType: " + fi.getContentType(), module);
				Debug.logInfo("DataExchange in isFormField: " + fi.isFormField(), module);
		
				if (fi.getFieldName().equals("localFile")) {  // uploaded file found....
					localFile = fi;
					return "OK";
				}
			}
			
		} catch( Exception e) {
			Debug.logError(e, "[DataExchange] " , module);
			request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
			try {
				TransactionUtil.rollback();
			} catch(GenericTransactionException e2) {
				request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
				return "error";
			}
			return "error";
		}
		return "error";
	}
    
    public static String importHotel(HttpServletRequest request,
			HttpServletResponse response) throws GenericEntityException {
    	int serviceCounter = 0;
        int modified = 0;
        int created = 0;
        HashMap affected = new HashMap();
		delegator = (GenericDelegator) request.getAttribute("delegator");
		dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");

		if (getFile(request).equals("error") || localFile == null
				|| localFile.getSize() == 0) { // get the content of the
												// uploaded file...
			request.setAttribute("_ERROR_MESSAGE_",
							"importHotel: Uploaded file not found or an empty file......");
			return "error";
		}

		try {
			Document doc = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().newDocument();
			
			DOMResult dataRes = new DOMResult(doc);
			Source dataSrc = new StreamSource(localFile.getInputStream());
			if(transformer==null){
			Source xsltSrc = new StreamSource(importData.class.getResourceAsStream("/pt/link/utils/importer/hotel.xslt"));
//			Source xsltSrc = new StreamSource(new FileInputStream("C:/ofbiz/ofbiz/specialized/opentravelsystem/src/pt/link/utils/importer/hotel.xslt"));

			transformer = TransformerFactory.newInstance()
					.newTransformer(xsltSrc);
			}
			transformer.transform(dataSrc, dataRes);
			
/* * /if(Debug.warningOn()){
			StreamResult dataRes2 = new StreamResult(new FileOutputStream("c:/debugdata.xml"));
			Source dataSrc2 = new StreamSource(localFile.getInputStream());
			transformer.transform(dataSrc2, dataRes2);
			dataRes2.getOutputStream().close();
}/ * */	
			importImages((Document) dataRes.getNode());

			List values = delegator.makeValues((Document) dataRes.getNode());
			Set productIds = new HashSet();
			if (values != null) {
				Iterator iterator = values.iterator();
				while (iterator.hasNext()) {
					GenericValue value = (GenericValue) iterator.next();

					try {
						if (needsLocalId.contains(value.getEntityName())) {
							value.set("localId", value.getString("localId")
									.toLowerCase());
						}
						if (value.getEntityName().equals("Hotel")
								&& (value.get("locationId") == null)) {
							value.set("locationId", "_NA_");
						}
/*						if (value.getEntityName().equals("Hotel")) {
							previousHotel = value.getString("partyId");
						}
*/				
						if (value.getEntityName().equals("ContactMech")) {
//							previous = "hotel" + value.getString("contactMechType") + previousHotel;  
//							value.set("contactMechId", previous);
						}
						if (value.getEntityName().equals("PartyContactMech")) {
							//value.set("contactMechId", previous);
							value.set("fromDate", new Timestamp(System
									.currentTimeMillis()));
						}
						if (value.getEntityName().equals(
								"PartyContactMechPurpose")) {
							//value.set("contactMechId", previous);
							value.set("fromDate", new Timestamp(System
									.currentTimeMillis()));
						}
						if (value.getEntityName().equals("Hotel")
								&& (value.get("locationId") == null)) {
							value.set("locationId", "_NA_");
						}
						if (value.getEntityName().equals("FixedAsset")
								&& (value.get("productionCapacity") == null || value
										.get("productionCapacity").equals(""))) {
							value.set("productionCapacity", "0");
						}
						if (value.getEntityName().equals("Product")){
							String productId = value.getString("productId"); 
							if (productIds.contains(productId)){
								throw new IllegalArgumentException("Produto com o identificador em duplicado!!!");
							}else{
								productIds.add(productId);	
							}
						}
						if (value.getEntityName().equals("Product")
								&& (value.get("description") == null)) {
							value.set("description", "&nbsp;");
						}
						if (needsAttrName.contains(value.getEntityName())
								&& (value.get("attrName") == null)) {
							value.set("attrName", "/unknown.gif");
						}
						if (needFromDate.contains(value.getEntityName())
								&& (value.get("fromDate") == null)) {
							value.set("fromDate", new Timestamp(System
									.currentTimeMillis()));
						}
						if (value.getEntityName().equals("PartyAttribute")){
							String x = value.getString("attrName");
							if(x!=null && !x.equals("")){
                                int slash = x.lastIndexOf('/');
                                if(slash>0)
                                    x = x.substring(slash);
							} else {
								x = "unknown" + (serviceCounter++) + ".gif";
							}
							value.setString("attrName", x);
						}
					} catch (Exception e) {
                        //FIXME: this error handling cannot be right
						e.printStackTrace();
					}

					GenericValue dbVal = null;
                    
                    //TODO: this is a very naive implementation to avoid duplication of associations where fromDate is part of the key
                    if (needFromDate.contains(value.getEntityName())){
                        Map pkWithoutDate = value.getPrimaryKey().getAllFields();
                        pkWithoutDate.remove("fromDate");
                        List matches = delegator.findByAnd(value.getEntityName(),pkWithoutDate);
                        List activeMatches = EntityUtil.filterByDate(matches);
                        if(activeMatches.size()==1){
                            dbVal = (GenericValue)activeMatches.get(0);
                        } else if (activeMatches.size()==0){
                            dbVal = null;
                        } else
                            throw new IllegalStateException("found duplicate associations:" + matches + ".for:" + value);
                        
                    } else {
                        dbVal = delegator.findByPrimaryKey(value.getPrimaryKey());
                    }

                    IntCount cnt = (IntCount)affected.get(value.getEntityName());
                    if( null == cnt){
                        cnt = new IntCount();affected.put(value.getEntityName(), cnt);
                    }
                    cnt.incr();
					if (dbVal != null) {
						value.store(); modified++;
					} else {
						value.create(); created++;
					}
				}
			}

		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		} catch (TransformerException e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		} catch (GenericEntityException e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new GenericEntityException(e);
		}
        request.setAttribute("affected", affected);
        request.setAttribute("modified", new Integer(modified));
        request.setAttribute("created", new Integer(created));
        List evList = UtilMisc.toList(affected);
        evList.addAll(UtilMisc.toList(new Integer(modified),new Integer(created)));
        request.setAttribute("eventMessageList", evList);
		return "OK";
	}
    
    
    private static final Collection needFromDate = new HashSet();
    static{
    	needFromDate.add("ProdCatalogRole");
    	needFromDate.add("ProductStoreCatalog");
    	needFromDate.add("FixedAssetProduct");
        needFromDate.add("ProductCategoryMember");
        needFromDate.add("ProductCategoryRollup");
    }
    private static final Collection needsLocalId = new HashSet();
    static{
    	needsLocalId.add("LocalizedHotelDescription");
    	needsLocalId.add("LocalizedProductDesc");
    }
    private static final Collection needsAttrName = new HashSet();
    static{
    	needsAttrName.add("PartyAttribute");
    	needsAttrName.add("ProductAttribute");
    }
    
    private static void importImages(Document doc) throws GenericEntityException {
		NodeList elements = ((Element) doc.getDocumentElement())
				.getChildNodes();
		for (int i = 0; i < elements.getLength(); i++) {
			if (elements.item(i) instanceof Element) {
				Element element = (Element) elements.item(i);
				if (element.getNodeName().equals("Hotel")
						|| element.getNodeName().equals("Product")) {
					NodeList elements2 = element.getChildNodes();
					ArrayList list = new ArrayList();
					for (int j = 0; j < elements2.getLength(); j++) {
						Element element2 = (Element) elements2.item(j);
						if (element2.getFirstChild().getNodeName().equals("imagedata")){
							importImage(element2);
						} else if (element2.getFirstChild().getNodeName().equals("url")){
							importUrl(element2);
						} else {
							Debug.logWarning("Unkown image type!!!","ots");
						}
						
                        list.add(element2);
					}
					for (int j = 0; j < list.size(); j++) {
						Element element2 = (Element) list.get(j);
						element2.getParentNode().removeChild(element2);
					}
				}
			}
		}
	}

    private static void importUrl(Element src) {
		String type = src.getAttribute("urltype");
		String value = src.getFirstChild().getFirstChild().getNodeValue();
		if (!value.startsWith("http:")){
			int slash = value.lastIndexOf('/');
            if (slash>0)
                value = value.substring(slash);
		}
		((Element)src.getParentNode()).setAttribute(type, value);
	}

	private static void importImage(Element src) throws GenericEntityException {
		String imageDirName = UtilProperties.getPropertyValue("catalog", "image.server.path");
		String imageUrlPrefix = UtilProperties.getPropertyValue("catalog", "image.url.prefix");
		File imageDir = new File(imageDirName);
        
//        if(!imageDir.exists()){
//            imageDir.mkdirs();
//        }

//
		String filename = src.getAttribute("filename");
		if(filename.startsWith(imageUrlPrefix)){
			filename = filename.substring(imageUrlPrefix.length());
		}
		
		
        Element imageData=(Element)src.getFirstChild();
        
		NodeList segments = imageData.getChildNodes();
			
		StringBuffer buffer = new StringBuffer();
		for(int x=0;x < segments.getLength(); x++){
			buffer.append(segments.item(x).getNodeValue());
		}
		
		if (buffer.length()>0) {
			// Save the File
			File imageFile = new File(imageDir, filename);
			
			filename.replace('\\', '/');
			int lastIndexOfSeparator = filename.lastIndexOf("/");
			if(lastIndexOfSeparator != -1){
				String fileParent = new StringBuffer(filename).substring(0,lastIndexOfSeparator);
				File parentDir = new File(imageDir, fileParent);
				if(!parentDir.exists())
					parentDir.mkdirs();
			}
			try {
				
				OutputStream output = new FileOutputStream(imageFile, false);
				Base64.decodeToStream(buffer.toString(),output);
				output.close();
				
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				throw new GenericEntityException(e);
			} catch (IOException e) {
				e.printStackTrace();
				throw new GenericEntityException(e);
			} catch (Exception e){
				imageFile.delete();
			}
		}
	}

    private static final class IntCount {
        private int cnt = 0;
        public void incr(){cnt++;}
        public void decr(){cnt--;}
        public String toString(){return "cnt:"+cnt;}
    }
}




