Full Repository Export / Import Support - first checkpoint

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2591 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2006-03-30 18:38:03 +00:00
parent 69039bc6c9
commit 701657f2f1
28 changed files with 1179 additions and 443 deletions

View File

@@ -258,22 +258,22 @@ import org.alfresco.service.namespace.QName;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
for (Exporter exporter : exporters)
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
for (Exporter exporter : exporters)
{
exporter.content(nodeRef, property, content, contentData);
exporter.content(nodeRef, property, content, contentData, index);
}
}

View File

@@ -215,7 +215,7 @@ public class ExporterComponent
try
{
XMLWriter writer = new XMLWriter(viewWriter, format);
return new ViewXMLExporter(namespaceService, nodeService, dictionaryService, permissionService, writer);
return new ViewXMLExporter(namespaceService, nodeService, searchService, dictionaryService, permissionService, writer);
}
catch (UnsupportedEncodingException e)
{
@@ -399,14 +399,18 @@ public class ExporterComponent
if (value instanceof Collection)
{
exporter.startValueCollection(nodeRef, property);
int index = 0;
for (Object valueInCollection : (Collection)value)
{
walkProperty(nodeRef, property, valueInCollection, parameters, exporter);
walkProperty(nodeRef, property, valueInCollection, index, parameters, exporter);
index++;
}
exporter.endValueCollection(nodeRef, property);
}
else
{
walkProperty(nodeRef, property, value, parameters, exporter);
walkProperty(nodeRef, property, value, -1, parameters, exporter);
}
// end export of property
@@ -468,10 +472,11 @@ public class ExporterComponent
* @param nodeRef
* @param property
* @param value
* @param index
* @param parameters
* @param exporter
*/
private void walkProperty(NodeRef nodeRef, QName property, Object value, ExporterCrawlerParameters parameters, Exporter exporter)
private void walkProperty(NodeRef nodeRef, QName property, Object value, int index, ExporterCrawlerParameters parameters, Exporter exporter)
{
// determine data type of value
PropertyDefinition propDef = dictionaryService.getProperty(property);
@@ -495,12 +500,12 @@ public class ExporterComponent
// Export non content data types
try
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
catch(TypeConversionException e)
{
exporter.warning("Value of property " + property + " could not be converted to xml string");
exporter.value(nodeRef, property, value.toString());
exporter.value(nodeRef, property, value.toString(), index);
}
}
else
@@ -512,7 +517,7 @@ public class ExporterComponent
// export an empty url for the content
ContentData contentData = (ContentData)value;
ContentData noContentURL = new ContentData("", contentData.getMimetype(), contentData.getSize(), contentData.getEncoding());
exporter.content(nodeRef, property, null, noContentURL);
exporter.content(nodeRef, property, null, noContentURL, index);
exporter.warning("Skipped content for property " + property + " on node " + nodeRef);
}
else
@@ -520,7 +525,7 @@ public class ExporterComponent
InputStream inputStream = reader.getContentInputStream();
try
{
exporter.content(nodeRef, property, inputStream, reader.getContentData());
exporter.content(nodeRef, property, inputStream, reader.getContentData(), index);
}
finally
{

View File

@@ -160,12 +160,12 @@ public class ExporterComponentTest extends BaseSpringTest
// System.out.println("TestProgress: end value collection: node " + nodeRef + " , property " + property);
}
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
// System.out.println("TestProgress: single value " + value);
}
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// System.out.println("TestProgress: content stream ");
}

View File

