From b9fa952956d5b3f4f01cdd6b3b56a6434c858e74 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 28 Aug 2012 09:19:43 +0200
Subject: [PATCH] OO-292: rewrite the import for eportfolio with a xslt
 transformation to remove conflicting resources as user proeprties,
 artefacts... make the standard xstream more robust to transform hibernate
 collections in standard ones, make it robust to the package changes within
 hibernate

---
 .../olat/core/util/xml/EnhancedMapper.java    |  14 +-
 .../olat/core/util/xml/EnhancedXStream.java   |  77 +++++++++
 .../java/org/olat/core/util/xml/Util.java     |  81 ----------
 .../olat/core/util/xml/XMLPrettyPrinter.java  | 129 ---------------
 .../org/olat/core/util/xml/XStreamHelper.java |  12 +-
 .../ImportPortfolioReferencesController.java  |   4 +-
 src/main/java/org/olat/package-cleanup.txt    |  25 ---
 .../portfolio/manager/EPFrontendManager.java  |   1 -
 .../portfolio/manager/EPStructureManager.java |   3 +
 .../portfolio/manager/EPXStreamHandler.java   | 150 ++++++++++++++++++
 .../manager/portfolio_without_artefacts.xsl   |  10 ++
 .../repository/handlers/PortfolioHandler.java |  75 ++-------
 .../olat/portfolio/EPFrontendManagerTest.java |   1 +
 .../java/org/olat/portfolio/EPImportTest.java |  67 ++++++++
 .../java/org/olat/portfolio/map_81.xml.zip    | Bin 0 -> 2584 bytes
 .../java/org/olat/test/AllTestsJunit4.java    |   1 +
 16 files changed, 328 insertions(+), 322 deletions(-)
 create mode 100644 src/main/java/org/olat/core/util/xml/EnhancedXStream.java
 delete mode 100644 src/main/java/org/olat/core/util/xml/Util.java
 delete mode 100644 src/main/java/org/olat/core/util/xml/XMLPrettyPrinter.java
 delete mode 100644 src/main/java/org/olat/package-cleanup.txt
 create mode 100644 src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java
 create mode 100644 src/main/java/org/olat/portfolio/manager/portfolio_without_artefacts.xsl
 create mode 100644 src/test/java/org/olat/portfolio/EPImportTest.java
 create mode 100644 src/test/java/org/olat/portfolio/map_81.xml.zip

diff --git a/src/main/java/org/olat/core/util/xml/EnhancedMapper.java b/src/main/java/org/olat/core/util/xml/EnhancedMapper.java
index 90979e61f08..636c1c2a1ab 100644
--- a/src/main/java/org/olat/core/util/xml/EnhancedMapper.java
+++ b/src/main/java/org/olat/core/util/xml/EnhancedMapper.java
@@ -21,6 +21,7 @@ package org.olat.core.util.xml;
 
 import org.hibernate.collection.internal.PersistentBag;
 import org.hibernate.collection.internal.PersistentList;
+import org.hibernate.collection.internal.PersistentMap;
 
 import com.thoughtworks.xstream.mapper.MapperWrapper;
 
@@ -42,19 +43,10 @@ public class EnhancedMapper extends MapperWrapper {
 			return PersistentBag.class;
 		} else if("org.hibernate.collection.PersistentList".equals(elementName)) {
 			return PersistentList.class;
+		} else if("org.hibernate.collection.PersistentMap".equals(elementName)) {
+			return PersistentMap.class;
 		} else {
 			return super.realClass(elementName);
 		}
 	}
-	
-	@SuppressWarnings("rawtypes")
-	public String serializedClass(final Class type) {
-		if(PersistentBag.class.equals(type)) {
-			return "org.hibernate.collection.PersistentBag";
-		} else if(PersistentList.class.equals(type)) {
-			return "org.hibernate.collection.PersistentList";
-		} else {
-			return super.serializedClass(type);
-		}
-	}
 }
