/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
*  Copyright (C)
* 
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/

package org.infoglue.cmsinstaller;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.JDO;
import org.exolab.castor.mapping.Mapping;
import org.infoglue.cms.controllers.kernel.impl.simple.AvailableServiceBindingController;
import org.infoglue.cms.controllers.kernel.impl.simple.CastorDatabaseService;
import org.infoglue.cms.controllers.kernel.impl.simple.CategoryController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentTypeDefinitionController;
import org.infoglue.cms.controllers.kernel.impl.simple.ImportController;
import org.infoglue.cms.controllers.kernel.impl.simple.LanguageController;
import org.infoglue.cms.controllers.kernel.impl.simple.ServiceDefinitionController;
import org.infoglue.cms.controllers.kernel.impl.simple.SiteNodeTypeDefinitionController;
import org.infoglue.cms.entities.content.Content;
import org.infoglue.cms.entities.content.ContentCategory;
import org.infoglue.cms.entities.content.ContentVersion;
import org.infoglue.cms.entities.content.DigitalAsset;
import org.infoglue.cms.entities.content.impl.simple.ContentImpl;
import org.infoglue.cms.entities.content.impl.simple.ContentVersionImpl;
import org.infoglue.cms.entities.management.AvailableServiceBinding;
import org.infoglue.cms.entities.management.Category;
import org.infoglue.cms.entities.management.CategoryVO;
import org.infoglue.cms.entities.management.ContentTypeDefinition;
import org.infoglue.cms.entities.management.Language;
import org.infoglue.cms.entities.management.ServiceDefinition;
import org.infoglue.cms.entities.management.SiteNodeTypeDefinition;
import org.infoglue.cms.entities.management.impl.simple.AvailableServiceBindingImpl;
import org.infoglue.cms.entities.management.impl.simple.CategoryImpl;
import org.infoglue.cms.entities.management.impl.simple.ContentTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.LanguageImpl;
import org.infoglue.cms.entities.management.impl.simple.ServiceDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.SiteNodeTypeDefinitionImpl;
import org.infoglue.cms.entities.structure.Qualifyer;
import org.infoglue.cms.entities.structure.ServiceBinding;
import org.infoglue.cms.entities.structure.SiteNode;
import org.infoglue.cms.entities.structure.SiteNodeVersion;
import org.infoglue.cms.entities.structure.impl.simple.ServiceBindingImpl;
import org.infoglue.cms.entities.structure.impl.simple.SiteNodeImpl;
import org.infoglue.cms.entities.structure.impl.simple.SiteNodeVersionImpl;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.util.CmsPropertyHandler;

/**
* This class handles Importing of a site from an XML-file.
* 
* @author mattias
*/

public class InitialDataInstaller
{
	private String onlyLatestVersions = "false";
	private int version = 2;
	
    public Database getDatabase() throws Exception
    {
        try
        {
            JDO jdo = new JDO();
            jdo.setDatabaseName("INFOGLUE_CMS");
            File file = new File("localConfigs/database.xml");
            //System.out.println("file:" + file);
            jdo.setConfiguration(file.toString());
        	//jdo.setConfiguration(CastorDatabaseService.class.getResource("database.xml").toString());
            jdo.setClassLoader(CastorDatabaseService.class.getClassLoader());
            //jdo.setCallbackInterceptor(new CmsJDOCallback() );
            return jdo.getDatabase();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            throw e;
        }
    }	
    
	/**
	 * This handles the actual importing.
	 */
	