@@ -0,0 +1,420 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.exporter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.view.Exporter;
import org.alfresco.service.cmr.view.ExporterCrawlerParameters;
import org.alfresco.service.cmr.view.ExporterException;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.Location;
import org.alfresco.service.cmr.view.RepositoryExporterService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.TempFileProvider;
/**
* Full Repository Export Service
*
* @author davidc
*/
public class RepositoryExporterComponent implements RepositoryExporterService
{
private static final String STOREREF_KEY = "storeRef";
private static final String PACKAGENAME_KEY = "packageName";
// component dependencies
private ExporterService exporterService;
private MimetypeService mimetypeService;
private FileFolderService fileFolderService;
private NodeService nodeService;
private List<Properties> exportStores;
public void setExporterService(ExporterService exporterService)
{
this.exporterService = exporterService;
}
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setStores(List<Properties> exportStores)
{
this.exportStores = exportStores;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export()
*/
public FileExportHandle[] export(String packageName)
{
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new TempFileExporter());
return exportHandles.toArray(new FileExportHandle[exportHandles.size()]);
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export(java.io.File)
*/
public FileExportHandle[] export(File directoryDestination, String packageName)
{
ParameterCheck.mandatory("directoryDestination", directoryDestination);
if (!directoryDestination.isDirectory())
{
throw new ExporterException("Export location " + directoryDestination.getAbsolutePath() + " is not a directory");
}
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new FileExporter(directoryDestination));
return exportHandles.toArray(new FileExportHandle[exportHandles.size()]);
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export(org.alfresco.service.cmr.repository.NodeRef)
*/
public RepositoryExportHandle[] export(NodeRef repositoryDestination, String packageName)
{
ParameterCheck.mandatory("repositoryDestination", repositoryDestination);
FileInfo destInfo = fileFolderService.getFileInfo(repositoryDestination);
if (destInfo == null || !destInfo.isFolder())
{
throw new ExporterException("Repository destination " + repositoryDestination + " is not a folder.");
}
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new TempFileExporter());
List<RepositoryExportHandle> repoExportHandles = new ArrayList<RepositoryExportHandle>(exportHandles.size());
for (FileExportHandle exportHandle : exportHandles)
{
String description = I18NUtil.getMessage("export.store.package.description", new Object[] { exportHandle.storeRef.getIdentifier() });
NodeRef repoExportFile = addExportFile(repositoryDestination, exportHandle.packageName, description, exportHandle.exportFile);
RepositoryExportHandle handle = new RepositoryExportHandle();
handle.storeRef = exportHandle.storeRef;
handle.packageName = exportHandle.packageName;
handle.exportFile = repoExportFile;
repoExportHandles.add(handle);
}
return repoExportHandles.toArray(new RepositoryExportHandle[repoExportHandles.size()]);
}
/**
* Add a file system based .acp file into the repository
*
* @param repoDestination location within repository to place .acp file
* @param packageName acp package name
* @param packageDescription acp package description
* @param exportFile the .acp file
* @return node reference to import .acp file
*/
private NodeRef addExportFile(NodeRef repoDestination, String packageName, String packageDescription, File exportFile)
{
//
// import temp file into repository
//
// determine if file already exists
String fileName = packageName + "." + ACPExportPackageHandler.ACP_EXTENSION;
List<String> paths = new ArrayList<String>();
paths.add(fileName);
try
{
FileInfo fileInfo = fileFolderService.resolveNamePath(repoDestination, paths);
// Note: file already exists - delete
fileFolderService.delete(fileInfo.getNodeRef());
}
catch (org.alfresco.service.cmr.model.FileNotFoundException e)
{
// Note: file does not exist - no need to delete
}
// create acp file in repository
NodeRef exportFileNodeRef = null;
try
{
FileInfo fileInfo = fileFolderService.create(repoDestination, fileName, ContentModel.TYPE_CONTENT);
ContentWriter writer = fileFolderService.getWriter(fileInfo.getNodeRef());
writer.setMimetype(MimetypeMap.MIMETYPE_ACP);
writer.putContent(exportFile);
exportFileNodeRef = fileInfo.getNodeRef();
// add a title for Web Client viewing
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(3, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, packageName);
titledProps.put(ContentModel.PROP_DESCRIPTION, packageDescription);
nodeService.addAspect(exportFileNodeRef, ContentModel.ASPECT_TITLED, titledProps);
}
catch (FileExistsException e)
{
// Note: shouldn't get here
}
return exportFileNodeRef;
}
/**
* Contract for exporting a store
*
* @author davidc
*
* @param <ExportHandleType>
*/
private interface ExportStore<ExportHandleType extends ExportHandle>
{
public ExportHandleType exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress);
}
/**
* Enumerate list of pre-configured Stores and export one by one
*
* @param <ExportHandle> type of export file handle
* @param stores the list of stores to export
* @param exportStore the exporter call-back for handling the actual export
* @return the list export file handles
*/
private <ExportHandleType extends ExportHandle> List<ExportHandleType> exportStores(List<Properties> stores, String packageName, ExportStore<ExportHandleType> exportStore)
{
List<ExportHandleType> exportHandles = new ArrayList<ExportHandleType>(stores.size());
for (Properties store : stores)
{
// retrieve store reference to export
String storeRefStr = (String)store.get(STOREREF_KEY);
if (storeRefStr == null || storeRefStr.length() == 0)
{
throw new ExporterException("Store Reference has not been provided.");
}
StoreRef storeRef = new StoreRef(storeRefStr);
// retrieve package name to export into
String storePackageName = (String)store.get(PACKAGENAME_KEY);
if (storePackageName == null || storePackageName.length() == 0)
{
storePackageName = storeRef.getIdentifier();
}
String completePackageName = (packageName == null) ? storePackageName : packageName + "_" + storePackageName;
// now export
// NOTE: For now, do not provide exporter progress
ExporterCrawlerParameters exportParameters = getExportParameters(storeRef);
ExportHandleType exportHandle = exportStore.exportStore(exportParameters, completePackageName, null);
exportHandles.add(exportHandle);
}
return exportHandles;
}
/**
* Get export parameters for exporting a complete store
*
* @param storeRef store reference to export
* @return the parameters for exporting the complete store
*/
private ExporterCrawlerParameters getExportParameters(StoreRef storeRef)
{
ExporterCrawlerParameters parameters = new ExporterCrawlerParameters();
parameters.setExportFrom(new Location(storeRef));
parameters.setCrawlSelf(true);
parameters.setCrawlChildNodes(true);
parameters.setCrawlContent(true);
parameters.setCrawlAssociations(true);
parameters.setCrawlNullProperties(true);
parameters.setExcludeNamespaceURIs(new String[] {});
return parameters;
}
/**
* Export a Store to a temporary file
*
* @author davidc
*/
private class TempFileExporter implements ExportStore<FileExportHandle>
{
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// create a temporary file to hold the acp export
File tempFile = TempFileProvider.createTempFile("repoExp", "." + ACPExportPackageHandler.ACP_EXTENSION);
// create acp export handler around the temp file
File dataFile = new File(packageName);
File contentDir = new File(packageName);
try
{
OutputStream outputStream = new FileOutputStream(tempFile);
ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService);
// export the store
exporterService.exportView(acpHandler, exportParameters, progress);
}
catch(FileNotFoundException e)
{
tempFile.delete();
throw new ExporterException("Failed to create temporary file for holding export of store " + exportParameters.getExportFrom().getStoreRef());
}
// return handle onto temp file
FileExportHandle handle = new FileExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = tempFile;
return handle;
};
};
/**
* Export a Store to a file in a specified folder
*
* @author davidc
*/
private class FileExporter implements ExportStore<FileExportHandle>
{
private File directoryDestination;
/**
* Construct
*
* @param directoryDestination destination file system folder to create export file
*/
public FileExporter(File directoryDestination)
{
this.directoryDestination = directoryDestination;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// create a file to hold the acp export
File file = new File(directoryDestination, packageName + "." + ACPExportPackageHandler.ACP_EXTENSION);
// create acp export handler around the temp file
File dataFile = new File(packageName);
File contentDir = new File(packageName);
try
{
OutputStream outputStream = new FileOutputStream(file);
ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService);
// export the store
exporterService.exportView(acpHandler, exportParameters, progress);
}
catch(FileNotFoundException e)
{
file.delete();
throw new ExporterException("Failed to create file " + file.getAbsolutePath() + " for holding the export of store " + exportParameters.getExportFrom().getStoreRef());
}
// return handle onto temp file
FileExportHandle handle = new FileExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = file;
return handle;
};
};
/**
* Export a store to Repository File
*
* @author davidc
*/
private class RepositoryFileExporter implements ExportStore<RepositoryExportHandle>
{
private TempFileExporter tempFileExporter = new TempFileExporter();
private NodeRef repoDestination;
/**
* Construct
*
* @param repoDestination destination within repository to create export file
*/
public RepositoryFileExporter(NodeRef repoDestination)
{
this.repoDestination = repoDestination;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public RepositoryExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// export acp to temporary file
FileExportHandle tempFile = tempFileExporter.exportStore(exportParameters, packageName, progress);
String description = I18NUtil.getMessage("export.store.package.description", new Object[] { tempFile.storeRef.getIdentifier() });
NodeRef repoExportFile = addExportFile(repoDestination, packageName, description, tempFile.exportFile);
RepositoryExportHandle handle = new RepositoryExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = repoExportFile;
return handle;
}
};
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/package org.alfresco.repo.exporter;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.view.RepositoryExporterService;
import org.alfresco.service.cmr.view.RepositoryExporterService.FileExportHandle;
import org.alfresco.service.cmr.view.RepositoryExporterService.RepositoryExportHandle;
import org.alfresco.util.BaseSpringTest;
public class RepositoryExporterComponentTest extends BaseSpringTest
{
private RepositoryExporterService repositoryService;
private AuthenticationComponent authenticationComponent;
private NodeService nodeService;
private FileFolderService fileFolderService;
@Override
protected void onSetUpInTransaction() throws Exception
{
this.nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
this.fileFolderService = (FileFolderService)applicationContext.getBean(ServiceRegistry.FILE_FOLDER_SERVICE.getLocalName());
this.repositoryService = (RepositoryExporterService)applicationContext.getBean("repositoryExporterComponent");
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
this.authenticationComponent.setSystemUserAsCurrentUser();
}
@Override
protected void onTearDownInTransaction() throws Exception
{
authenticationComponent.clearCurrentSecurityContext();
super.onTearDownInTransaction();
}
public void testDummy()
{
}
public void xtestTempFileExport()
throws Exception
{
FileExportHandle[] handles = repositoryService.export("test");
assertNotNull(handles);
assertEquals(4, handles.length);
for (FileExportHandle tempFile : handles)
{
assertTrue(tempFile.exportFile.exists());
}
}
public void xtestRepositoryExport()
throws Exception
{
// Create a temp store to hold exports
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
NodeRef rootNode = nodeService.getRootNode(storeRef);
FileInfo container = fileFolderService.create(rootNode, "export", ContentModel.TYPE_FOLDER);
// Export stores
RepositoryExportHandle[] handles = repositoryService.export(container.getNodeRef(), "test");
assertNotNull(handles);
assertEquals(4, handles.length);
for (RepositoryExportHandle handle : handles)
{
assertTrue(nodeService.exists(handle.exportFile));
}
setComplete();
}
}