diff --git a/src/main/java/org/olat/core/util/xml/EnhancedXStream.java b/src/main/java/org/olat/core/util/xml/EnhancedXStream.java
new file mode 100644
index 00000000000..6edcaadcea6
--- /dev/null
+++ b/src/main/java/org/olat/core/util/xml/EnhancedXStream.java
@@ -0,0 +1,77 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.core.util.xml;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.hibernate.collection.internal.PersistentBag;
+import org.hibernate.collection.internal.PersistentList;
+import org.hibernate.collection.internal.PersistentMap;
+import org.hibernate.collection.internal.PersistentSet;
+import org.hibernate.collection.internal.PersistentSortedMap;
+import org.hibernate.collection.internal.PersistentSortedSet;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.collections.CollectionConverter;
+import com.thoughtworks.xstream.converters.collections.MapConverter;
+import com.thoughtworks.xstream.mapper.MapperWrapper;
+
+/**
+ * This implmentation of XStream automatically convert hibernat list, set and map
+ * to standard java collections and convert by import / deserialization
+ * the old hibernate 3 collection packages to the new one.
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class EnhancedXStream extends XStream  {
+	
+	public EnhancedXStream() {
+		super();
+		
+		addDefaultImplementation(PersistentList.class, List.class);
+		addDefaultImplementation(PersistentBag.class, List.class);
+		addDefaultImplementation(PersistentMap.class, Map.class);
+		addDefaultImplementation(PersistentSortedMap.class, Map.class);
+		addDefaultImplementation(PersistentSet.class, Set.class);
+		addDefaultImplementation(PersistentSortedSet.class, Set.class);
+		addDefaultImplementation(ArrayList.class, List.class);
+		
+		registerConverter(new CollectionConverter(getMapper()) {
+		    public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+		        return PersistentList.class == type || PersistentBag.class == type;
+		    }
+		});
+		
+		registerConverter(new MapConverter(getMapper()) {
+		  public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+		    return PersistentMap.class == type;
+		  }
+		});
+	}
+	
+	@Override
+	protected MapperWrapper wrapMapper(MapperWrapper next) {
+		return new EnhancedMapper(next);
+	}
+	
+}
diff --git a/src/main/java/org/olat/core/util/xml/Util.java b/src/main/java/org/olat/core/util/xml/Util.java
deleted file mode 100644
index ec9dd25d270..00000000000
--- a/src/main/java/org/olat/core/util/xml/Util.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.  
-* <p>
-*/ 
-package org.olat.core.util.xml;
-
-import java.beans.XMLEncoder;
-import java.io.BufferedOutputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.util.Iterator;
-import java.util.List;
-
-import org.dom4j.Element;
-import org.olat.core.logging.OLATRuntimeException;
-
-/**
- * enclosing_type Description: <br>
- * 
- * @author Felix Jost
- */
-public class Util {
-
-	/**
-	 * @param o
-	 * @param file
-	 */
-	public static void writeObjectAsXML(Object o, String file) {
-
-		XMLEncoder e;
-		try {
-			e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(file)));
-			e.writeObject(o);
-			e.close();
-		} catch (FileNotFoundException e1) {
-			throw new OLATRuntimeException(Util.class, "Error writing object to XML.", e1);
-		}
-
-	}
-
-	/**
-	 * @param elem
-	 * @return String
-	 */
-	public static String getTextsOnly(Element elem) {
-		StringBuilder sb = new StringBuilder();
-		visit(sb, elem);
-		return sb.toString();
-	}
-
-	private static void visit(StringBuilder sb, Element elem) {
-		sb.append(elem.getTextTrim());
-		List children = elem.elements();
-		for (Iterator it_ch = children.iterator(); it_ch.hasNext();) {
-			Element element = (Element) it_ch.next();
-			visit(sb, element);
-		}
-	}
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/util/xml/XMLPrettyPrinter.java b/src/main/java/org/olat/core/util/xml/XMLPrettyPrinter.java
deleted file mode 100644
index 0405e5c3c37..00000000000
--- a/src/main/java/org/olat/core/util/xml/XMLPrettyPrinter.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.  
-* <p>
-*/ 
-
-package org.olat.core.util.xml;
-
-
-/**
- * Description:<br>
- * TODO: Felix Class Description for XMLPrettyPrinter
- * <P>
- * Initial Date: 09.09.2005 <br>
- * 
- * @author Felix
- */
-public class XMLPrettyPrinter {
-/*
-	public static String prettyPrint(String in) {
-		StringBuilder sb = new StringBuilder();
-		DefaultHandler handler = new SAXIndent(sb);
-		// Parse the input with the default (non-validating) parser
-		SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
-		saxParser.parse(new InputSource(new StringReader(in)), handler);
-		try {
-			StringWriter sw = new StringWriter();
-			Transformer t = TransformerFactory.newInstance().newTransformer();
-			t.setOutputProperty(OutputKeys.INDENT, "yes");
-			t.setOutputProperty(OutputKeys.METHOD, "xml");	
-			t.setOutputProperty(OutputKeys.STANDALONE, "yes");	
-			t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");	
-			
-			t.transform(new StreamSource(new StringReader(componentListenerInfo)), new StreamResult(sw));
-			String res = sw.getBuffer().toString();
-			componentListenerInfo = res;
-		} catch (Exception e) {
-			// ignore
-		}
-		String r = componentListenerInfo;
-	}
-*/
-}
-/*
-class SAXIndent extends DefaultHandler {
-	private static String sNEWLINE = "\n";
-	private StringBuilder sb;
-
-	SAXIndent(StringBuilder sb) {
-		this.sb = sb;
-	}
-
-	public void startDocument() throws SAXException {
-		echoString(sNEWLINE + "<?xml ...?>" + sNEWLINE + sNEWLINE);
-	}
-
-	public void endDocument() throws SAXException {
-		echoString(sNEWLINE);
-	}
-
-	public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException {
-		echoTextBuffer();
-		String eName = ("".equals(localName)) ? qName : localName;
-		echoString("<" + eName); // element name
-		if (attrs != null) {
-			for (int i = 0; i < attrs.getLength(); i++) {
-				String aName = attrs.getLocalName(i); // Attr name
-				if ("".equals(aName)) aName = attrs.getQName(i);
-				echoString(" " + aName + "=\"" + attrs.getValue(i) + "\"");
-			}
-		}
-		echoString(">");
-	}
-
-	public void endElement(String namespaceURI, String localName, // local name
-			String qName) // qualified name
-			throws SAXException {
-		echoTextBuffer();
-		String eName = ("".equals(localName)) ? qName : localName;
-		echoString("</" + eName + ">"); // element name
-	}
-
-	public void characters(char[] buf, int offset, int len) throws SAXException {
-		String s = new String(buf, offset, len);
-		sb.append(s);
-	}
-
-	// ---- Helper methods ----
-
-	// Display text accumulated in the character buffer
-	private void echoTextBuffer() throws SAXException {
-		if (textBuffer == null) return;
-		echoString(textBuffer.toString());
-		textBuffer = null;
-	}
-
-	// Wrap I/O exceptions in SAX exceptions, to
-	// suit handler signature requirements
-	private void echoString(String s) throws SAXException {
-		try {
-			if (null == out) out = new OutputStreamWriter(System.out, "UTF8");
-			out.write(s);
-			out.flush();
-		} catch (IOException ex) {
-			throw new SAXException("I/O error", ex);
-		}
-	}
-}
-*/
diff --git a/src/main/java/org/olat/core/util/xml/XStreamHelper.java b/src/main/java/org/olat/core/util/xml/XStreamHelper.java
index 9cc6dd8fd31..baafef39b8d 100644
--- a/src/main/java/org/olat/core/util/xml/XStreamHelper.java
+++ b/src/main/java/org/olat/core/util/xml/XStreamHelper.java
@@ -40,7 +40,6 @@ import org.olat.core.util.FileUtils;
 import org.olat.core.util.vfs.VFSLeaf;
 
 import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.mapper.MapperWrapper;
 
 /**
  * Description:<br>
@@ -225,7 +224,8 @@ public class XStreamHelper {
 	 * writing to a configured XML mapping
 	 */
 	public static XStream createXStreamInstance() {
-		return new EnhancedXStream();
+		EnhancedXStream xstream = new EnhancedXStream();
+		return xstream;
 	}
 
 	/**
@@ -379,12 +379,4 @@ public class XStreamHelper {
 			FileUtils.closeSafely(os);
 		}
 	}
-	
-	private static class EnhancedXStream extends XStream {
-		@Override
-		protected MapperWrapper wrapMapper(MapperWrapper next) {
-			return new EnhancedMapper(next);
-		}
-	}
-
 }
diff --git a/src/main/java/org/olat/course/repository/ImportPortfolioReferencesController.java b/src/main/java/org/olat/course/repository/ImportPortfolioReferencesController.java
index d386470e3e0..4b3bfacf777 100644
--- a/src/main/java/org/olat/course/repository/ImportPortfolioReferencesController.java
+++ b/src/main/java/org/olat/course/repository/ImportPortfolioReferencesController.java
@@ -50,6 +50,7 @@ import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.portfolio.PortfolioCourseNodeEditController;
 import org.olat.portfolio.EPTemplateMapResource;
 import org.olat.portfolio.manager.EPFrontendManager;
+import org.olat.portfolio.manager.EPXStreamHandler;
 import org.olat.portfolio.model.structel.EPStructuredMapTemplate;
 import org.olat.portfolio.model.structel.PortfolioStructure;
 import org.olat.portfolio.model.structel.PortfolioStructureMap;
@@ -59,7 +60,6 @@ import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.RepositoryTableModel;
 import org.olat.repository.controllers.RepositorySearchController;
-import org.olat.repository.handlers.PortfolioHandler;
 import org.olat.repository.handlers.RepositoryHandler;
 import org.olat.repository.handlers.RepositoryHandlerFactory;
 import org.olat.resource.OLATResource;
@@ -174,7 +174,7 @@ public class ImportPortfolioReferencesController extends BasicController {
 	public static RepositoryEntry doImport(RepositoryEntryImportExport importExport, CourseNode node, boolean keepSoftkey,
 			Identity owner) {
 		File fExportedFile = importExport.importGetExportedFile();
-		PortfolioStructure structure = PortfolioHandler.getAsObject(fExportedFile);
+		PortfolioStructure structure = EPXStreamHandler.getAsObject(fExportedFile, false);
 		if(structure == null) {
 			log.warn("Error adding portfolio map resource during repository reference import: " + importExport.getDisplayName());
 			return null;
diff --git a/src/main/java/org/olat/package-cleanup.txt b/src/main/java/org/olat/package-cleanup.txt
deleted file mode 100644
index a6b04183631..00000000000
--- a/src/main/java/org/olat/package-cleanup.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Entfernen aller versions etc. Tags die beim mergen Konflikte bereiten und eh überflüssig sind:
-
-1) Paket selektieren und auf Search gehen
-2) File search nach ^ *\*.*\$:*$ (regexp enablen)
-3) Nicht suchen sondern replace drücken
-4) Jede gefundene Stelle duchsteppen und ersetzen mit nichts
-5) Refresh (F5)
-6) Synchronize, outgoing changes
-7) Jeden change anschauen und die Leerzeile weglöschen. So hat man grad 
-   die Kontrolle dass alles korrekt gelöscht ist. Zudem immer schauen ob Tags vergessen
-   gegangen sind (Ein paar werden mit der regexp nicht gefunden)
-8) Checkin
-
-
-Packages (inklusive subpackages)
-
-PACKAGE			WER		STATUS
--------------------------------
-admin			fg		done
-basesecurity		fg		done
-bookmark			fg		done
-catalog			fg		done
-collaboration	fg		done
-configuration	fg		done
-org.olat.gui.components fj done
diff --git a/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java b/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java
index 1e6888537c0..b9a5dd5ac3e 100755
--- a/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java
+++ b/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java
@@ -28,7 +28,6 @@ import java.util.Map;
 import java.util.Set;
 
 import org.olat.basesecurity.BaseSecurity;
-import org.olat.basesecurity.BaseSecurityManager;
 import org.olat.basesecurity.Constants;
 import org.olat.basesecurity.IdentityShort;
 import org.olat.basesecurity.Policy;
diff --git a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
index 91f4c90b063..5956f4f2bd5 100755
--- a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
+++ b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
@@ -1877,6 +1877,9 @@ public class EPStructureManager extends BasicManager {
 	
 
 	private static class KeyStructureToStructureLinkComparator implements Comparator<EPStructureToStructureLink>, Serializable {
+
+		private static final long serialVersionUID = 366101659547497002L;
+
 		public KeyStructureToStructureLinkComparator() {
 			//
 		}
diff --git a/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java b/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java
new file mode 100644
index 00000000000..c4a2dec75fd
--- /dev/null
+++ b/src/main/java/org/olat/portfolio/manager/EPXStreamHandler.java
@@ -0,0 +1,150 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.portfolio.manager;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.io.IOUtils;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.xml.XStreamHelper;
+import org.olat.portfolio.model.restriction.CollectRestriction;
+import org.olat.portfolio.model.structel.EPAbstractMap;
+import org.olat.portfolio.model.structel.EPDefaultMap;
+import org.olat.portfolio.model.structel.EPPage;
+import org.olat.portfolio.model.structel.EPStructureElement;
+import org.olat.portfolio.model.structel.EPStructureToArtefactLink;
+import org.olat.portfolio.model.structel.EPStructureToStructureLink;
+import org.olat.portfolio.model.structel.EPStructuredMap;
+import org.olat.portfolio.model.structel.EPStructuredMapTemplate;
+import org.olat.portfolio.model.structel.PortfolioStructure;
+
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * 
+ * 
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class EPXStreamHandler {
+	
+	private static final OLog log = Tracing.createLoggerFor(EPXStreamHandler.class);
+
+	private static final XStream myStream = XStreamHelper.createXStreamInstance();
+	private static Templates filterArtefactsTemplates;
+	
+	static { // initialize supported types
+		myStream.alias("defaultMap", EPDefaultMap.class);
+		myStream.alias("structureMap", EPStructuredMap.class);
+		myStream.alias("templateMap", EPStructuredMapTemplate.class);
+		myStream.alias("structure", EPStructureElement.class);
+		myStream.alias("page", EPPage.class);
+		myStream.alias("structureToArtefact", EPStructureToArtefactLink.class);
+		myStream.alias("structureToStructure", EPStructureToStructureLink.class);
+		myStream.alias("collectionRestriction", CollectRestriction.class);
+		myStream.omitField(EPAbstractMap.class, "ownerGroup"); // see also OLAT-6344
+		
+		try {
+			InputStream xsltIn = EPXStreamHandler.class.getResourceAsStream("portfolio_without_artefacts.xsl");
+			Source xsltSource = new StreamSource(xsltIn);
+			filterArtefactsTemplates = TransformerFactory.newInstance().newTemplates(xsltSource);
+		} catch (TransformerConfigurationException e) {
+			log.error("", e);
+		} catch (TransformerFactoryConfigurationError e) {
+			log.error("", e);
+		}
+	}
+	
+	public static final PortfolioStructure copy(PortfolioStructure structure) {
+		String stringuified = myStream.toXML(structure);
+		PortfolioStructure newStructure = (PortfolioStructure)myStream.fromXML(stringuified);
+		return newStructure;
+	}
+	
+	public static final PortfolioStructure getAsObject(File fMapXml, boolean withArtefacts) {
+		try {
+			//extract from zip
+			InputStream in = new FileInputStream(fMapXml);
+			ZipInputStream zipIn = new ZipInputStream(in);
+			//open the entry of the map
+			zipIn.getNextEntry();
+
+			Writer buffer = new StringWriter();
+			if(!withArtefacts) {
+				Transformer transformer = filterArtefactsTemplates.newTransformer();
+				transformer.transform(new StreamSource(zipIn), new StreamResult(buffer));
+			} else {
+				IOUtils.copy(zipIn, buffer);
+			}
+
+			PortfolioStructure struct = (PortfolioStructure) myStream.fromXML(buffer.toString());
+			// OLAT-6344: reset ownerGroup from earlier exports. A new group is created by import in ePFMgr.importPortfolioMapTemplate() later on anyway.
+			((EPAbstractMap) struct).setOwnerGroup(null); 
+			return struct;
+		} catch (Exception e) {
+			log.error("Cannot export this map: " + fMapXml, e);
+		}
+		return null;
+	}
+	
+	public static final InputStream toStream(PortfolioStructure structure)
+	throws IOException {
+		String xmlStructure = myStream.toXML(structure);
+		try {
+			//prepare a zip
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			ZipOutputStream zipOut = new ZipOutputStream(out);
+			zipOut.putNextEntry(new ZipEntry("map.xml"));
+			InputStream in = new ByteArrayInputStream(xmlStructure.getBytes("UTF8"));
+			IOUtils.copy(in, out);
+			zipOut.closeEntry();
+			zipOut.close();
+			
+			//prepare media resource
+			byte[] outArray = out.toByteArray();
+			IOUtils.closeQuietly(out);
+			IOUtils.closeQuietly(in);
+			return new ByteArrayInputStream(outArray);
+		} catch (IOException e) {
+			log.error("Cannot export this map: " + structure, e);
+			return null;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/portfolio/manager/portfolio_without_artefacts.xsl b/src/main/java/org/olat/portfolio/manager/portfolio_without_artefacts.xsl
new file mode 100644
index 00000000000..3bc232532d8
--- /dev/null
+++ b/src/main/java/org/olat/portfolio/manager/portfolio_without_artefacts.xsl
@@ -0,0 +1,10 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:template match="artefacts">
+  	<!-- Ommit artefacts -->
+  </xsl:template>
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java
index 4d8a3b3c56c..48cf095b6bd 100644
--- a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java
+++ b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java
@@ -25,12 +25,21 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
 import org.olat.core.gui.UserRequest;
@@ -55,6 +64,7 @@ import org.olat.portfolio.EPSecurityCallbackFactory;
 import org.olat.portfolio.EPTemplateMapResource;
 import org.olat.portfolio.EPUIFactory;
 import org.olat.portfolio.manager.EPFrontendManager;
+import org.olat.portfolio.manager.EPXStreamHandler;
 import org.olat.portfolio.model.restriction.CollectRestriction;
 import org.olat.portfolio.model.structel.EPAbstractMap;
 import org.olat.portfolio.model.structel.EPDefaultMap;
@@ -76,7 +86,6 @@ import org.olat.resource.accesscontrol.ui.RepositoryMainAccessControllerWrapper;
 import org.olat.resource.references.ReferenceManager;
 
 import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.converters.collections.CollectionConverter;
 
 import de.bps.onyx.plugin.StreamMediaResource;
 
@@ -97,7 +106,6 @@ public class PortfolioHandler implements RepositoryHandler {
 	public static final String PROCESS_CREATENEW = "create_new";
 	public static final String PROCESS_UPLOAD = "upload";
 	
-	public static XStream myStream = XStreamHelper.createXStreamInstance();
 
 	private static final boolean DOWNLOADABLE = false;
 	private static final boolean EDITABLE = true;
@@ -108,24 +116,6 @@ public class PortfolioHandler implements RepositoryHandler {
 	static { // initialize supported types
 		supportedTypes = new ArrayList<String>(1);
 		supportedTypes.add(EPTemplateMapResource.TYPE_NAME);
-		
-		myStream.alias("defaultMap", EPDefaultMap.class);
-		myStream.alias("structureMap", EPStructuredMap.class);
-		myStream.alias("templateMap", EPStructuredMapTemplate.class);
-		myStream.alias("structure", EPStructureElement.class);
-		myStream.alias("page", EPPage.class);
-		myStream.alias("structureToArtefact", EPStructureToArtefactLink.class);
-		myStream.alias("structureToStructure", EPStructureToStructureLink.class);
-		myStream.alias("collectionRestriction", CollectRestriction.class);
-		myStream.omitField(EPAbstractMap.class, "ownerGroup"); // see also OLAT-6344
-		//myStream.addDefaultImplementation(PersistentList.class, List.class);
-		myStream.addDefaultImplementation(ArrayList.class, List.class);
-		/*myStream.registerConverter(new CollectionConverter(myStream.getMapper()) {
-		    public boolean canConvert(Class type) {
-		        return PersistentList.class == type;
-		    }
-		});*/
-		
 	}
 	
 	/**
@@ -211,8 +201,7 @@ public class PortfolioHandler implements RepositoryHandler {
 	public OLATResourceable createCopy(OLATResourceable res, UserRequest ureq) {
 		EPFrontendManager ePFMgr = (EPFrontendManager)CoreSpringFactory.getBean("epFrontendManager");
 		PortfolioStructure structure = ePFMgr.loadPortfolioStructure(res);
-		String stringuified = myStream.toXML(structure);
-		PortfolioStructure newStructure = (PortfolioStructure)myStream.fromXML(stringuified);
+		PortfolioStructure newStructure = EPXStreamHandler.copy(structure);
 		PortfolioStructureMap map = ePFMgr.importPortfolioMapTemplate(newStructure, ureq.getIdentity());
 		return map.getOlatResource();
 	}
@@ -239,54 +228,14 @@ public class PortfolioHandler implements RepositoryHandler {
 
 		EPFrontendManager ePFMgr = (EPFrontendManager)CoreSpringFactory.getBean("epFrontendManager");
 		PortfolioStructure structure = ePFMgr.loadPortfolioStructure(res);
-		String xmlStructure = myStream.toXML(structure);
 		try {
-			//prepare a zip
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			ZipOutputStream zipOut = new ZipOutputStream(out);
-			zipOut.putNextEntry(new ZipEntry("map.xml"));
-			InputStream in = new ByteArrayInputStream(xmlStructure.getBytes("UTF8"));
-			FileUtils.copy(in, zipOut);
-			zipOut.closeEntry();
-			zipOut.close();
-			
-			//prepare media resource
-			byte[] outArray = out.toByteArray();
-			FileUtils.closeSafely(out);
-			FileUtils.closeSafely(in);
-			InputStream inOut = new ByteArrayInputStream(outArray);
+			InputStream inOut = EPXStreamHandler.toStream(structure);
 			mr = new StreamMediaResource(inOut, null, 0l, 0l);
 		} catch (IOException e) {
 			log.error("Cannot export this map: " + structure, e);
 		}
-		
 		return mr;
 	}
-	
-	public static final PortfolioStructure getAsObject(File fMapXml) {
-		try {
-			//extract from zip
-			InputStream in = new FileInputStream(fMapXml);
-			ZipInputStream zipIn = new ZipInputStream(in);
-			ZipEntry entry = zipIn.getNextEntry();
-			
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			FileUtils.copy(zipIn, out);
-			zipIn.closeEntry();
-			zipIn.close();
-			
-			//prepare decoding with xstream
-			byte[] outArray = out.toByteArray();
-			String xml = new String(outArray);
-			PortfolioStructure struct = (PortfolioStructure) myStream.fromXML(xml);
-			// OLAT-6344: reset ownerGroup from earlier exports. A new group is created by import in ePFMgr.importPortfolioMapTemplate() later on anyway.
-			((EPAbstractMap) struct).setOwnerGroup(null); 
-			return struct;
-		} catch (IOException e) {
-			log.error("Cannot export this map: " + fMapXml, e);
-		}
-		return null;
-	}
 
 	/**
 	 * @see org.olat.repository.handlers.RepositoryHandler#getDetailsComponent(org.olat.core.id.OLATResourceable,
diff --git a/src/test/java/org/olat/portfolio/EPFrontendManagerTest.java b/src/test/java/org/olat/portfolio/EPFrontendManagerTest.java
index 9b510dccea1..120dcc82c26 100644
--- a/src/test/java/org/olat/portfolio/EPFrontendManagerTest.java
+++ b/src/test/java/org/olat/portfolio/EPFrontendManagerTest.java
@@ -133,6 +133,7 @@ public class EPFrontendManagerTest extends OlatTestCase {
 		epStructureManager.savePortfolioStructure(struct11);
 		//structure element 2 from page 1
 		PortfolioStructure struct12 = epFrontendManager.createAndPersistPortfolioStructureElement(page1, "template-structure-1.2", "template-structure-1.2");
+		assertNotNull(struct12);
 		//first page
 		PortfolioStructure page2 = epFrontendManager.createAndPersistPortfolioPage(templateEl, "template-page-2", "template-page-2");
 		//structure element 1 from page 2
diff --git a/src/test/java/org/olat/portfolio/EPImportTest.java b/src/test/java/org/olat/portfolio/EPImportTest.java
new file mode 100644
index 00000000000..039953b9ce4
--- /dev/null
+++ b/src/test/java/org/olat/portfolio/EPImportTest.java
@@ -0,0 +1,67 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.portfolio;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.portfolio.manager.EPFrontendManager;
+import org.olat.portfolio.manager.EPXStreamHandler;
+import org.olat.portfolio.model.structel.PortfolioStructure;
+import org.olat.portfolio.model.structel.PortfolioStructureMap;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Test different imports
+ * 
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class EPImportTest extends OlatTestCase {
+
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private EPFrontendManager epFrontendManager;
+	
+	
+	@Test
+	public void testImportFromOpenOLAT_81_Hibernate3() throws URISyntaxException  {
+		URL mapUrl = EPImportTest.class.getResource("map_81.xml.zip");
+		assertNotNull(mapUrl);
+		File mapFile = new File(mapUrl.toURI());
+		//import the map
+		PortfolioStructure rootStructure = EPXStreamHandler.getAsObject(mapFile, false);
+		PortfolioStructureMap importedMap = epFrontendManager.importPortfolioMapTemplate(rootStructure, null);
+		Assert.assertNotNull(importedMap);
+		dbInstance.commitAndCloseSession();
+	}
+	
+
+	
+}
diff --git a/src/test/java/org/olat/portfolio/map_81.xml.zip b/src/test/java/org/olat/portfolio/map_81.xml.zip
new file mode 100644
index 0000000000000000000000000000000000000000..4c751bf9e016f4b4279a94c7aa5c09006324af70
GIT binary patch
literal 2584
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
YTl^jP)<m*$n|Y--=9`UkzryD0KdQ-bhX4Qo

literal 0
HcmV?d00001

diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 97971c0a860..15495ea5964 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -122,6 +122,7 @@ import org.junit.runners.Suite;
 	org.olat.portfolio.EPFrontendManagerTest.class,
 	org.olat.portfolio.EPStructureManagerTest.class,
 	org.olat.portfolio.EPStructureToArtefactTest.class,
+	org.olat.portfolio.EPImportTest.class,
 	org.olat.commons.info.InfoManagerTest.class,
 	org.olat.core.commons.service.tagging.SimpleTagProposalManagerTest.class,
 	org.olat.commons.coordinate.singlevm.SingleVMLockerTest.class,
-- 
GitLab