	public void importRepository(File file) throws Exception 
	{
		System.out.println("Importing file " + file.getName());

		CmsPropertyHandler.setApplicationName("cms");
	    CmsPropertyHandler.setPropertyFile(new File("classes/cms.properties"));
	    
		Database db = getDatabase();
		
		try 
		{
			Mapping map = new Mapping();
			File xmlMappingFile = new File("classes/xml_mapping_site_2.5.xml");
			//System.out.println("MappingFile:" + xmlMappingFile.toString());
			map.loadMapping(xmlMappingFile.toString());

			// All ODMG database access requires a transaction
			db.begin();
			
			//now restore the value and list what we get			
			String encoding = "UTF-8";
	        
			Map contentIdMap = new HashMap();
			Map siteNodeIdMap = new HashMap();
			List allContentIds = new ArrayList();

			ImportController.getController().importRepository(db, map, file, encoding, version, onlyLatestVersions, contentIdMap, siteNodeIdMap, allContentIds);

			System.out.println("After import repositoryCall");

			/*
			FileInputStream fis = new FileInputStream(file);
            InputStreamReader reader = new InputStreamReader(fis, encoding);
			//Reader reader = new FileReader(file);
            
            Unmarshaller unmarshaller = new Unmarshaller(map);
			unmarshaller.setWhitespacePreserve(true);
			InfoGlueExportImpl infoGlueExportImplRead = (InfoGlueExportImpl)unmarshaller.unmarshal(reader);
			Collection contentTypeDefinitions = infoGlueExportImplRead.getContentTypeDefinitions();
			Collection categories = infoGlueExportImplRead.getCategories();

			Map categoryIdMap = new HashMap();
			Map contentTypeIdMap = new HashMap();

			importCategories(categories, null, categoryIdMap, db);
			
			updateContentTypeDefinitions(contentTypeDefinitions, categoryIdMap);
			
			List readSiteNodes = infoGlueExportImplRead.getRootSiteNode();
			//SiteNode readSiteNode = infoGlueExportImplRead.getRootSiteNode();
			//logger.info(readSiteNode.getName());
			List readContents = infoGlueExportImplRead.getRootContent();
			//Content readContent = infoGlueExportImplRead.getRootContent();
			//logger.info(readContent.getName());

			Map contentIdMap = new HashMap();
			Map siteNodeIdMap = new HashMap();
			
			List allContents = new ArrayList();
			List allSiteNodes = new ArrayList();
			
			Map<String, AvailableServiceBinding> readAvailableServiceBindings = new HashMap<String, AvailableServiceBinding>();

			Iterator readSiteNodesIterator = readSiteNodes.iterator();
			while(readSiteNodesIterator.hasNext())
			{
				SiteNode readSiteNode = (SiteNode)readSiteNodesIterator.next();

				Repository repositoryRead = readSiteNode.getRepository();

				Content readContent = null;
				if(readContents != null && readContents.size() > 1)
				{
					Iterator readContentsIterator = readContents.iterator();
					while(readContentsIterator.hasNext())
					{
						Content readContentCandidate = (Content)readContentsIterator.next();
						if(readContentCandidate.getRepositoryId().equals(repositoryRead.getId()))
						{
							readContent = readContentCandidate;
							break;
						}
					}
				}
				else
				{
					readContent = (Content)readContents.get(0);
				}
				
				readContent.setRepository((RepositoryImpl)repositoryRead);

				db.create(repositoryRead);

				Collection repositoryLanguages = repositoryRead.getRepositoryLanguages();
				Iterator repositoryLanguagesIterator = repositoryLanguages.iterator();
				while(repositoryLanguagesIterator.hasNext())
				{
					RepositoryLanguage repositoryLanguage = (RepositoryLanguage)repositoryLanguagesIterator.next();
					Language originalLanguage = repositoryLanguage.getLanguage();
					
					Language language = LanguageController.getController().getLanguageWithCode(originalLanguage.getLanguageCode(), db);
					if(language == null)
					{
					    db.create(originalLanguage);
					    language = originalLanguage;
					}
					
					repositoryLanguage.setLanguage(language);
					repositoryLanguage.setRepository(repositoryRead);

					db.create(repositoryLanguage);
					
					language.getRepositoryLanguages().add(repositoryLanguage);
				}
				
				readSiteNode.setRepository((RepositoryImpl)repositoryRead);
				
				createContents(readContent, contentIdMap, contentTypeIdMap, allContents, Collections.unmodifiableCollection(contentTypeDefinitions), categoryIdMap, version, db);
				createStructure(readSiteNode, contentIdMap, siteNodeIdMap, readAvailableServiceBindings, allSiteNodes, db);
			}
						
			List allContentIds = new ArrayList();
			Iterator allContentsIterator = allContents.iterator();
			while(allContentsIterator.hasNext())
			{
				Content content = (Content)allContentsIterator.next();
				allContentIds.add(content.getContentId());
			}
			*/

			db.commit();
			db.close();
						
			Iterator allContentIdsIterator = allContentIds.iterator();
			while(allContentIdsIterator.hasNext())
			{
				Integer contentId = (Integer)allContentIdsIterator.next();
				try
				{
					db = CastorDatabaseService.getDatabase();
					db.begin();
	
					Content content = ContentController.getContentController().getContentWithId(contentId, db);
					ImportController.getController().updateContentVersions(content, contentIdMap, siteNodeIdMap, onlyLatestVersions);
					//updateContentVersions(content, contentIdMap, siteNodeIdMap);
	
					db.commit();
				}
				catch(Exception e)
				{
					try
					{
						db.rollback();
					}
					catch(Exception e2) { e2.printStackTrace(); }
				}
				finally
				{
					db.close();					
				}
			}

			//updateContentVersions(allContents, contentIdMap, siteNodeIdMap);
			
			//reader.close();
			
			//db.commit();
			//db.close();

		} 
		catch ( Exception e) 
		{
			try
            {
                db.rollback();
                db.close();
            } 
			catch (Exception e1)
            {
    			throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e);
            }
			
			throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e);
		}
		
	}

	
	private void updateContentTypeDefinitions(Collection contentTypeDefinitions, Map categoryIdMap) 
	{
		Iterator contentTypeDefinitionsIterator = contentTypeDefinitions.iterator();
		while(contentTypeDefinitionsIterator.hasNext())
		{
			ContentTypeDefinition contentTypeDefinition = (ContentTypeDefinition)contentTypeDefinitionsIterator.next();
			String schema = contentTypeDefinition.getSchemaValue();
			Iterator categoryIdMapIterator = categoryIdMap.keySet().iterator();
			while(categoryIdMapIterator.hasNext())
			{
				Integer oldId = (Integer)categoryIdMapIterator.next();
				Integer newId = (Integer)categoryIdMap.get(oldId);
				schema = schema.replaceAll("<categoryId>" + oldId + "</categoryId>", "<categoryId>new_" + newId + "</categoryId>");
			}
			schema = schema.replaceAll("<categoryId>new_", "<categoryId>");
			contentTypeDefinition.setSchemaValue(schema);
		}
	}

	private void importCategories(Collection categories, Category parentCategory, Map categoryIdMap, Database db) throws SystemException
	{
		Iterator categoryIterator = categories.iterator();
		while(categoryIterator.hasNext())
		{
			CategoryVO categoryVO = (CategoryVO)categoryIterator.next();
			Category newParentCategory = null;
			
			List existingCategories = null;
			if(parentCategory != null)
				existingCategories = CategoryController.getController().findByParent(parentCategory.getCategoryId(), db);
			else
				existingCategories = CategoryController.getController().findRootCategories(db);
				
			Iterator existingCategoriesIterator = existingCategories.iterator();
			while(existingCategoriesIterator.hasNext())
			{
				Category existingCategory = (Category)existingCategoriesIterator.next();
				if(existingCategory.getName().equals(categoryVO.getName()))
				{
					newParentCategory = existingCategory;
					break;
				}
			}

			if(newParentCategory == null)
			{
				Integer oldId = categoryVO.getId();
				categoryVO.setCategoryId(null);
				if(parentCategory != null)	
					categoryVO.setParentId(parentCategory.getCategoryId());
				else
					categoryVO.setParentId(null);
					
				Category newCategory = CategoryController.getController().save(categoryVO, db);
				categoryIdMap.put(oldId, newCategory.getCategoryId());
				newParentCategory = newCategory;
			}
			else
			{
				categoryIdMap.put(categoryVO.getId(), newParentCategory.getCategoryId());
			}
				
			importCategories(categoryVO.getChildren(), newParentCategory, categoryIdMap, db);
		}
	}
	
	/**
	 * This method copies a sitenode and all it relations.
	 * 
	 * @param siteNode
	 * @param db
	 * @throws Exception
	 */
	private void createStructure(SiteNode siteNode, Map contentIdMap, Map siteNodeIdMap, Map readAvailableServiceBindings, List allSiteNodes, Database db) throws Exception
	{
		Integer originalSiteNodeId = siteNode.getSiteNodeId();

		SiteNodeTypeDefinition originalSiteNodeTypeDefinition = siteNode.getSiteNodeTypeDefinition();
		SiteNodeTypeDefinition siteNodeTypeDefinition = null;
		if(originalSiteNodeTypeDefinition != null)
		{
			siteNodeTypeDefinition = SiteNodeTypeDefinitionController.getController().getSiteNodeTypeDefinitionWithName(siteNode.getSiteNodeTypeDefinition().getName(), db, false);
			if(siteNodeTypeDefinition == null)
			{
			    db.create(originalSiteNodeTypeDefinition);
			    siteNodeTypeDefinition = originalSiteNodeTypeDefinition;
			}
			
			siteNode.setSiteNodeTypeDefinition((SiteNodeTypeDefinitionImpl)siteNodeTypeDefinition);
		}
		
		String mappedMetaInfoContentId = "-1";
		if(siteNode.getMetaInfoContentId() != null)
		{
			if(contentIdMap.containsKey(siteNode.getMetaInfoContentId().toString()))
				mappedMetaInfoContentId = (String)contentIdMap.get(siteNode.getMetaInfoContentId().toString());
			//System.out.println("siteNode meta info content id was:" + siteNode.getMetaInfoContentId() + " and is now " + mappedMetaInfoContentId);
		}
		siteNode.setMetaInfoContentId(new Integer(mappedMetaInfoContentId));
		
		db.create(siteNode);
		
		allSiteNodes.add(siteNode);
		    
		Integer newSiteNodeId = siteNode.getSiteNodeId();
		siteNodeIdMap.put(originalSiteNodeId.toString(), newSiteNodeId.toString());
		
		Collection childSiteNodes = siteNode.getChildSiteNodes();
		if(childSiteNodes != null)
		{
			Iterator childSiteNodesIterator = childSiteNodes.iterator();
			while(childSiteNodesIterator.hasNext())
			{
				SiteNode childSiteNode = (SiteNode)childSiteNodesIterator.next();
				childSiteNode.setRepository(siteNode.getRepository());
				childSiteNode.setParentSiteNode((SiteNodeImpl)siteNode);
				createStructure(childSiteNode, contentIdMap, siteNodeIdMap, readAvailableServiceBindings, allSiteNodes, db);
			}
		}

		Collection siteNodeVersions = siteNode.getSiteNodeVersions();
		
		if(onlyLatestVersions.equalsIgnoreCase("true"))
		{
			List selectedSiteNodeVersions = new ArrayList();
			Iterator realSiteNodeVersionsIterator = siteNodeVersions.iterator();
			while(realSiteNodeVersionsIterator.hasNext())
			{
				SiteNodeVersion siteNodeVersion = (SiteNodeVersion)realSiteNodeVersionsIterator.next();			
				Iterator selectedSiteNodeVersionsIterator = selectedSiteNodeVersions.iterator();
				boolean addVersion = true;
				while(selectedSiteNodeVersionsIterator.hasNext())
				{
					SiteNodeVersion currentSiteNodeVersion = (SiteNodeVersion)selectedSiteNodeVersionsIterator.next();
					if(siteNodeVersion.getIsActive().booleanValue() && siteNodeVersion.getSiteNodeVersionId().intValue() > currentSiteNodeVersion.getSiteNodeVersionId().intValue())
					{
						selectedSiteNodeVersionsIterator.remove();
						addVersion = true;
					}						
				}
	
				if(addVersion)
					selectedSiteNodeVersions.add(siteNodeVersion);
			}	
			
			siteNodeVersions = selectedSiteNodeVersions;
		}

		Iterator siteNodeVersionsIterator = siteNodeVersions.iterator();
		while(siteNodeVersionsIterator.hasNext())
		{
			SiteNodeVersion siteNodeVersion = (SiteNodeVersion)siteNodeVersionsIterator.next();
			
			Collection serviceBindings = siteNodeVersion.getServiceBindings();

			siteNodeVersion.setOwningSiteNode((SiteNodeImpl)siteNode);
			
			db.create(siteNodeVersion);
						
			Iterator serviceBindingsIterator = serviceBindings.iterator();
			while(serviceBindingsIterator.hasNext())
			{
				ServiceBinding serviceBinding = (ServiceBinding)serviceBindingsIterator.next();
				
				ServiceDefinition originalServiceDefinition = serviceBinding.getServiceDefinition();
				String serviceDefinitionName = originalServiceDefinition.getName();
				ServiceDefinition serviceDefinition = ServiceDefinitionController.getController().getServiceDefinitionWithName(serviceDefinitionName, db, false);
				if(serviceDefinition == null)
				{
				    db.create(originalServiceDefinition);
				    serviceDefinition = originalServiceDefinition;
				    //availableServiceBinding.getServiceDefinitions().add(serviceDefinition);
				}
				
				serviceBinding.setServiceDefinition((ServiceDefinitionImpl)serviceDefinition);

				AvailableServiceBinding originalAvailableServiceBinding = serviceBinding.getAvailableServiceBinding();
				String availableServiceBindingName = originalAvailableServiceBinding.getName();
				AvailableServiceBinding availableServiceBinding = (AvailableServiceBinding)readAvailableServiceBindings.get(availableServiceBindingName);
				if(availableServiceBinding == null)
				{
					availableServiceBinding = AvailableServiceBindingController.getController().getAvailableServiceBindingWithName(availableServiceBindingName, db, false);
					readAvailableServiceBindings.put(availableServiceBindingName, availableServiceBinding);
				}
				
				if(availableServiceBinding == null)
				{
				    db.create(originalAvailableServiceBinding);
				    availableServiceBinding = originalAvailableServiceBinding;
				    readAvailableServiceBindings.put(availableServiceBindingName, availableServiceBinding);
				    
				    if(siteNodeTypeDefinition != null)
				    {
					    siteNodeTypeDefinition.getAvailableServiceBindings().add((AvailableServiceBindingImpl)availableServiceBinding);
					    serviceDefinition.getAvailableServiceBindings().add((AvailableServiceBindingImpl)availableServiceBinding);
					    availableServiceBinding.getSiteNodeTypeDefinitions().add((SiteNodeTypeDefinitionImpl)siteNodeTypeDefinition);
					    availableServiceBinding.getServiceDefinitions().add((ServiceDefinitionImpl)serviceDefinition);
				    }
				}
				else
				{
					if(siteNodeTypeDefinition != null && !siteNodeTypeDefinition.getAvailableServiceBindings().contains(availableServiceBinding))
					{
						siteNodeTypeDefinition.getAvailableServiceBindings().add((AvailableServiceBindingImpl)availableServiceBinding);
						availableServiceBinding.getSiteNodeTypeDefinitions().add(siteNodeTypeDefinition);
					}
				}
				
				serviceBinding.setAvailableServiceBinding((AvailableServiceBindingImpl)availableServiceBinding);
				
				
				Collection qualifyers = serviceBinding.getBindingQualifyers();
				Iterator qualifyersIterator = qualifyers.iterator();
				while(qualifyersIterator.hasNext())
				{
					Qualifyer qualifyer = (Qualifyer)qualifyersIterator.next();
					qualifyer.setServiceBinding((ServiceBindingImpl)serviceBinding);
					
					String entityName 	= qualifyer.getName();
					String entityId		= qualifyer.getValue();
					
					if(entityName.equalsIgnoreCase("contentId"))
					{
						String mappedContentId = (String)contentIdMap.get(entityId);
						qualifyer.setValue((mappedContentId == null) ? entityId : mappedContentId);
					}
					else if(entityName.equalsIgnoreCase("siteNodeId"))
					{
						String mappedSiteNodeId = (String)siteNodeIdMap.get(entityId);
						qualifyer.setValue((mappedSiteNodeId == null) ? entityId : mappedSiteNodeId);						
					}
				}

				serviceBinding.setSiteNodeVersion((SiteNodeVersionImpl)siteNodeVersion);				

				db.create(serviceBinding);

			}
		}		
		
	}


	/**
	 * This method copies a content and all it relations.
	 * 
	 * @param siteNode
	 * @param db
	 * @throws Exception
	 */
	
	private List createContents(Content content, Map idMap, Map contentTypeDefinitionIdMap, List allContents, Collection contentTypeDefinitions, Map categoryIdMap, int version, Database db) throws Exception
	{
		ContentTypeDefinition contentTypeDefinition = null;
		
	    Integer originalContentId = content.getContentId();
	    if(version == 2)
	    {
		    Integer contentTypeDefinitionId = ((ContentImpl)content).getContentTypeDefinitionId();
		    
    		if(contentTypeDefinitionId != null)
			{
    			if(contentTypeDefinitionIdMap.containsKey(contentTypeDefinitionId))
    				contentTypeDefinitionId = (Integer)contentTypeDefinitionIdMap.get(contentTypeDefinitionId);
    				
		    	ContentTypeDefinition originalContentTypeDefinition = null;
		    	Iterator contentTypeDefinitionsIterator = contentTypeDefinitions.iterator();
		    	while(contentTypeDefinitionsIterator.hasNext())
		    	{
		    		ContentTypeDefinition contentTypeDefinitionCandidate = (ContentTypeDefinition)contentTypeDefinitionsIterator.next();		    		
		    		if(contentTypeDefinitionCandidate.getId().intValue() == contentTypeDefinitionId.intValue())
		    		{
		    			originalContentTypeDefinition = contentTypeDefinitionCandidate;
		    			break;
		    		}
		    	}

		    	//System.out.println("originalContentTypeDefinition:" + originalContentTypeDefinition);

		    	if(originalContentTypeDefinition != null)
		    	{
			    	contentTypeDefinition = ContentTypeDefinitionController.getController().getContentTypeDefinitionWithName(originalContentTypeDefinition.getName(), db);

			    	if(contentTypeDefinition == null)
					{
			    		Integer before = originalContentTypeDefinition.getId();
			    		db.create(originalContentTypeDefinition);
			    		contentTypeDefinition = originalContentTypeDefinition;
			    		Integer after = originalContentTypeDefinition.getId();
			    		contentTypeDefinitionIdMap.put(before, after);
			    	}
				
		    		content.setContentTypeDefinition((ContentTypeDefinitionImpl)contentTypeDefinition);

		    	}
			    else
			    	System.out.println("The content " + content.getName() + " had a content type not found amongst the listed ones:" + contentTypeDefinitionId);
			}
		    else
		    	System.out.println("The content " + content.getName() + " had no content type at all");
	    }
	    else if(version == 1)
	    {
			ContentTypeDefinition originalContentTypeDefinition = content.getContentTypeDefinition();
			if(originalContentTypeDefinition != null)
			{
			    contentTypeDefinition = ContentTypeDefinitionController.getController().getContentTypeDefinitionWithName(originalContentTypeDefinition.getName(), db);
				if(contentTypeDefinition == null)
				{
		    		//contentTypeDefinition = ContentTypeDefinitionController.getController().create(originalContentTypeDefinition.getValueObject(), db);
		    		//contentTypeDefinitions.add(contentTypeDefinition);
		    		
				    db.create(originalContentTypeDefinition);
				    contentTypeDefinition = originalContentTypeDefinition;
				}

	    		content.setContentTypeDefinition((ContentTypeDefinitionImpl)contentTypeDefinition);
			}
	    }
	    
	    if(content.getContentTypeDefinition() == null)
	    	System.err.println("No content type definition for content:" + content.getId());
	    
	    System.out.println("Creating content:" + content.getName() + ":" + content.getId());
	    //if(!db.isPersistent(content))
	    	db.create(content);
		
		allContents.add(content);
		
		Integer newContentId = content.getContentId();
		idMap.put(originalContentId.toString(), newContentId.toString());
		
		Collection contentVersions = content.getContentVersions();
	    
		if(onlyLatestVersions.equalsIgnoreCase("true"))
		{
			List selectedContentVersions = new ArrayList();
			Iterator realContentVersionsIterator = contentVersions.iterator();
			while(realContentVersionsIterator.hasNext())
			{
				ContentVersion contentVersion = (ContentVersion)realContentVersionsIterator.next();			
				Iterator selectedContentVersionsIterator = selectedContentVersions.iterator();
				boolean addLanguageVersion = true;
				boolean noLanguageVersionFound = true;
				while(selectedContentVersionsIterator.hasNext())
				{
					ContentVersion currentContentVersion = (ContentVersion)selectedContentVersionsIterator.next();
					if(currentContentVersion.getLanguage().getLanguageCode().equals(contentVersion.getLanguage().getLanguageCode()))
					{
						noLanguageVersionFound = false;
						
						if(contentVersion.getIsActive().booleanValue() && contentVersion.getContentVersionId().intValue() > currentContentVersion.getContentVersionId().intValue())
						{
							selectedContentVersionsIterator.remove();
							addLanguageVersion = true;
						}						
					}
				}
	
				if(addLanguageVersion || noLanguageVersionFound)
					selectedContentVersions.add(contentVersion);
			}	
			
			contentVersions = selectedContentVersions;
		}
		
		Iterator contentVersionsIterator = contentVersions.iterator();
		while(contentVersionsIterator.hasNext())
		{
			ContentVersion contentVersion = (ContentVersion)contentVersionsIterator.next();
			Language language = LanguageController.getController().getLanguageWithCode(contentVersion.getLanguage().getLanguageCode(), db);

			contentVersion.setOwningContent((ContentImpl)content);
			contentVersion.setLanguage((LanguageImpl)language);
			
			Collection digitalAssets = contentVersion.getDigitalAssets();
			if(digitalAssets != null)
			{
				List initialDigitalAssets = new ArrayList();
					
				Iterator digitalAssetsIterator = digitalAssets.iterator();
				while(digitalAssetsIterator.hasNext())
				{
					DigitalAsset digitalAsset = (DigitalAsset)digitalAssetsIterator.next();
					
					List initialContentVersions = new ArrayList();
					initialContentVersions.add(contentVersion);
					digitalAsset.setContentVersions(initialContentVersions);
					
					//if(!db.isPersistent(digitalAsset))
						db.create(digitalAsset);
					
					initialDigitalAssets.add(digitalAsset);
				}
				
				contentVersion.setDigitalAssets(initialDigitalAssets);
			}

			Collection contentCategories = contentVersion.getContentCategories();
			
			//if(!db.isPersistent(contentVersion))
				db.create(contentVersion);
			
			if(contentCategories != null)
			{
				List initialContentCategories = new ArrayList();
					
				Iterator contentCategoriesIterator = contentCategories.iterator();
				while(contentCategoriesIterator.hasNext())
				{
					ContentCategory contentCategory = (ContentCategory)contentCategoriesIterator.next();
					contentCategory.setContentVersion((ContentVersionImpl)contentVersion);
					
					Integer oldCategoryId = contentCategory.getCategoryId();
					Integer newCategoryId = (Integer)categoryIdMap.get(oldCategoryId);
					if(newCategoryId == null)
						newCategoryId = oldCategoryId;
					
					if(newCategoryId != null)
					{
						Category category = CategoryController.getController().findById(newCategoryId, db);
						if(category != null)
						{
							contentCategory.setCategory((CategoryImpl)category);
							
							//if(!db.isPersistent(contentCategory))
								db.create(contentCategory);
						
							initialContentCategories.add(contentCategory);
						}
					}
				}
				
				contentVersion.setContentCategories(initialContentCategories);
			}

		}		
		
		Collection childContents = content.getChildren();
		if(childContents != null)
		{
			Iterator childContentsIterator = childContents.iterator();
			while(childContentsIterator.hasNext())
			{
				Content childContent = (Content)childContentsIterator.next();
				childContent.setRepository(content.getRepository());
				childContent.setParentContent((ContentImpl)content);
				createContents(childContent, idMap, contentTypeDefinitionIdMap, allContents, contentTypeDefinitions, categoryIdMap, version, db);
			}
		}
		
		return allContents;
	}
	
	/**
	 * This method updates all the bindings in content-versions to reflect the move. 
	 */
	private void updateContentVersions(Content content, Map contentIdMap, Map siteNodeIdMap) throws Exception
	{
	    Collection contentVersions = content.getContentVersions();
	        
		if(onlyLatestVersions.equalsIgnoreCase("true"))
		{
			List selectedContentVersions = new ArrayList();
			Iterator realContentVersionsIterator = contentVersions.iterator();
			while(realContentVersionsIterator.hasNext())
			{
				ContentVersion contentVersion = (ContentVersion)realContentVersionsIterator.next();			
				Iterator selectedContentVersionsIterator = selectedContentVersions.iterator();
				boolean addLanguageVersion = true;
				boolean noLanguageVersionFound = true;
				while(selectedContentVersionsIterator.hasNext())
				{
					ContentVersion currentContentVersion = (ContentVersion)selectedContentVersionsIterator.next();
					if(currentContentVersion.getLanguage().getLanguageCode().equals(contentVersion.getLanguage().getLanguageCode()))
					{
						noLanguageVersionFound = false;
						
						if(contentVersion.getIsActive().booleanValue() && contentVersion.getContentVersionId().intValue() > currentContentVersion.getContentVersionId().intValue())
						{
							selectedContentVersionsIterator.remove();
							addLanguageVersion = true;
						}						
					}
				}
	
				if(addLanguageVersion || noLanguageVersionFound)
					selectedContentVersions.add(contentVersion);
			}	
			
			contentVersions = selectedContentVersions;
		}

        
        Iterator contentVersionIterator = contentVersions.iterator();
        while(contentVersionIterator.hasNext())
        {
            ContentVersion contentVersion = (ContentVersion)contentVersionIterator.next();
            String contentVersionValue = contentVersion.getVersionValue();

            contentVersionValue = contentVersionValue.replaceAll("contentId=\"", "contentId=\"oldContentId_");
            contentVersionValue = contentVersionValue.replaceAll("\\?contentId=", "\\?contentId=oldContentId_");
            contentVersionValue = contentVersionValue.replaceAll("getInlineAssetUrl\\(", "getInlineAssetUrl\\(oldContentId_");
            contentVersionValue = contentVersionValue.replaceAll("languageId,", "languageId,oldContentId_");
            contentVersionValue = contentVersionValue.replaceAll("entity=\"Content\" entityId=\"", "entity=\"Content\" entityId=\"oldContentId_");
            //contentVersionValue = contentVersionValue.replaceAll("entity='Content'><id>", "entity='Content'><id>oldContentId_");
            contentVersionValue = contentVersionValue.replaceAll("siteNodeId=\"", "siteNodeId=\"oldSiteNodeId_");
            contentVersionValue = contentVersionValue.replaceAll("getPageUrl\\((\\d)", "getPageUrl\\(oldSiteNodeId_$1");
            contentVersionValue = contentVersionValue.replaceAll("entity=\"SiteNode\" entityId=\"", "entity=\"SiteNode\" entityId=\"oldSiteNodeId_");
            //contentVersionValue = contentVersionValue.replaceAll("entity='SiteNode'><id>", "entity='SiteNode'><id>old_");

            contentVersionValue = this.prepareAllRelations(contentVersionValue);
            	            
            
            //logger.info("contentVersionValue before:" + contentVersionValue);
            
            Iterator contentIdMapIterator = contentIdMap.keySet().iterator();
            while (contentIdMapIterator.hasNext()) 
            {
                String oldContentId = (String)contentIdMapIterator.next();
                String newContentId = (String)contentIdMap.get(oldContentId);
                
                //logger.info("Replacing all:" + oldContentId + " with " + newContentId);
                
                contentVersionValue = contentVersionValue.replaceAll("contentId=\"oldContentId_" + oldContentId + "\"", "contentId=\"" + newContentId + "\"");
                contentVersionValue = contentVersionValue.replaceAll("\\?contentId=oldContentId_" + oldContentId + "&", "\\?contentId=" + newContentId + "&");
                contentVersionValue = contentVersionValue.replaceAll("getInlineAssetUrl\\(oldContentId_" + oldContentId + ",", "getInlineAssetUrl\\(" + newContentId + ",");
                contentVersionValue = contentVersionValue.replaceAll("languageId,oldContentId_" + oldContentId + "\\)", "languageId," + newContentId + "\\)");
                contentVersionValue = contentVersionValue.replaceAll("entity=\"Content\" entityId=\"oldContentId_" + oldContentId + "\"", "entity=\"Content\" entityId=\"" + newContentId + "\"");
                contentVersionValue = contentVersionValue.replaceAll("<id>oldContentId_" + oldContentId + "</id>", "<id>" + newContentId + "</id>");
                //contentVersionValue = contentVersionValue.replaceAll("entity='Content'><id>old_" + oldContentId + "</id>", "entity='Content'><id>" + newContentId + "</id>");
                //contentVersionValue = contentVersionValue.replaceAll("<id>" + oldContentId + "</id>", "<id>" + newContentId + "</id>");
            }
            
            Iterator siteNodeIdMapIterator = siteNodeIdMap.keySet().iterator();
            while (siteNodeIdMapIterator.hasNext()) 
            {
                String oldSiteNodeId = (String)siteNodeIdMapIterator.next();
                String newSiteNodeId = (String)siteNodeIdMap.get(oldSiteNodeId);
                
                //logger.info("Replacing all:" + oldSiteNodeId + " with " + newSiteNodeId);
                
                contentVersionValue = contentVersionValue.replaceAll("siteNodeId=\"oldSiteNodeId_" + oldSiteNodeId + "\"", "siteNodeId=\"" + newSiteNodeId + "\"");
                contentVersionValue = contentVersionValue.replaceAll("getPageUrl\\(oldSiteNodeId_" + oldSiteNodeId + ",", "getPageUrl\\(" + newSiteNodeId + ",");
                contentVersionValue = contentVersionValue.replaceAll("entity=\"SiteNode\" entityId=\"oldSiteNodeId_" + oldSiteNodeId + "\"", "entity=\"SiteNode\" entityId=\"" + newSiteNodeId + "\"");
                //contentVersionValue = contentVersionValue.replaceAll("entity='SiteNode'><id>old_" + oldSiteNodeId + "</id>", "entity='SiteNode'><id>" + newSiteNodeId + "</id>");
                contentVersionValue = contentVersionValue.replaceAll("<id>oldSiteNodeId_" + oldSiteNodeId + "</id>", "<id>" + newSiteNodeId + "</id>");
            }
            
            //logger.info("contentVersionValue after:" + contentVersionValue);
            
            //Now replace all occurrances of old as they should never be there.
            contentVersionValue = contentVersionValue.replaceAll("oldContentId_", "");
            contentVersionValue = contentVersionValue.replaceAll("oldSiteNodeId_", "");

            contentVersion.setVersionValue(contentVersionValue);
        }
	}

	private String prepareAllRelations(String xml) throws Exception
	{
		StringBuffer newXML = new StringBuffer();
		
    	String after = xml;
    	String before = "";
    	String qualifyer = "";
    	boolean changed = false; 
    	
    	int startIndex = xml.indexOf("<qualifyer");
    	while(startIndex > -1)
    	{
    		int stopIndex = xml.indexOf("</qualifyer>", startIndex);
    		if(stopIndex > -1)
    		{
    			changed = true;
	    		before = xml.substring(0, startIndex);
	    		after = xml.substring(stopIndex + 12);
	    		qualifyer = xml.substring(startIndex, stopIndex + 12);
	    		//logger.info("startIndex: " + startIndex);
	    		//System.out.println("stopIndex: " + stopIndex);
	    		//System.out.println("before: " + before);
	    		//System.out.println("after: " + after);
	    		//System.out.println("qualifyer: " + qualifyer);
	    		
	    		String newQualifyer = qualifyer;
	    		
	    		if(qualifyer.indexOf("entity='Content'") > 0)
	    			newQualifyer = qualifyer.replaceAll("<id>", "<id>oldContentId_");
	    		else if(qualifyer.indexOf("entity='SiteNode'") > 0)
	    			newQualifyer = qualifyer.replaceAll("<id>", "<id>oldSiteNodeId_");
	    			
	    		newXML.append(before);
	    		newXML.append(newQualifyer);
	    		//System.out.println("newXML:" + newXML);
	    		xml = after;
    		}
    		else
    		{
    			throw new Exception("Error in xml - qualifyer tag broken in " + xml);
    		}
    		
    		startIndex = xml.indexOf("<qualifyer");
    	}

		newXML.append(after);
		
		//if(changed)
		//	System.out.println("newXML:" + newXML);
		
		return newXML.toString();
	}
	
	public String getOnlyLatestVersions() {
		return "false";
	}

}