View File

@@ -204,19 +204,19 @@ import org.alfresco.util.ParameterCheck;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// Handle the stream by converting it to a URL and export the URL
ContentData exportedContentData = streamHandler.exportContent(content, contentData);
value(nodeRef, property, exportedContentData);
value(nodeRef, property, exportedContentData, index);
}
/* (non-Javadoc)

View File

@@ -17,7 +17,7 @@
package org.alfresco.repo.exporter;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -28,6 +28,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.view.Exporter;
@@ -98,6 +99,7 @@ import org.xml.sax.helpers.AttributesImpl;
// Service dependencies
private NamespaceService namespaceService;
private NodeService nodeService;
private SearchService searchService;
private DictionaryService dictionaryService;
private PermissionService permissionService;
@@ -113,11 +115,12 @@ import org.xml.sax.helpers.AttributesImpl;
* @param nodeService node service
* @param contentHandler content handler
*/
ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService,
ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService, SearchService searchService,
DictionaryService dictionaryService, PermissionService permissionService, ContentHandler contentHandler)
{
this.namespaceService = namespaceService;
this.nodeService = nodeService;
this.searchService = searchService;
this.dictionaryService = dictionaryService;
this.permissionService = permissionService;
this.contentHandler = contentHandler;
@@ -492,7 +495,7 @@ import org.xml.sax.helpers.AttributesImpl;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
try
{
@@ -512,12 +515,16 @@ import org.xml.sax.helpers.AttributesImpl;
// convert node references to paths
if (value instanceof NodeRef)
{
Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value);
value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService);
NodeRef valueNodeRef = (NodeRef)value;
if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef()))
{
Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, valueNodeRef);
value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService);
}
}
// output value wrapper if value is null or property data type is ANY
if (value == null || valueDataType != null)
// output value wrapper if value is null or property data type is ANY or value is part of collection
if (value == null || valueDataType != null || index != -1)
{
AttributesImpl attrs = new AttributesImpl();
if (value == null)
@@ -539,7 +546,7 @@ import org.xml.sax.helpers.AttributesImpl;
}
// output value wrapper if property data type is any
if (value == null || valueDataType != null)
if (value == null || valueDataType != null || index != -1)
{
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME));
}
@@ -550,74 +557,10 @@ import org.xml.sax.helpers.AttributesImpl;
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.util.Collection)
*/
public void value(NodeRef nodeRef, QName property, Collection values)
{
try
{
PropertyDefinition propDef = dictionaryService.getProperty(property);
DataTypeDefinition dataTypeDef = (propDef == null) ? null : propDef.getDataType();
// start collection
contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME), EMPTY_ATTRIBUTES);
for (Object value : values)
{
// determine data type of value
QName valueDataType = null;
if (dataTypeDef == null || dataTypeDef.getName().equals(DataTypeDefinition.ANY))
{
dataTypeDef = (value == null) ? null : dictionaryService.getDataType(value.getClass());
if (dataTypeDef != null)
{
valueDataType = dataTypeDef.getName();
}
}
// output value wrapper with datatype
AttributesImpl attrs = new AttributesImpl();
if (value == null)
{
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, ISNULL_LOCALNAME, ISNULL_QNAME.toPrefixString(), null, "true");
}
if (valueDataType != null)
{
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, DATATYPE_LOCALNAME, DATATYPE_QNAME.toPrefixString(), null, toPrefixString(valueDataType));
}
contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME), attrs);
// convert node references to paths
if (value instanceof NodeRef)
{
value = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value).toPrefixString(namespaceService);
}
// output value
String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value);
if (strValue != null)
{
contentHandler.characters(strValue.toCharArray(), 0, strValue.length());
}
// output value wrapper if property data type is any
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME));
}
// end collection
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME));
}
catch (SAXException e)
{
throw new ExporterException("Failed to process multi-value event - nodeRef " + nodeRef + "; property " + toPrefixString(property), e);
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// TODO: Base64 encode content and send out via Content Handler
}
@@ -770,9 +713,9 @@ import org.xml.sax.helpers.AttributesImpl;
return null;
}
Path rootPath = nodeService.getPath(rootRef);
Path fromPath = nodeService.getPath(fromRef);
Path toPath = nodeService.getPath(toRef);
Path rootPath = createIndexedPath(rootRef, nodeService.getPath(rootRef));
Path fromPath = createIndexedPath(fromRef, nodeService.getPath(fromRef));
Path toPath = createIndexedPath(toRef, nodeService.getPath(toRef));
Path relativePath = null;
try
@@ -840,4 +783,43 @@ import org.xml.sax.helpers.AttributesImpl;
return relativePath;
}
/**
* Helper to convert a path into an indexed path which uniquely identifies a node
*
* @param nodeRef
* @param path
* @return
*/
private Path createIndexedPath(NodeRef nodeRef, Path path)
{
// Add indexes for same name siblings
// TODO: Look at more efficient approach
for (int i = path.size() - 1; i >= 0; i--)
{
Path.Element pathElement = path.get(i);
if (i > 0 && pathElement instanceof Path.ChildAssocElement)
{
int index = 1; // for xpath index compatibility
String searchPath = path.subPath(i).toPrefixString(namespaceService);
List<NodeRef> siblings = searchService.selectNodes(nodeRef, searchPath, null, namespaceService, false);
if (siblings.size() > 1)
{
ChildAssociationRef childAssoc = ((Path.ChildAssocElement)pathElement).getRef();
NodeRef childRef = childAssoc.getChildRef();
for (NodeRef sibling : siblings)
{
if (sibling.equals(childRef))
{
childAssoc.setNthSibling(index);
break;
}
index++;
}
}
}
}
return path;
}
}