mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
VS2 - version store refactor (merged from DEV/VS2 to HEAD)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10574 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -191,6 +191,17 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="version2Bootstrap" parent="version2StoreImporter" singleton="false">
|
||||
<property name="bootstrapViews">
|
||||
<list>
|
||||
<props>
|
||||
<prop key="path">/</prop>
|
||||
<prop key="location">alfresco/bootstrap/version2Store.xml</prop>
|
||||
</props>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="spacesArchiveBootstrap" parent="spacesArchiveStoreImporter" singleton="false">
|
||||
<property name="bootstrapViews">
|
||||
<list>
|
||||
|
15
config/alfresco/bootstrap/version2Store.xml
Normal file
15
config/alfresco/bootstrap/version2Store.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
|
||||
xmlns:ver2="http://www.alfresco.org/model/versionstore/2.0">
|
||||
|
||||
<view:reference view:pathref="/">
|
||||
<!-- Apply All access to Everyone on root node of version2 store -->
|
||||
<view:acl>
|
||||
<view:ace view:access="ALLOWED">
|
||||
<view:authority>GROUP_EVERYONE</view:authority>
|
||||
<view:permission>All</view:permission>
|
||||
</view:ace>
|
||||
</view:acl>
|
||||
<ver2:versionStoreRoot/>
|
||||
</view:reference>
|
||||
|
||||
</view:view>
|
@@ -649,7 +649,7 @@
|
||||
<!-- -->
|
||||
|
||||
|
||||
<bean id="versionService" class="org.alfresco.repo.version.VersionServiceImpl" init-method="initialise">
|
||||
<bean id="versionService" class="org.alfresco.repo.version.Version2ServiceImpl" init-method="initialise">
|
||||
<property name="nodeService">
|
||||
<ref bean="NodeService" />
|
||||
</property>
|
||||
@@ -671,9 +671,15 @@
|
||||
<property name="policyBehaviourFilter">
|
||||
<ref bean="policyBehaviourFilter" />
|
||||
</property>
|
||||
<property name="permissionService">
|
||||
<ref bean="permissionService" />
|
||||
</property>
|
||||
<property name="onlyUseDeprecatedV1">
|
||||
<value>${version.store.onlyUseDeprecatedV1}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="versionNodeService" class="org.alfresco.repo.version.NodeServiceImpl">
|
||||
<bean id="versionNodeService" class="org.alfresco.repo.version.Node2ServiceImpl">
|
||||
<property name="dbNodeService">
|
||||
<ref bean="dbNodeService" />
|
||||
</property>
|
||||
@@ -682,6 +688,27 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="versionMigrator" class="org.alfresco.repo.version.VersionMigrator" init-method="init">
|
||||
<property name="dbNodeService">
|
||||
<ref bean="dbNodeService" />
|
||||
</property>
|
||||
<property name="versionNodeService">
|
||||
<ref bean="versionNodeService" />
|
||||
</property>
|
||||
<property name="version2ServiceImpl">
|
||||
<ref bean="versionService" />
|
||||
</property>
|
||||
<property name="policyBehaviourFilter">
|
||||
<ref bean="policyBehaviourFilter" />
|
||||
</property>
|
||||
<property name="dictionaryService">
|
||||
<ref bean="dictionaryService" />
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="transactionService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="versionCounterService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.alfresco.repo.version.common.counter.VersionCounterService</value>
|
||||
@@ -798,7 +825,10 @@
|
||||
<!-- Implementation models -->
|
||||
<value>org/alfresco/repo/action/actionModel.xml</value>
|
||||
<value>org/alfresco/repo/rule/ruleModel.xml</value>
|
||||
<value>org/alfresco/repo/version/version_model.xml</value>
|
||||
|
||||
<!-- Version models -->
|
||||
<value>org/alfresco/repo/version/version_model.xml</value> <!-- deprecated -->
|
||||
<value>org/alfresco/repo/version/version2_model.xml</value>
|
||||
|
||||
<!-- Email model -->
|
||||
<value>alfresco/model/emailServerModel.xml</value>
|
||||
|
@@ -165,7 +165,7 @@
|
||||
<prop key="packageName">spaces_archive</prop>
|
||||
</props>
|
||||
<props>
|
||||
<prop key="storeRef">workspace://lightWeightVersionStore</prop>
|
||||
<prop key="storeRef">${version.store.version2Store}</prop>
|
||||
<prop key="packageName">versions</prop>
|
||||
</props>
|
||||
</list>
|
||||
@@ -331,7 +331,13 @@
|
||||
|
||||
<bean id="versionStoreImporter" parent="storeImporter" abstract="true">
|
||||
<property name="storeUrl">
|
||||
<value>workspace://lightWeightVersionStore</value>
|
||||
<value>${version.store.deprecated.lightWeightVersionStore}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="version2StoreImporter" parent="storeImporter" abstract="true">
|
||||
<property name="storeUrl">
|
||||
<value>${version.store.version2Store}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
@@ -223,3 +223,6 @@ patch.createSiteStore.result=Created the AVM site data store.
|
||||
|
||||
patch.sitePermissionRefactorPatch.description=Create permission groups for sites.
|
||||
patch.sitePermissionRefactorPatch.result=Groups have been created for all sites and user's allocated accordingly.
|
||||
|
||||
patch.migrateVersionStore.description=Migrate from lightWeightVersionStore to version2Store
|
||||
patch.migrateVersionStore.result=Migrated version store. Created {0} version histories
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Rule service externalised display strings
|
||||
# Version service externalised display strings
|
||||
|
||||
version_service.err_restore_exists=The node {0} cannot be restored since it already exists.
|
||||
version_service.err_not_found=The current version label of the node does not exist in the version history.
|
||||
@@ -6,3 +6,14 @@ version_service.err_unsupported=The current implementation of the version servic
|
||||
version_service.err_one_preceeding=The current implementation of the version service only supports one preceeding version.
|
||||
version_service.err_restore_no_version=The node {0} cannot be restore since there is no version information available for this node.
|
||||
version_service.err_revert_mismatch=The version provided to revert to does not come from the nodes version history.
|
||||
|
||||
|
||||
version_service.migration.patch.noop=Nothing to do (no version histories found in old version store)
|
||||
version_service.migration.patch.complete=Completed migration of {0} version histories (to new version store) in {1} secs
|
||||
version_service.migration.patch.warn.skip1=Skipped migration of {0} version histories (migrate failed)
|
||||
version_service.migration.patch.warn.skip2=Skipped migration of {0} version histories (already migrated)
|
||||
|
||||
version_service.migration.delete.progress=\t\tBackground deletion of migrated version histories (from old version store) {0}% complete, estimated complete at {1}
|
||||
version_service.migration.delete.complete=Completed deletion of {0} migrated version histories (from old version store) in {1} secs
|
||||
version_service.migration.delete.warn.skip1=Skipped deletion of {0} version histories (delete failed)
|
||||
version_service.migration.delete.warn.skip2=Skipped deletion of {0} version histories (not migrated)
|
@@ -129,6 +129,11 @@
|
||||
<property name="maxErrorsPerTransaction" >
|
||||
<value>5</value> <!-- limit output (exception and log) to the first N violation messages -->
|
||||
</property>
|
||||
<property name="storesToIgnore">
|
||||
<list>
|
||||
<value>${version.store.version2Store}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- tags nodes that are incomplete w.r.t. properties-->
|
||||
@@ -142,6 +147,11 @@
|
||||
<property name="nodeService">
|
||||
<ref bean="nodeService" />
|
||||
</property>
|
||||
<property name="storesToIgnore">
|
||||
<list>
|
||||
<value>${version.store.version2Store}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- NodeService implemented to persist to Database. Resource management enabled. -->
|
||||
|
@@ -1488,4 +1488,16 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="patch.migrateVersionStore" class="org.alfresco.repo.admin.patch.impl.MigrateVersionStorePatch" parent="basePatch" >
|
||||
<property name="id"><value>patch.migrateVersionStore</value></property>
|
||||
<property name="description"><value>patch.migrateVersionStore.description</value></property>
|
||||
<property name="fixesFromSchema"><value>0</value></property>
|
||||
<property name="fixesToSchema"><value>129</value></property>
|
||||
<property name="targetSchema"><value>130</value></property>
|
||||
<!-- helper beans/properties -->
|
||||
<property name="versionMigrator">
|
||||
<ref bean="versionMigrator" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
@@ -185,6 +185,12 @@ spaces.content_forms.childname=app:forms
|
||||
spaces.user_homes.childname=app:user_homes
|
||||
spaces.sites.childname=st:sites
|
||||
|
||||
# ADM VersionStore Configuration
|
||||
version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore
|
||||
version.store.version2Store=workspace://version2Store
|
||||
# WARNING: For non-production testing only !!! Do not change (to avoid version store issues, including possible mismatch). Should be false since lightWeightVersionStore is deprecated.
|
||||
version.store.onlyUseDeprecatedV1=false
|
||||
|
||||
# Folders for storing people
|
||||
system.system_container.childname=sys:system
|
||||
system.people_container.childname=sys:people
|
||||
|
@@ -470,4 +470,36 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- enable scheduler property to activate -->
|
||||
<bean id="versionStoreMigrationCleanupJob" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean id="versionStoreMigrationCleanupDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.version.MigrationCleanupJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="versionMigrator">
|
||||
<ref bean="versionMigrator" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
|
||||
<!-- enable this to activate bean -->
|
||||
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
|
||||
<!-- start after bootstrap (1 minute) and run once -->
|
||||
<property name="startDelayMinutes">
|
||||
<value>1</value>
|
||||
</property>
|
||||
<property name="repeatCount">
|
||||
<value>0</value>
|
||||
</property>
|
||||
|
||||
</bean>
|
||||
</beans>
|
@@ -19,4 +19,4 @@ version.build=@build-number@
|
||||
|
||||
# Schema number
|
||||
|
||||
version.schema=129
|
||||
version.schema=130
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.version.VersionMigrator;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Migrate version store from workspace://lightWeightVersionStore to workspace://version2Store
|
||||
*/
|
||||
public class MigrateVersionStorePatch extends AbstractPatch
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(MigrateVersionStorePatch.class);
|
||||
|
||||
private static final String MSG_SUCCESS = "patch.migrateVersionStore.result";
|
||||
|
||||
private VersionMigrator versionMigrator;
|
||||
private int batchSize = 1;
|
||||
private boolean deleteImmediately = false;
|
||||
|
||||
public void setVersionMigrator(VersionMigrator versionMigrator)
|
||||
{
|
||||
this.versionMigrator = versionMigrator;
|
||||
}
|
||||
|
||||
public void setBatchSize(int batchSize)
|
||||
{
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
|
||||
public void setDeleteImmediately(boolean deleteImmediately)
|
||||
{
|
||||
this.deleteImmediately = deleteImmediately;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (batchSize < 1)
|
||||
{
|
||||
String errorMessage = "batchSize ("+batchSize+") cannot be less than 1";
|
||||
logger.error(errorMessage);
|
||||
throw new AlfrescoRuntimeException(errorMessage);
|
||||
}
|
||||
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
int vhCount = versionMigrator.migrateVersions(batchSize, deleteImmediately);
|
||||
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, vhCount);
|
||||
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,9 +31,11 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.version.Version2Model;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.service.cmr.ml.EditionService;
|
||||
@@ -257,9 +259,29 @@ public class EditionServiceImpl implements EditionService
|
||||
|
||||
Map<QName, Serializable> properties = versionNodeService.getProperties(mlContainerEdition.getFrozenStateNodeRef());
|
||||
|
||||
// get the serialisation of the version histories in the version properties
|
||||
List<VersionHistory> versionHistories = (List<VersionHistory>)
|
||||
properties.get(VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
|
||||
List<VersionHistory> versionHistories = null;
|
||||
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
|
||||
// get the serialisation of the version histories in the version properties
|
||||
versionHistories = (List<VersionHistory>)
|
||||
properties.get(Version2Model.PROP_QNAME_TRANSLATION_VERSIONS);
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
|
||||
// get the serialisation of the version histories in the version properties
|
||||
versionHistories = (List<VersionHistory>)
|
||||
properties.get(VersionModel.PROP_QNAME_TRANSLATION_VERSIONS);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected versionstore: " + versionService.getVersionStoreReference().getIdentifier());
|
||||
}
|
||||
|
||||
if (versionHistories == null)
|
||||
{
|
||||
@@ -296,18 +318,37 @@ public class EditionServiceImpl implements EditionService
|
||||
// properties in which the version histories will be stored
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
|
||||
// add the version history of the translation as property of the Edition
|
||||
properties.put(VersionModel.PROP_QNAME_QNAME, VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
|
||||
properties.put(VersionModel.PROP_QNAME_IS_MULTI_VALUE, true);
|
||||
properties.put(VersionModel.PROP_QNAME_MULTI_VALUE, (Serializable) translationVersionHistories);
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
|
||||
// add the version history of the translation as property of the Edition
|
||||
NodeRef versionNodeRef = VersionUtil.convertNodeRef(edition.getFrozenStateNodeRef());
|
||||
this.nodeService.setProperty(versionNodeRef, Version2Model.PROP_QNAME_TRANSLATION_VERSIONS, (Serializable) translationVersionHistories);
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
|
||||
// add the version history of the translation as property of the Edition
|
||||
properties.put(VersionModel.PROP_QNAME_QNAME, VersionModel.PROP_QNAME_TRANSLATION_VERSIONS);
|
||||
properties.put(VersionModel.PROP_QNAME_IS_MULTI_VALUE, true);
|
||||
properties.put(VersionModel.PROP_QNAME_MULTI_VALUE, (Serializable) translationVersionHistories);
|
||||
|
||||
// create the versioned property node
|
||||
this.nodeService.createNode(
|
||||
VersionUtil.convertNodeRef(edition.getFrozenStateNodeRef()),
|
||||
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
|
||||
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
|
||||
VersionModel.TYPE_QNAME_VERSIONED_PROPERTY,
|
||||
properties);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected versionstore: " + versionService.getVersionStoreReference().getIdentifier());
|
||||
}
|
||||
|
||||
// create the versioned property node
|
||||
this.nodeService.createNode(
|
||||
VersionUtil.convertNodeRef(edition.getFrozenStateNodeRef()),
|
||||
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
|
||||
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
|
||||
VersionModel.TYPE_QNAME_VERSIONED_PROPERTY,
|
||||
properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,6 +25,7 @@
|
||||
package org.alfresco.repo.node.integrity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -79,6 +80,7 @@ public class IncompleteNodeTagger
|
||||
private PolicyComponent policyComponent;
|
||||
private DictionaryService dictionaryService;
|
||||
private NodeService nodeService;
|
||||
private List<String> storesToIgnore = new ArrayList<String>(0);
|
||||
|
||||
public IncompleteNodeTagger()
|
||||
{
|
||||
@@ -108,6 +110,15 @@ public class IncompleteNodeTagger
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param storesToIgnore stores (eg. workspace://version2Store) which will be
|
||||
* ignored by IncompleteNodeTagger. Note: assumes associations are within a store.
|
||||
*/
|
||||
public void setStoresToIgnore(List<String> storesToIgnore)
|
||||
{
|
||||
this.storesToIgnore = storesToIgnore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the system-level policy behaviours
|
||||
*/
|
||||
@@ -236,9 +247,12 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||
save(nodeRef);
|
||||
saveAssoc(nodeRef, null);
|
||||
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||
{
|
||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||
save(nodeRef);
|
||||
saveAssoc(nodeRef, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +263,10 @@ public class IncompleteNodeTagger
|
||||
Map<QName, Serializable> before,
|
||||
Map<QName, Serializable> after)
|
||||
{
|
||||
save(nodeRef);
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
save(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,14 +278,17 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||
{
|
||||
logger.debug("Ignoring aspect addition: " + ContentModel.ASPECT_INCOMPLETE);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Ignoring aspect addition: " + ContentModel.ASPECT_INCOMPLETE);
|
||||
}
|
||||
}
|
||||
save(nodeRef);
|
||||
}
|
||||
save(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,14 +296,17 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||
{
|
||||
logger.debug("Ignoring aspect removal: " + ContentModel.ASPECT_INCOMPLETE);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Ignoring aspect removal: " + ContentModel.ASPECT_INCOMPLETE);
|
||||
}
|
||||
}
|
||||
save(nodeRef);
|
||||
}
|
||||
save(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,9 +317,12 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNew)
|
||||
{
|
||||
if (!isNew)
|
||||
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||
{
|
||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||
if (!isNew)
|
||||
{
|
||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +331,10 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||
{
|
||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +342,10 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
||||
{
|
||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||
{
|
||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +353,10 @@ public class IncompleteNodeTagger
|
||||
*/
|
||||
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
||||
{
|
||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||
{
|
||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -107,6 +107,7 @@ public class IntegrityChecker
|
||||
private boolean failOnViolation;
|
||||
private int maxErrorsPerTransaction;
|
||||
private boolean traceOn;
|
||||
private List<String> storesToIgnore = new ArrayList<String>(0);
|
||||
|
||||
/**
|
||||
* Downgrade violations to warnings within the current transaction. This is temporary and
|
||||
@@ -207,6 +208,15 @@ public class IntegrityChecker
|
||||
this.maxErrorsPerTransaction = maxLogNumberPerTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param storesToIgnore stores (eg. workspace://version2Store) which will be
|
||||
* ignored by integrity checker. Note: assumes associations are within a store.
|
||||
*/
|
||||
public void setStoresToIgnore(List<String> storesToIgnore)
|
||||
{
|
||||
this.storesToIgnore = storesToIgnore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the system-level policy behaviours
|
||||
*/
|
||||
@@ -320,42 +330,45 @@ public class IntegrityChecker
|
||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
NodeRef childRef = childAssocRef.getChildRef();
|
||||
IntegrityEvent event = null;
|
||||
// check properties on child node
|
||||
event = new PropertiesIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childRef);
|
||||
save(event);
|
||||
|
||||
// check that the multiplicity and other properties of the new association are allowed
|
||||
onCreateChildAssociation(childAssocRef, false);
|
||||
|
||||
// check mandatory aspects
|
||||
event = new AspectsIntegrityEvent(nodeService, dictionaryService, childRef);
|
||||
save(event);
|
||||
|
||||
// check for associations defined on the new node (child)
|
||||
QName childNodeTypeQName = nodeService.getType(childRef);
|
||||
ClassDefinition nodeTypeDef = dictionaryService.getClass(childNodeTypeQName);
|
||||
if (nodeTypeDef == null)
|
||||
if (! storesToIgnore.contains(childRef.getStoreRef().toString()))
|
||||
{
|
||||
throw new DictionaryException("The node type is not recognized: " + childNodeTypeQName);
|
||||
}
|
||||
Map<QName, AssociationDefinition> childAssocDefs = nodeTypeDef.getAssociations();
|
||||
|
||||
// check the multiplicity of each association with the node acting as a source
|
||||
for (AssociationDefinition assocDef : childAssocDefs.values())
|
||||
{
|
||||
QName assocTypeQName = assocDef.getName();
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
IntegrityEvent event = null;
|
||||
// check properties on child node
|
||||
event = new PropertiesIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childRef,
|
||||
assocTypeQName,
|
||||
false);
|
||||
childRef);
|
||||
save(event);
|
||||
|
||||
// check that the multiplicity and other properties of the new association are allowed
|
||||
onCreateChildAssociation(childAssocRef, false);
|
||||
|
||||
// check mandatory aspects
|
||||
event = new AspectsIntegrityEvent(nodeService, dictionaryService, childRef);
|
||||
save(event);
|
||||
|
||||
// check for associations defined on the new node (child)
|
||||
QName childNodeTypeQName = nodeService.getType(childRef);
|
||||
ClassDefinition nodeTypeDef = dictionaryService.getClass(childNodeTypeQName);
|
||||
if (nodeTypeDef == null)
|
||||
{
|
||||
throw new DictionaryException("The node type is not recognized: " + childNodeTypeQName);
|
||||
}
|
||||
Map<QName, AssociationDefinition> childAssocDefs = nodeTypeDef.getAssociations();
|
||||
|
||||
// check the multiplicity of each association with the node acting as a source
|
||||
for (AssociationDefinition assocDef : childAssocDefs.values())
|
||||
{
|
||||
QName assocTypeQName = assocDef.getName();
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childRef,
|
||||
assocTypeQName,
|
||||
false);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,10 +380,13 @@ public class IntegrityChecker
|
||||
Map<QName, Serializable> before,
|
||||
Map<QName, Serializable> after)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check properties on node
|
||||
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check properties on node
|
||||
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,31 +402,34 @@ public class IntegrityChecker
|
||||
*/
|
||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check properties on node
|
||||
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
|
||||
// check for associations defined on the aspect
|
||||
AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName);
|
||||
if (aspectDef == null)
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
throw new DictionaryException("The aspect type is not recognized: " + aspectTypeQName);
|
||||
}
|
||||
Map<QName, AssociationDefinition> assocDefs = aspectDef.getAssociations();
|
||||
|
||||
// check the multiplicity of each association with the node acting as a source
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
QName assocTypeQName = assocDef.getName();
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeRef,
|
||||
assocTypeQName,
|
||||
false);
|
||||
IntegrityEvent event = null;
|
||||
// check properties on node
|
||||
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
|
||||
// check for associations defined on the aspect
|
||||
AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName);
|
||||
if (aspectDef == null)
|
||||
{
|
||||
throw new DictionaryException("The aspect type is not recognized: " + aspectTypeQName);
|
||||
}
|
||||
Map<QName, AssociationDefinition> assocDefs = aspectDef.getAssociations();
|
||||
|
||||
// check the multiplicity of each association with the node acting as a source
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
QName assocTypeQName = assocDef.getName();
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeRef,
|
||||
assocTypeQName,
|
||||
false);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,11 +438,13 @@ public class IntegrityChecker
|
||||
*/
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check mandatory aspects
|
||||
event = new AspectsIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
|
||||
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check mandatory aspects
|
||||
event = new AspectsIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,45 +463,48 @@ public class IntegrityChecker
|
||||
return;
|
||||
}
|
||||
|
||||
IntegrityEvent event = null;
|
||||
// check source type
|
||||
event = new AssocSourceTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check target type
|
||||
event = new AssocTargetTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target role
|
||||
event = new AssocTargetRoleIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
childAssocRef.getQName());
|
||||
save(event);
|
||||
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source type
|
||||
event = new AssocSourceTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check target type
|
||||
event = new AssocTargetTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target role
|
||||
event = new AssocTargetRoleIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
childAssocRef.getQName());
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,23 +513,26 @@ public class IntegrityChecker
|
||||
*/
|
||||
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getChildRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,37 +543,40 @@ public class IntegrityChecker
|
||||
*/
|
||||
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source type
|
||||
event = new AssocSourceTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check target type
|
||||
event = new AssocTargetTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source type
|
||||
event = new AssocSourceTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check target type
|
||||
event = new AssocTargetTypeIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName());
|
||||
save(event);
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
false);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,23 +585,26 @@ public class IntegrityChecker
|
||||
*/
|
||||
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||
{
|
||||
IntegrityEvent event = null;
|
||||
// check source multiplicity
|
||||
event = new AssocSourceMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getTargetRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
// check target multiplicity
|
||||
event = new AssocTargetMultiplicityIntegrityEvent(
|
||||
nodeService,
|
||||
dictionaryService,
|
||||
nodeAssocRef.getSourceRef(),
|
||||
nodeAssocRef.getTypeQName(),
|
||||
true);
|
||||
save(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -133,6 +133,11 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
this.dictionaryDAO = dictionaryDAO;
|
||||
}
|
||||
|
||||
public void setVersionService(VersionService versionService)
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during the transaction setup
|
||||
*/
|
||||
@@ -148,7 +153,6 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
|
||||
// Get the services by name from the application context
|
||||
this.dbNodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||
this.versionService = (VersionService)applicationContext.getBean("versionService");
|
||||
this.versionCounterDaoService = (VersionCounterService)applicationContext.getBean("versionCounterService");
|
||||
this.contentService = (ContentService)applicationContext.getBean("contentService");
|
||||
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
|
||||
@@ -158,6 +162,8 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
this.nodeArchiveService = (NodeArchiveService) applicationContext.getBean("nodeArchiveService");
|
||||
this.nodeService = (NodeService)applicationContext.getBean("nodeService");
|
||||
|
||||
setVersionService((VersionService)applicationContext.getBean("versionService"));
|
||||
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
|
||||
// Create the test model
|
||||
@@ -214,6 +220,16 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
* @return the node reference
|
||||
*/
|
||||
protected NodeRef createNewVersionableNode()
|
||||
{
|
||||
return createNode(true);
|
||||
}
|
||||
|
||||
protected NodeRef createNewNode()
|
||||
{
|
||||
return createNode(false);
|
||||
}
|
||||
|
||||
protected NodeRef createNode(boolean versionable)
|
||||
{
|
||||
// Use this map to retrive the versionable nodes in later tests
|
||||
this.versionableNodes = new HashMap<String, NodeRef>();
|
||||
@@ -225,7 +241,10 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
QName.createQName("{test}MyVersionableNode"),
|
||||
TEST_TYPE_QNAME,
|
||||
this.nodeProperties).getChildRef();
|
||||
this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
if (versionable)
|
||||
{
|
||||
this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
}
|
||||
|
||||
assertNotNull(nodeRef);
|
||||
this.versionableNodes.put(nodeRef.getId(), nodeRef);
|
||||
@@ -241,7 +260,12 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
TEST_CHILD_ASSOC_1,
|
||||
TEST_TYPE_QNAME,
|
||||
this.nodeProperties).getChildRef();
|
||||
this.dbNodeService.addAspect(child1, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
|
||||
if (versionable)
|
||||
{
|
||||
this.dbNodeService.addAspect(child1, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
}
|
||||
|
||||
assertNotNull(child1);
|
||||
this.versionableNodes.put(child1.getId(), child1);
|
||||
NodeRef child2 = this.dbNodeService.createNode(
|
||||
@@ -250,7 +274,12 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
TEST_CHILD_ASSOC_2,
|
||||
TEST_TYPE_QNAME,
|
||||
this.nodeProperties).getChildRef();
|
||||
this.dbNodeService.addAspect(child2, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
|
||||
if (versionable)
|
||||
{
|
||||
this.dbNodeService.addAspect(child2, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||
}
|
||||
|
||||
assertNotNull(child2);
|
||||
this.versionableNodes.put(child2.getId(), child2);
|
||||
|
||||
@@ -304,6 +333,25 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
protected Collection<Version> createVersion(NodeRef versionableNode, Map<String, Serializable> versionProperties, boolean versionChildren)
|
||||
{
|
||||
// Get the next version number
|
||||
int nextVersion = peekNextVersionNumber();
|
||||
String nextVersionLabel = peekNextVersionLabel(versionableNode, nextVersion, versionProperties);
|
||||
|
||||
// Snap-shot the date-time
|
||||
long beforeVersionTime = System.currentTimeMillis();
|
||||
|
||||
// Now lets create new version for this node (optionally with children)
|
||||
Collection<Version> versions = versionService.createVersion(versionableNode, this.versionProperties, versionChildren);
|
||||
|
||||
// Check the returned versions are correct
|
||||
checkVersionCollection(nextVersion, nextVersionLabel, beforeVersionTime, versions);
|
||||
|
||||
// Return the new versions
|
||||
return versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next version label
|
||||
*/
|
||||
@@ -322,15 +370,17 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
* @param newVersion the new version
|
||||
* @param versionableNode the versioned node
|
||||
*/
|
||||
protected void checkNewVersion(long beforeVersionTime, int expectedVersionNumber, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
|
||||
protected void checkVersion(long beforeVersionTime, int expectedVersionNumber, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
|
||||
{
|
||||
assertNotNull(newVersion);
|
||||
|
||||
// Check the version label and version number
|
||||
|
||||
assertEquals(
|
||||
"The expected version number was not used.",
|
||||
Integer.toString(expectedVersionNumber),
|
||||
newVersion.getVersionProperty(VersionModel.PROP_VERSION_NUMBER).toString());
|
||||
newVersion.getVersionProperty(VersionBaseModel.PROP_VERSION_NUMBER).toString());
|
||||
|
||||
assertEquals(
|
||||
"The expected version label was not used.",
|
||||
expectedVersionLabel,
|
||||
@@ -347,28 +397,53 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
// Check the creator
|
||||
assertEquals(USER_NAME, newVersion.getCreator());
|
||||
|
||||
// Check the properties of the verison
|
||||
// Check the metadata properties of the version
|
||||
Map<String, Serializable> props = newVersion.getVersionProperties();
|
||||
assertNotNull("The version properties collection should not be null.", props);
|
||||
// TODO sort this out - need to check for the reserved properties too
|
||||
//assertEquals(versionProperties.size(), props.size());
|
||||
for (String key : versionProperties.keySet())
|
||||
if (versionProperties != null)
|
||||
{
|
||||
assertEquals(
|
||||
versionProperties.get(key),
|
||||
newVersion.getVersionProperty(key));
|
||||
// TODO sort this out - need to check for the reserved properties too
|
||||
//assertEquals(versionProperties.size(), props.size());
|
||||
for (String key : versionProperties.keySet())
|
||||
{
|
||||
assertEquals(
|
||||
versionProperties.get(key),
|
||||
newVersion.getVersionProperty(key));
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the node reference is correct
|
||||
NodeRef nodeRef = newVersion.getFrozenStateNodeRef();
|
||||
assertNotNull(nodeRef);
|
||||
assertEquals(
|
||||
VersionModel.STORE_ID,
|
||||
nodeRef.getStoreRef().getIdentifier());
|
||||
assertEquals(
|
||||
VersionModel.STORE_PROTOCOL,
|
||||
nodeRef.getStoreRef().getProtocol());
|
||||
assertNotNull(nodeRef.getId());
|
||||
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
assertEquals(
|
||||
Version2Model.STORE_ID,
|
||||
nodeRef.getStoreRef().getIdentifier());
|
||||
assertEquals(
|
||||
Version2Model.STORE_PROTOCOL,
|
||||
nodeRef.getStoreRef().getProtocol());
|
||||
assertNotNull(nodeRef.getId());
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
assertEquals(
|
||||
VersionModel.STORE_ID,
|
||||
nodeRef.getStoreRef().getIdentifier());
|
||||
assertEquals(
|
||||
VersionModel.STORE_PROTOCOL,
|
||||
nodeRef.getStoreRef().getProtocol());
|
||||
assertNotNull(nodeRef.getId());
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkNewVersion(long beforeVersionTime, int expectedVersionNumber, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
|
||||
{
|
||||
checkVersion(beforeVersionTime, expectedVersionNumber, expectedVersionLabel, newVersion, versionableNode);
|
||||
|
||||
// TODO: How do we check the frozen attributes ??
|
||||
|
||||
@@ -379,6 +454,43 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
||||
assertEquals(newVersion.getVersionLabel(), currentVersionLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check the validity of the list of newly created versions.
|
||||
*
|
||||
* @param expectedVersionNumber the expected version number that all the versions should have
|
||||
* @param beforeVersionTime the time before the versions where created
|
||||
* @param versions the collection of version objects
|
||||
*/
|
||||
private void checkVersionCollection(int expectedVersionNumber, String expectedVersionLabel, long beforeVersionTime, Collection<Version> versions)
|
||||
{
|
||||
for (Version version : versions)
|
||||
{
|
||||
// Get the frozen id from the version
|
||||
String frozenNodeId = null;
|
||||
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
frozenNodeId = ((NodeRef)version.getVersionProperty(Version2Model.PROP_FROZEN_NODE_REF)).getId();
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
frozenNodeId = (String)version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID);
|
||||
}
|
||||
|
||||
assertNotNull("Unable to retrieve the frozen node id from the created version.", frozenNodeId);
|
||||
|
||||
// Get the original node ref (based on the forzen node)
|
||||
NodeRef origionaNodeRef = this.versionableNodes.get(frozenNodeId);
|
||||
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", origionaNodeRef);
|
||||
|
||||
// Check the new version
|
||||
checkNewVersion(beforeVersionTime, expectedVersionNumber, expectedVersionLabel, version, origionaNodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next version number without affecting the version counter.
|
||||
*
|
||||
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Cleanup of Version Store Migration - to delete old/migrated version histories from old version store. Typically this is configured to run once on startup.
|
||||
*/
|
||||
public class MigrationCleanupJob implements Job
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(MigrationCleanupJob.class);
|
||||
|
||||
private static final String KEY_COMPONENT = "versionMigrator";
|
||||
private static final String KEY_BATCHSIZE = "batchSize";
|
||||
|
||||
private int batchSize = 1;
|
||||
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
VersionMigrator migrationCleanup = (VersionMigrator)jobData.get(KEY_COMPONENT);
|
||||
if (migrationCleanup == null)
|
||||
{
|
||||
throw new JobExecutionException("Missing job data: " + KEY_COMPONENT);
|
||||
}
|
||||
|
||||
String batchSizeStr = (String)jobData.get(KEY_BATCHSIZE);
|
||||
if (batchSizeStr == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
batchSize = new Integer(batchSizeStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.warn("Invalid batchsize, using default: " + batchSize, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (batchSize < 1)
|
||||
{
|
||||
String errorMessage = "batchSize ("+batchSize+") cannot be less than 1";
|
||||
logger.error(errorMessage);
|
||||
throw new AlfrescoRuntimeException(errorMessage);
|
||||
}
|
||||
|
||||
// perform the cleanup of the old version store
|
||||
migrationCleanup.executeCleanup(batchSize);
|
||||
}
|
||||
}
|
210
source/java/org/alfresco/repo/version/Node2ServiceImpl.java
Normal file
210
source/java/org/alfresco/repo/version/Node2ServiceImpl.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
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.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
|
||||
|
||||
/**
|
||||
* The version2 store node service implementation
|
||||
*/
|
||||
public class Node2ServiceImpl extends NodeServiceImpl implements NodeService, Version2Model
|
||||
{
|
||||
/**
|
||||
* The name of the spoofed root association
|
||||
*/
|
||||
private static final QName rootAssocName = QName.createQName(Version2Model.NAMESPACE_URI, "versionedState");
|
||||
|
||||
|
||||
/**
|
||||
* Type translation for version store
|
||||
*/
|
||||
public QName getType(NodeRef nodeRef) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getType(nodeRef);
|
||||
}
|
||||
|
||||
// frozen node type -> replaced by actual node type of the version node
|
||||
return (QName)this.dbNodeService.getType(VersionUtil.convertNodeRef(nodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation for version store
|
||||
*/
|
||||
public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getAspects(nodeRef);
|
||||
}
|
||||
|
||||
Set<QName> aspects = this.dbNodeService.getAspects(VersionUtil.convertNodeRef(nodeRef));
|
||||
aspects.remove(Version2Model.ASPECT_VERSION);
|
||||
return aspects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property translation for version store
|
||||
*/
|
||||
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getProperties(nodeRef);
|
||||
}
|
||||
|
||||
Map<QName, Serializable> props = dbNodeService.getProperties(VersionUtil.convertNodeRef(nodeRef));
|
||||
VersionUtil.convertFrozenToOriginalProps(props);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property translation for version store
|
||||
*/
|
||||
public Serializable getProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getProperty(nodeRef, qname);
|
||||
}
|
||||
|
||||
// TODO optimise - get property directly and convert if needed
|
||||
Map<QName, Serializable> properties = getProperties(VersionUtil.convertNodeRef(nodeRef));
|
||||
return properties.get(qname);
|
||||
}
|
||||
|
||||
/**
|
||||
* The node will apprear to be attached to the root of the version store
|
||||
*
|
||||
* @see NodeService#getParentAssocs(NodeRef, QNamePattern, QNamePattern)
|
||||
*/
|
||||
public List<ChildAssociationRef> getParentAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern)
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getParentAssocs(nodeRef, typeQNamePattern, qnamePattern);
|
||||
}
|
||||
|
||||
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>();
|
||||
if (qnamePattern.isMatch(rootAssocName) == true)
|
||||
{
|
||||
result.add(new ChildAssociationRef(
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
dbNodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID)),
|
||||
rootAssocName,
|
||||
nodeRef));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs conversion from version store properties to <i>real</i> associations
|
||||
*/
|
||||
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getChildAssocs(nodeRef, typeQNamePattern, qnamePattern);
|
||||
}
|
||||
|
||||
// Get the child assocs from the version store
|
||||
List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs(
|
||||
VersionUtil.convertNodeRef(nodeRef),
|
||||
typeQNamePattern, qnamePattern);
|
||||
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(childAssocRefs.size());
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
// Get the child reference
|
||||
NodeRef childRef = childAssocRef.getChildRef();
|
||||
NodeRef referencedNode = (NodeRef)this.dbNodeService.getProperty(childRef, ContentModel.PROP_REFERENCE);
|
||||
|
||||
// Build a child assoc ref to add to the returned list
|
||||
ChildAssociationRef newChildAssocRef = new ChildAssociationRef(
|
||||
childAssocRef.getTypeQName(),
|
||||
childAssocRef.getParentRef(),
|
||||
childAssocRef.getQName(),
|
||||
referencedNode,
|
||||
childAssocRef.isPrimary(),
|
||||
childAssocRef.getNthSibling());
|
||||
result.add(newChildAssocRef);
|
||||
}
|
||||
|
||||
// sort the results so that the order appears to be exactly as it was originally
|
||||
Collections.sort(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the node begin attached to the root node of the version store.
|
||||
*/
|
||||
public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException
|
||||
{
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getPrimaryParent(nodeRef);
|
||||
}
|
||||
|
||||
return new ChildAssociationRef(
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
dbNodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID)),
|
||||
rootAssocName,
|
||||
nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
@Override
|
||||
public List<AssociationRef> getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern)
|
||||
{
|
||||
if (sourceRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
return super.getTargetAssocs(sourceRef, qnamePattern);
|
||||
}
|
||||
|
||||
// This operation is not supported for a version2 store
|
||||
throw new UnsupportedOperationException(MSG_UNSUPPORTED);
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -36,6 +36,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
@@ -54,6 +55,8 @@ import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,10 +66,12 @@ import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
*/
|
||||
public class NodeServiceImpl implements NodeService, VersionModel
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(NodeServiceImpl.class);
|
||||
|
||||
/**
|
||||
* Error messages
|
||||
*/
|
||||
private final static String MSG_UNSUPPORTED =
|
||||
protected final static String MSG_UNSUPPORTED =
|
||||
"This operation is not supported by a version store implementation of the node service.";
|
||||
|
||||
/**
|
||||
@@ -331,7 +336,23 @@ public class NodeServiceImpl implements NodeService, VersionModel
|
||||
if (isMultiValue.booleanValue() == false)
|
||||
{
|
||||
value = this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_VALUE);
|
||||
value = (Serializable)DefaultTypeConverter.INSTANCE.convert(propDef.getDataType(), value);
|
||||
|
||||
if (propDef != null)
|
||||
{
|
||||
DataTypeDefinition dataTypeDef = propDef.getDataType();
|
||||
if (dataTypeDef != null)
|
||||
{
|
||||
value = (Serializable)DefaultTypeConverter.INSTANCE.convert(dataTypeDef, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Null dataTypeDefinition for: " + propDef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Null propertyDefinition for: " + qName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -119,13 +119,25 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
||||
|
||||
// Get the properties of the versioned state
|
||||
Map<QName, Serializable> versionedProperties = this.lightWeightVersionStoreNodeService.getProperties(version.getFrozenStateNodeRef());
|
||||
//assertEquals(origProps.size(), versionedProperties.size());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("original ("+origProps.size()+"): " + origProps.keySet());
|
||||
logger.debug("versioned ("+versionedProperties.size()+"): " + versionedProperties.keySet());
|
||||
}
|
||||
|
||||
for (QName key : origProps.keySet())
|
||||
{
|
||||
assertTrue(versionedProperties.containsKey(key));
|
||||
assertEquals(origProps.get(key), versionedProperties.get(key));
|
||||
assertEquals(""+key, origProps.get(key), versionedProperties.get(key));
|
||||
}
|
||||
|
||||
// NOTE: cm:versionLabel is an expected additional property
|
||||
//assertEquals(origProps.size(), versionedProperties.size());
|
||||
|
||||
// check version label
|
||||
assertEquals("1.0", versionedProperties.get(ContentModel.PROP_VERSION_LABEL));
|
||||
|
||||
// TODO do futher versioning and check by changing values
|
||||
}
|
||||
|
||||
@@ -163,46 +175,47 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
||||
*/
|
||||
public void testGetChildAssocs()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
// Let's have a look at the version store ..
|
||||
System.out.println(NodeStoreInspector.dumpNodeStore(
|
||||
logger.trace(NodeStoreInspector.dumpNodeStore(
|
||||
this.dbNodeService,
|
||||
this.versionService.getVersionStoreReference()) + "\n\n");
|
||||
logger.debug("");
|
||||
logger.trace("");
|
||||
}
|
||||
|
||||
// Create a new versionable node
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
Collection<ChildAssociationRef> origionalChildren = this.dbNodeService.getChildAssocs(versionableNode);
|
||||
assertNotNull(origionalChildren);
|
||||
Collection<ChildAssociationRef> originalChildren = this.dbNodeService.getChildAssocs(versionableNode);
|
||||
assertNotNull(originalChildren);
|
||||
|
||||
// Store the origional children in a map for easy navigation later
|
||||
HashMap<String, ChildAssociationRef> origionalChildAssocRefs = new HashMap<String, ChildAssociationRef>();
|
||||
for (ChildAssociationRef ref : origionalChildren)
|
||||
// Store the original children in a map for easy navigation later
|
||||
HashMap<String, ChildAssociationRef> originalChildAssocRefs = new HashMap<String, ChildAssociationRef>();
|
||||
for (ChildAssociationRef ref : originalChildren)
|
||||
{
|
||||
origionalChildAssocRefs.put(ref.getChildRef().getId(), ref);
|
||||
originalChildAssocRefs.put(ref.getChildRef().getId(), ref);
|
||||
}
|
||||
|
||||
// Create a new version
|
||||
Version version = createVersion(versionableNode, this.versionProperties);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
// Let's have a look at the version store ..
|
||||
System.out.println(NodeStoreInspector.dumpNodeStore(
|
||||
logger.trace(NodeStoreInspector.dumpNodeStore(
|
||||
this.dbNodeService,
|
||||
this.versionService.getVersionStoreReference()));
|
||||
logger.trace("");
|
||||
}
|
||||
|
||||
// Get the children of the versioned node
|
||||
Collection<ChildAssociationRef> versionedChildren = this.lightWeightVersionStoreNodeService.getChildAssocs(version.getFrozenStateNodeRef());
|
||||
assertNotNull(versionedChildren);
|
||||
assertEquals(origionalChildren.size(), versionedChildren.size());
|
||||
assertEquals(originalChildren.size(), versionedChildren.size());
|
||||
|
||||
for (ChildAssociationRef versionedChildRef : versionedChildren)
|
||||
{
|
||||
ChildAssociationRef origChildAssocRef = origionalChildAssocRefs.get(versionedChildRef.getChildRef().getId());
|
||||
ChildAssociationRef origChildAssocRef = originalChildAssocRefs.get(versionedChildRef.getChildRef().getId());
|
||||
assertNotNull(origChildAssocRef);
|
||||
|
||||
assertEquals(
|
||||
@@ -219,25 +232,51 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
||||
|
||||
/**
|
||||
* Test getAssociationTargets
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public void testGetAssociationTargets()
|
||||
{
|
||||
// Create a new versionable node
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
try
|
||||
{
|
||||
this.lightWeightVersionStoreNodeService.getTargetAssocs(
|
||||
dummyNodeRef,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
fail("This operation is not supported.");
|
||||
}
|
||||
catch (UnsupportedOperationException exception)
|
||||
{
|
||||
if (exception.getMessage() != MSG_ERR)
|
||||
{
|
||||
fail("Unexpected exception raised during method excution: " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
|
||||
// Store the current details of the target associations
|
||||
List<AssociationRef> origAssocs = this.dbNodeService.getTargetAssocs(
|
||||
versionableNode,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
// Create a new versionable node
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
|
||||
// Create a new version
|
||||
Version version = createVersion(versionableNode, this.versionProperties);
|
||||
// Store the current details of the target associations
|
||||
List<AssociationRef> origAssocs = this.dbNodeService.getTargetAssocs(
|
||||
versionableNode,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
List<AssociationRef> assocs = this.lightWeightVersionStoreNodeService.getTargetAssocs(
|
||||
version.getFrozenStateNodeRef(),
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
assertNotNull(assocs);
|
||||
assertEquals(origAssocs.size(), assocs.size());
|
||||
// Create a new version
|
||||
Version version = createVersion(versionableNode, this.versionProperties);
|
||||
|
||||
List<AssociationRef> assocs = this.lightWeightVersionStoreNodeService.getTargetAssocs(
|
||||
version.getFrozenStateNodeRef(),
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
assertNotNull(assocs);
|
||||
assertEquals(origAssocs.size(), assocs.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,7 +316,10 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
||||
Set<QName> aspects = this.lightWeightVersionStoreNodeService.getAspects(version.getFrozenStateNodeRef());
|
||||
assertEquals(origAspects.size(), aspects.size());
|
||||
|
||||
// TODO check that the set's contain the same items
|
||||
for (QName origAspect : origAspects)
|
||||
{
|
||||
assertTrue(origAspect+"",aspects.contains(origAspect));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
118
source/java/org/alfresco/repo/version/Version2Model.java
Normal file
118
source/java/org/alfresco/repo/version/Version2Model.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Version2 Model Constants used by version2Store implementation
|
||||
*/
|
||||
public interface Version2Model extends VersionBaseModel
|
||||
{
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
public static final String NAMESPACE_URI = "http://www.alfresco.org/model/versionstore/2.0";
|
||||
|
||||
/**
|
||||
* The store id
|
||||
*/
|
||||
public static final String STORE_ID = "version2Store";
|
||||
|
||||
/** The version store root aspect */
|
||||
public static final QName ASPECT_VERSION_STORE_ROOT = QName.createQName(NAMESPACE_URI, ASPECT_LOCALNAME_VERSION_STORE_ROOT);
|
||||
|
||||
/**
|
||||
* Version history type
|
||||
*/
|
||||
public static final QName TYPE_QNAME_VERSION_HISTORY = QName.createQName(NAMESPACE_URI, TYPE_VERSION_HISTORY);
|
||||
|
||||
/**
|
||||
* Version history properties and associations
|
||||
*/
|
||||
public static final QName PROP_QNAME_VERSIONED_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_VERSIONED_NODE_ID);
|
||||
public static final QName ASSOC_ROOT_VERSION = QName.createQName(NAMESPACE_URI, ASSOC_LOCALNAME_ROOT_VERSION);
|
||||
|
||||
/**
|
||||
* Version aspect + aspect properties
|
||||
*/
|
||||
public static final String ASPECT_LOCALNAME_VERSION = "version";
|
||||
public static final QName ASPECT_VERSION = QName.createQName(NAMESPACE_URI, ASPECT_LOCALNAME_VERSION);
|
||||
|
||||
public static final String PROP_VERSION_DESCRIPTION = "versionDescription"; // maps from description
|
||||
|
||||
public static final QName PROP_QNAME_VERSION_LABEL = QName.createQName(NAMESPACE_URI, PROP_VERSION_LABEL);
|
||||
public static final QName PROP_QNAME_VERSION_NUMBER = QName.createQName(NAMESPACE_URI, PROP_VERSION_NUMBER);
|
||||
public static final QName PROP_QNAME_VERSION_DESCRIPTION = QName.createQName(NAMESPACE_URI, PROP_VERSION_DESCRIPTION);
|
||||
|
||||
// frozen sys:referenceable properties (x4)
|
||||
|
||||
public static final String PROP_FROZEN_NODE_REF = "frozenNodeRef";
|
||||
public static final QName PROP_QNAME_FROZEN_NODE_REF = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_REF);
|
||||
|
||||
public static final String PROP_FROZEN_NODE_DBID = "frozenNodeDbId";
|
||||
public static final QName PROP_QNAME_FROZEN_NODE_DBID = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_DBID);
|
||||
|
||||
// frozen cm:auditable properties (x5)
|
||||
|
||||
public static final String PROP_FROZEN_CREATOR = "frozenCreator";
|
||||
public static final QName PROP_QNAME_FROZEN_CREATOR = QName.createQName(NAMESPACE_URI, PROP_FROZEN_CREATOR);
|
||||
|
||||
public static final String PROP_FROZEN_CREATED = "frozenCreated";
|
||||
public static final QName PROP_QNAME_FROZEN_CREATED = QName.createQName(NAMESPACE_URI, PROP_FROZEN_CREATED);
|
||||
|
||||
public static final String PROP_FROZEN_MODIFIER = "frozenModifer";
|
||||
public static final QName PROP_QNAME_FROZEN_MODIFIER = QName.createQName(NAMESPACE_URI, PROP_FROZEN_MODIFIER);
|
||||
|
||||
public static final String PROP_FROZEN_MODIFIED = "frozenModified";
|
||||
public static final QName PROP_QNAME_FROZEN_MODIFIED = QName.createQName(NAMESPACE_URI, PROP_FROZEN_MODIFIED);
|
||||
|
||||
public static final String PROP_FROZEN_ACCESSED = "frozenAccessed";
|
||||
public static final QName PROP_QNAME_FROZEN_ACCESSED = QName.createQName(NAMESPACE_URI, PROP_FROZEN_ACCESSED);
|
||||
|
||||
|
||||
|
||||
public static final QName ASSOC_SUCCESSOR = QName.createQName(NAMESPACE_URI, "successor");
|
||||
|
||||
public static final String PROP_METADATA_PREFIX = "metadata-";
|
||||
|
||||
public static final String PROP_VERSION_TYPE = "versionType";
|
||||
|
||||
/**
|
||||
* Child relationship names
|
||||
*/
|
||||
public static final QName CHILD_QNAME_VERSION_HISTORIES = QName.createQName(NAMESPACE_URI, CHILD_VERSION_HISTORIES);
|
||||
public static final QName CHILD_QNAME_VERSIONS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONS);
|
||||
|
||||
|
||||
// Used by ML service
|
||||
|
||||
/**
|
||||
* Created version associated to the deleted translations of an mlContainer
|
||||
*/
|
||||
|
||||
public static final QName PROP_QNAME_TRANSLATION_VERSIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERSIONS);
|
||||
}
|
||||
|
1069
source/java/org/alfresco/repo/version/Version2ServiceImpl.java
Normal file
1069
source/java/org/alfresco/repo/version/Version2ServiceImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
78
source/java/org/alfresco/repo/version/VersionBaseModel.java
Normal file
78
source/java/org/alfresco/repo/version/VersionBaseModel.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
|
||||
/**
|
||||
* Base Version Model interface containing the common local names (and other constants)
|
||||
* used by the lightWeightVersionStore and version2Store implementations
|
||||
*/
|
||||
public interface VersionBaseModel
|
||||
{
|
||||
/**
|
||||
* The store protocol
|
||||
*/
|
||||
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
|
||||
|
||||
public static final String PROP_DESCRIPTION = "description";
|
||||
|
||||
public static final String PROP_VERSION_DESCRIPTION = "versionDescription";
|
||||
|
||||
public static final String PROP_VERSION_LABEL = "versionLabel";
|
||||
public static final String PROP_CREATED_DATE = ContentModel.PROP_CREATED.getLocalName();
|
||||
public static final String PROP_CREATOR = ContentModel.PROP_CREATOR.getLocalName();
|
||||
public static final String PROP_VERSION_TYPE = "versionType";
|
||||
public static final String PROP_VERSION_NUMBER = "versionNumber";
|
||||
|
||||
/** The version store root aspect localname*/
|
||||
public static final String ASPECT_LOCALNAME_VERSION_STORE_ROOT = "versionStoreRoot";
|
||||
|
||||
/**
|
||||
* Version history type
|
||||
*/
|
||||
public static final String TYPE_VERSION_HISTORY = "versionHistory";
|
||||
|
||||
/**
|
||||
* Version history properties and associations
|
||||
*/
|
||||
public static final String PROP_VERSIONED_NODE_ID = "versionedNodeId";
|
||||
public static final String ASSOC_LOCALNAME_ROOT_VERSION = "rootVersion";
|
||||
|
||||
|
||||
/**
|
||||
* Child relationship names
|
||||
*/
|
||||
public static final String CHILD_VERSION_HISTORIES = "versionHistory";
|
||||
public static final String CHILD_VERSIONS = "version";
|
||||
|
||||
// Used by ML service
|
||||
|
||||
/**
|
||||
* Created version associated to the deleted translations of an mlContainer
|
||||
*/
|
||||
public static final String PROP_TRANSLATION_VERSIONS = "translationVersions";
|
||||
}
|
659
source/java/org/alfresco/repo/version/VersionMigrator.java
Normal file
659
source/java/org/alfresco/repo/version/VersionMigrator.java
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.domain.hibernate.SessionSizeResourceManager;
|
||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
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.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Version2 Migrator
|
||||
*/
|
||||
public class VersionMigrator
|
||||
{
|
||||
protected static Log logger = LogFactory.getLog(VersionMigrator.class);
|
||||
|
||||
public static final StoreRef VERSION_STORE_REF_OLD = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID);
|
||||
public static final StoreRef VERSION_STORE_REF_NEW = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID);
|
||||
|
||||
/** track completion * */
|
||||
int percentComplete;
|
||||
|
||||
/** start time * */
|
||||
long startTime;
|
||||
|
||||
|
||||
private static final String MSG_PATCH_NOOP = "version_service.migration.patch.noop";
|
||||
private static final String MSG_PATCH_COMPLETE = "version_service.migration.patch.complete";
|
||||
private static final String MSG_PATCH_SKIP1 = "version_service.migration.patch.warn.skip1";
|
||||
private static final String MSG_PATCH_SKIP2 = "version_service.migration.patch.warn.skip2";
|
||||
|
||||
private static final String MSG_DELETE_PROGRESS = "version_service.migration.delete.progress";
|
||||
private static final String MSG_DELETE_COMPLETE = "version_service.migration.delete.complete";
|
||||
private static final String MSG_DELETE_SKIP1 = "version_service.migration.delete.warn.skip1";
|
||||
private static final String MSG_DELETE_SKIP2 = "version_service.migration.delete.warn.skip2";
|
||||
|
||||
private static final String MSG_PATCH_PROGRESS = "patch.progress";
|
||||
|
||||
private static final long RANGE_10 = 1000 * 60 * 90;
|
||||
private static final long RANGE_5 = 1000 * 60 * 60 * 4;
|
||||
private static final long RANGE_2 = 1000 * 60 * 90 * 10;
|
||||
|
||||
private static boolean busy = false;
|
||||
|
||||
public final static String PREFIX_MIGRATED = "migrated-";
|
||||
|
||||
private VersionServiceImpl version1Service = new VersionServiceImpl();
|
||||
|
||||
private Version2ServiceImpl version2Service;
|
||||
private NodeService dbNodeService;
|
||||
private BehaviourFilter policyBehaviourFilter;
|
||||
private DictionaryService dictionaryService;
|
||||
private TransactionService transactionService;
|
||||
private NodeService versionNodeService; // NodeService impl which redirects to appropriate VersionService
|
||||
|
||||
public void setVersion2ServiceImpl(Version2ServiceImpl versionService)
|
||||
{
|
||||
this.version2Service = versionService;
|
||||
}
|
||||
|
||||
public void setDbNodeService(NodeService nodeService)
|
||||
{
|
||||
this.dbNodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPolicyBehaviourFilter(BehaviourFilter policyBehaviourFilter)
|
||||
{
|
||||
this.policyBehaviourFilter = policyBehaviourFilter;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setVersionNodeService(NodeService versionNodeService)
|
||||
{
|
||||
this.versionNodeService = versionNodeService;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
version1Service.setNodeService(dbNodeService);
|
||||
version1Service.setDbNodeService(dbNodeService);
|
||||
|
||||
version2Service.setDbNodeService(dbNodeService);
|
||||
}
|
||||
|
||||
public NodeRef migrateVersionHistory(NodeRef oldVHNodeRef, NodeRef versionedNodeRef)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("migrateVersionHistory: oldVersionHistoryRef = " + oldVHNodeRef);
|
||||
}
|
||||
|
||||
VersionHistory vh = v1BuildVersionHistory(oldVHNodeRef, versionedNodeRef);
|
||||
|
||||
// create new version history node
|
||||
NodeRef newVHNodeRef = v2CreateVersionHistory(versionedNodeRef);
|
||||
|
||||
Version[] oldVersions = (Version[])vh.getAllVersions().toArray(new Version[]{});
|
||||
|
||||
// Disable auditable behaviour - so that migrated versions maintain their original auditable properties (eg. created, creator)
|
||||
this.policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = (oldVersions.length-1); i >= 0; i--)
|
||||
{
|
||||
// migrate versions
|
||||
v2CreateNewVersion(newVHNodeRef, oldVersions[i]);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Enable auditable behaviour
|
||||
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
|
||||
return newVHNodeRef;
|
||||
}
|
||||
|
||||
private NodeRef v2CreateVersionHistory(NodeRef nodeRef)
|
||||
{
|
||||
return version2Service.createVersionHistory(nodeRef);
|
||||
}
|
||||
|
||||
private NodeRef v2CreateNewVersion(NodeRef newVersionHistoryRef, Version oldVersion)
|
||||
{
|
||||
NodeRef versionedNodeRef = oldVersion.getVersionedNodeRef(); // nodeRef to versioned node in live store
|
||||
NodeRef frozenStateNodeRef = oldVersion.getFrozenStateNodeRef(); // nodeRef to version node in version store
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("v2CreateNewVersion: oldVersionRef = " + frozenStateNodeRef + " " + oldVersion);
|
||||
}
|
||||
|
||||
String versionLabel = oldVersion.getVersionLabel();
|
||||
String versionDescription = oldVersion.getDescription();
|
||||
|
||||
QName sourceType = versionNodeService.getType(frozenStateNodeRef);
|
||||
Set<QName> nodeAspects = versionNodeService.getAspects(frozenStateNodeRef);
|
||||
Map<QName, Serializable> nodeProperties = versionNodeService.getProperties(frozenStateNodeRef);
|
||||
|
||||
long nodeDbId = (Long)nodeProperties.get(ContentModel.PROP_NODE_DBID);
|
||||
nodeProperties.remove(ContentModel.PROP_NODE_UUID); // else will try to persist with this node uuid (see AbstractNodeServiceImpl.generateGuid)
|
||||
|
||||
int versionNumber = (Integer)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), VersionModel.PROP_QNAME_VERSION_NUMBER);
|
||||
|
||||
// get oldVersion auditable properties (of the version node itself, rather than the live versioned node)
|
||||
Date versionCreated = (Date)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), ContentModel.PROP_CREATED);
|
||||
String versionCreator = (String)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), ContentModel.PROP_CREATOR);
|
||||
Date versionModified = (Date)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), ContentModel.PROP_MODIFIED);
|
||||
String versionModifier = (String)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), ContentModel.PROP_MODIFIER);
|
||||
Date versionAccessed = (Date)dbNodeService.getProperty(VersionUtil.convertNodeRef(frozenStateNodeRef), ContentModel.PROP_ACCESSED);
|
||||
|
||||
Map<String, Serializable> versionMetaDataProperties = version1Service.getVersionMetaData(VersionUtil.convertNodeRef(frozenStateNodeRef));
|
||||
|
||||
// Create the node details
|
||||
PolicyScope nodeDetails = new PolicyScope(sourceType);
|
||||
|
||||
// add properties
|
||||
for (Map.Entry<QName, Serializable> entry : nodeProperties.entrySet())
|
||||
{
|
||||
nodeDetails.addProperty(sourceType, entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
// add aspects
|
||||
for (QName aspect : nodeAspects)
|
||||
{
|
||||
// add aspect
|
||||
nodeDetails.addAspect(aspect);
|
||||
|
||||
// copy the aspect properties
|
||||
ClassDefinition classDefinition = dictionaryService.getClass(aspect);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
|
||||
for (QName propertyName : propertyDefinitions.keySet())
|
||||
{
|
||||
Serializable propValue = nodeProperties.get(propertyName);
|
||||
nodeDetails.addProperty(aspect, propertyName, propValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeRef newVersionRef = version2Service.createNewVersion(
|
||||
sourceType,
|
||||
newVersionHistoryRef,
|
||||
version2Service.getStandardVersionProperties(versionedNodeRef, nodeDbId, nodeAspects, versionNumber, versionLabel, versionDescription),
|
||||
versionMetaDataProperties,
|
||||
versionNumber,
|
||||
nodeDetails);
|
||||
|
||||
// set newVersion auditable properties (of the version node itself, rather than the live versioned node)
|
||||
Map<QName, Serializable> props = dbNodeService.getProperties(newVersionRef);
|
||||
props.put(ContentModel.PROP_CREATED, versionCreated);
|
||||
props.put(ContentModel.PROP_CREATOR, versionCreator);
|
||||
props.put(ContentModel.PROP_MODIFIED, versionModified);
|
||||
props.put(ContentModel.PROP_MODIFIER, versionModifier);
|
||||
props.put(ContentModel.PROP_ACCESSED, versionAccessed);
|
||||
dbNodeService.setProperties(newVersionRef, props);
|
||||
|
||||
return newVersionRef;
|
||||
}
|
||||
|
||||
protected NodeRef v1GetVersionedNodeRef(NodeRef oldVersionHistoryRef)
|
||||
{
|
||||
NodeRef versionedNodeRef = null;
|
||||
|
||||
// Get versioned nodeRef from one of the versions - note: assumes all versions refer to the same versioned nodeRef
|
||||
Collection<ChildAssociationRef> versions = dbNodeService.getChildAssocs(oldVersionHistoryRef);
|
||||
if (versions.size() > 0)
|
||||
{
|
||||
Iterator<ChildAssociationRef> itr = versions.iterator();
|
||||
ChildAssociationRef childAssocRef = itr.next();
|
||||
NodeRef versionRef = childAssocRef.getChildRef();
|
||||
|
||||
Version version = version1Service.getVersion(versionRef);
|
||||
|
||||
versionedNodeRef = version.getVersionedNodeRef();
|
||||
}
|
||||
|
||||
return versionedNodeRef;
|
||||
}
|
||||
|
||||
private VersionHistory v1BuildVersionHistory(NodeRef oldVersionHistoryRef, NodeRef versionedNodeRef)
|
||||
{
|
||||
return version1Service.buildVersionHistory(oldVersionHistoryRef, versionedNodeRef);
|
||||
}
|
||||
|
||||
protected void v1DeleteVersionHistory(NodeRef oldVersionHistoryRef)
|
||||
{
|
||||
dbNodeService.deleteNode(oldVersionHistoryRef);
|
||||
}
|
||||
|
||||
private void v1MarkVersionHistory(NodeRef oldVersionHistoryRef)
|
||||
{
|
||||
String migratedName = PREFIX_MIGRATED+oldVersionHistoryRef.getId();
|
||||
dbNodeService.setProperty(oldVersionHistoryRef, ContentModel.PROP_NAME, migratedName);
|
||||
}
|
||||
|
||||
public List<ChildAssociationRef> getVersionHistories(final NodeRef rootNodeRef)
|
||||
{
|
||||
return dbNodeService.getChildAssocs(rootNodeRef);
|
||||
}
|
||||
|
||||
public int migrateVersions(final int batchSize, final boolean deleteImmediately)
|
||||
{
|
||||
final NodeRef oldRootNodeRef = dbNodeService.getRootNode(VersionMigrator.VERSION_STORE_REF_OLD);
|
||||
|
||||
final List<ChildAssociationRef> childAssocRefs = getVersionHistories(oldRootNodeRef);
|
||||
|
||||
int toDo = childAssocRefs.size();
|
||||
|
||||
if (toDo == 0)
|
||||
{
|
||||
logger.info(I18NUtil.getMessage(MSG_PATCH_NOOP));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found "+toDo+" version histories in old version store");
|
||||
}
|
||||
|
||||
// note: assumes patch runs before cleanup starts
|
||||
startTime = System.currentTimeMillis();
|
||||
percentComplete = 0;
|
||||
|
||||
int vhCount = 0;
|
||||
int alreadyMigratedCount = 0;
|
||||
int failCount = 0;
|
||||
|
||||
RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
boolean wasMLAware = MLPropertyInterceptor.setMLAware(true);
|
||||
SessionSizeResourceManager.setDisableInTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
int batchCount = 0;
|
||||
int totalCount = 0;
|
||||
|
||||
final List<NodeRef> tmpBatch = new ArrayList<NodeRef>(batchSize);
|
||||
|
||||
for (final ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
reportProgress(MSG_PATCH_PROGRESS, toDo, totalCount);
|
||||
totalCount++;
|
||||
|
||||
if (((String)dbNodeService.getProperty(childAssocRef.getChildRef(), ContentModel.PROP_NAME)).startsWith(VersionMigrator.PREFIX_MIGRATED))
|
||||
{
|
||||
// skip - already migrated
|
||||
alreadyMigratedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (batchCount < batchSize)
|
||||
{
|
||||
tmpBatch.add(childAssocRef.getChildRef());
|
||||
batchCount++;
|
||||
}
|
||||
|
||||
if ((batchCount == batchSize) || (totalCount == childAssocRefs.size()))
|
||||
{
|
||||
while (tmpBatch.size() != 0)
|
||||
{
|
||||
txHelper.setMaxRetries(1);
|
||||
|
||||
NodeRef failed = txHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Attempt to migrate batch of "+tmpBatch.size()+" version histories");
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
for (NodeRef oldVHNodeRef : tmpBatch)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef versionedNodeRef = v1GetVersionedNodeRef(oldVHNodeRef);
|
||||
migrateVersionHistory(oldVHNodeRef, versionedNodeRef);
|
||||
|
||||
if (deleteImmediately)
|
||||
{
|
||||
// delete old version history node
|
||||
v1DeleteVersionHistory(oldVHNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// mark old version history node for later cleanup
|
||||
v1MarkVersionHistory(oldVHNodeRef);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
logger.error("Skipping migration of: " + oldVHNodeRef, t);
|
||||
return oldVHNodeRef;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Migrated batch of "+tmpBatch.size()+" version histories in "+(System.currentTimeMillis()-startTime)+ " ms");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
if (failed != null)
|
||||
{
|
||||
tmpBatch.remove(failed); // retry batch without the failed node
|
||||
failCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
vhCount = vhCount + tmpBatch.size();
|
||||
tmpBatch.clear();
|
||||
batchCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
MLPropertyInterceptor.setMLAware(wasMLAware);
|
||||
SessionSizeResourceManager.setEnableInTransaction();
|
||||
}
|
||||
|
||||
if (failCount > 0)
|
||||
{
|
||||
logger.warn(I18NUtil.getMessage(MSG_PATCH_SKIP1, failCount));
|
||||
}
|
||||
else if (alreadyMigratedCount > 0)
|
||||
{
|
||||
logger.warn(I18NUtil.getMessage(MSG_PATCH_SKIP2, alreadyMigratedCount));
|
||||
}
|
||||
|
||||
logger.info(I18NUtil.getMessage(MSG_PATCH_COMPLETE, vhCount, ((System.currentTimeMillis()-startTime)/1000)));
|
||||
|
||||
return vhCount;
|
||||
}
|
||||
|
||||
|
||||
public void executeCleanup(final int batchSize)
|
||||
{
|
||||
if (! busy)
|
||||
{
|
||||
try
|
||||
{
|
||||
busy = true;
|
||||
|
||||
final RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper();
|
||||
txHelper.setMaxRetries(1);
|
||||
txHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
NodeRef oldRootNodeRef = dbNodeService.getRootNode(VersionMigrator.VERSION_STORE_REF_OLD);
|
||||
List<ChildAssociationRef> childAssocRefs = getVersionHistories(oldRootNodeRef);
|
||||
|
||||
int toDo = childAssocRefs.size();
|
||||
|
||||
if (toDo > 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found "+toDo+" version histories in old version store");
|
||||
}
|
||||
|
||||
// note: assumes cleanup runs after patch has completed
|
||||
startTime = System.currentTimeMillis();
|
||||
percentComplete = 0;
|
||||
|
||||
int deletedCount = 0;
|
||||
int failCount = 0;
|
||||
int notMigratedCount = 0;
|
||||
|
||||
boolean wasMLAware = MLPropertyInterceptor.setMLAware(true);
|
||||
SessionSizeResourceManager.setDisableInTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
int batchCount = 0;
|
||||
int totalCount = 0;
|
||||
|
||||
final List<NodeRef> tmpBatch = new ArrayList<NodeRef>(batchSize);
|
||||
|
||||
for (final ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
reportProgress(MSG_DELETE_PROGRESS, toDo, totalCount);
|
||||
totalCount++;
|
||||
|
||||
if (((String)dbNodeService.getProperty(childAssocRef.getChildRef(), ContentModel.PROP_NAME)).startsWith(VersionMigrator.PREFIX_MIGRATED))
|
||||
{
|
||||
if (batchCount < batchSize)
|
||||
{
|
||||
tmpBatch.add(childAssocRef.getChildRef());
|
||||
batchCount++;
|
||||
}
|
||||
|
||||
if ((batchCount == batchSize) || (totalCount == childAssocRefs.size()))
|
||||
{
|
||||
while (tmpBatch.size() != 0)
|
||||
{
|
||||
txHelper.setMaxRetries(1);
|
||||
NodeRef failed = txHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Attempt to delete batch of "+tmpBatch.size()+" migrated version histories");
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
for (NodeRef oldVHNodeRef : tmpBatch)
|
||||
{
|
||||
try
|
||||
{
|
||||
// delete old version history node
|
||||
v1DeleteVersionHistory(oldVHNodeRef);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
logger.error("Skipping deletion of: " + oldVHNodeRef, t);
|
||||
return oldVHNodeRef;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted batch of "+tmpBatch.size()+" migrated version histories in "+(System.currentTimeMillis()-startTime)+ " ms");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
if (failed != null)
|
||||
{
|
||||
tmpBatch.remove(failed); // retry batch without the failed node
|
||||
failCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
deletedCount = deletedCount + tmpBatch.size();
|
||||
tmpBatch.clear();
|
||||
batchCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
notMigratedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
MLPropertyInterceptor.setMLAware(wasMLAware);
|
||||
SessionSizeResourceManager.setEnableInTransaction();
|
||||
}
|
||||
|
||||
if (failCount > 0)
|
||||
{
|
||||
logger.warn(I18NUtil.getMessage(MSG_DELETE_SKIP1, failCount));
|
||||
}
|
||||
|
||||
if (notMigratedCount > 0)
|
||||
{
|
||||
logger.warn(I18NUtil.getMessage(MSG_DELETE_SKIP2, notMigratedCount));
|
||||
}
|
||||
|
||||
logger.info(I18NUtil.getMessage(MSG_DELETE_COMPLETE, deletedCount, ((System.currentTimeMillis()-startTime)/1000)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}, true, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Support to report % completion and estimated completion time.
|
||||
*
|
||||
* @param estimatedTotal
|
||||
* @param currentInteration
|
||||
*/
|
||||
protected void reportProgress(String msgKey, long estimatedTotal, long currentInteration)
|
||||
{
|
||||
if (currentInteration == 0)
|
||||
{
|
||||
percentComplete = 0;
|
||||
}
|
||||
else if (currentInteration * 100l / estimatedTotal > percentComplete)
|
||||
{
|
||||
int previous = percentComplete;
|
||||
percentComplete = (int) (currentInteration * 100l / estimatedTotal);
|
||||
|
||||
if (percentComplete < 100)
|
||||
{
|
||||
// conditional report
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long timeSoFar = currentTime - startTime;
|
||||
long timeRemaining = timeSoFar * (100 - percentComplete) / percentComplete;
|
||||
|
||||
int report = -1;
|
||||
|
||||
if (timeRemaining > 60000)
|
||||
{
|
||||
int reportInterval = getreportingInterval(timeSoFar, timeRemaining);
|
||||
|
||||
for (int i = previous + 1; i <= percentComplete; i++)
|
||||
{
|
||||
if (i % reportInterval == 0)
|
||||
{
|
||||
report = i;
|
||||
}
|
||||
}
|
||||
if (report > 0)
|
||||
{
|
||||
Date end = new Date(currentTime + timeRemaining);
|
||||
logger.info(I18NUtil.getMessage(msgKey, report, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getreportingInterval(long soFar, long toGo)
|
||||
{
|
||||
long total = soFar + toGo;
|
||||
if (total < RANGE_10)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
else if (total < RANGE_5)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else if (total < RANGE_2)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
232
source/java/org/alfresco/repo/version/VersionMigratorTest.java
Normal file
232
source/java/org/alfresco/repo/version/VersionMigratorTest.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Test simple version store migration
|
||||
*/
|
||||
public class VersionMigratorTest extends BaseVersionStoreTest
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(VersionMigratorTest.class);
|
||||
|
||||
protected VersionServiceImpl version1Service = new VersionServiceImpl();
|
||||
|
||||
protected Version2ServiceImpl version2Service;
|
||||
protected NodeService versionNodeService;
|
||||
|
||||
protected VersionMigrator versionMigrator;
|
||||
protected PolicyComponent policyComponent;
|
||||
protected DictionaryService dictionaryService;
|
||||
|
||||
public VersionMigratorTest()
|
||||
{
|
||||
//super.setDefaultRollback(false); // default is true
|
||||
}
|
||||
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
super.onSetUpInTransaction();
|
||||
|
||||
this.versionMigrator = (VersionMigrator)applicationContext.getBean("versionMigrator");
|
||||
this.policyComponent = (PolicyComponent)applicationContext.getBean("policyComponent");
|
||||
this.dictionaryService = (DictionaryService)applicationContext.getBean("dictionaryService");
|
||||
this.version2Service = (Version2ServiceImpl)applicationContext.getBean("versionService");
|
||||
this.versionNodeService = (NodeService)applicationContext.getBean("versionNodeService"); // note: auto-switches between V1 and V2
|
||||
|
||||
// Version1Service is used to create the version nodes in Version1Store (workspace://lightWeightVersionStore)
|
||||
version1Service.setDbNodeService(dbNodeService);
|
||||
version1Service.setNodeService(dbNodeService);
|
||||
version1Service.setVersionCounterService(versionCounterDaoService);
|
||||
version1Service.setPolicyComponent(policyComponent);
|
||||
version1Service.setDictionaryService(dictionaryService);
|
||||
version1Service.initialiseWithoutBind(); // TODO - temp - if use intialise, get: "More than one CalculateVersionLabelPolicy behaviour has been registered for the type {http://www.alfresco.org/model/content/1.0}content"
|
||||
|
||||
super.setVersionService(version1Service);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test migration of a simple versioned node (one version, no children)
|
||||
*/
|
||||
public void testMigrateOneVersion() throws Exception
|
||||
{
|
||||
if (version2Service.useDeprecatedV1 == true)
|
||||
{
|
||||
logger.info("testMigrateOneVersion: skip");
|
||||
return;
|
||||
}
|
||||
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
|
||||
logger.info("testMigrateOneVersion: versionedNodeRef = " + versionableNode);
|
||||
|
||||
// Get the next version number
|
||||
int nextVersion = peekNextVersionNumber();
|
||||
String nextVersionLabel = peekNextVersionLabel(versionableNode, nextVersion, versionProperties);
|
||||
|
||||
// Snap-shot the date-time
|
||||
Date beforeVersionDate = new Date();
|
||||
long beforeVersionTime = beforeVersionDate.getTime();
|
||||
logger.info("beforeVersion Date/Time: " + beforeVersionDate + " [" + beforeVersionTime + "]");
|
||||
|
||||
Version oldVersion = createVersion(versionableNode);
|
||||
|
||||
// get and store old version details for later comparison - versionNodeService will retrieve these from the old version store
|
||||
|
||||
QName oldVersionType = versionNodeService.getType(oldVersion.getFrozenStateNodeRef());
|
||||
Set<QName> oldVersionAspects = versionNodeService.getAspects(oldVersion.getFrozenStateNodeRef());
|
||||
Map<QName, Serializable> oldVersionProps = versionNodeService.getProperties(oldVersion.getFrozenStateNodeRef());
|
||||
|
||||
logger.info("oldVersion props: " + oldVersion);
|
||||
logger.info("oldVersion created: " + oldVersion.getCreatedDate() + " [" + oldVersion.getCreatedDate().getTime()+"]");
|
||||
|
||||
logger.info("oldVersion props via versionNodeService: " + oldVersionProps);
|
||||
|
||||
VersionHistory vh = version1Service.getVersionHistory(versionableNode);
|
||||
assertEquals(1, vh.getAllVersions().size());
|
||||
|
||||
NodeRef oldVHNodeRef = version1Service.getVersionHistoryNodeRef(versionableNode);
|
||||
|
||||
// Migrate and delete old version history !
|
||||
NodeRef versionedNodeRef = versionMigrator.v1GetVersionedNodeRef(oldVHNodeRef);
|
||||
NodeRef newVHNodeRef = versionMigrator.migrateVersionHistory(oldVHNodeRef, versionedNodeRef);
|
||||
versionMigrator.v1DeleteVersionHistory(oldVHNodeRef);
|
||||
|
||||
VersionHistory vh2 = version2Service.getVersionHistory(versionableNode);
|
||||
assertEquals(1, vh2.getAllVersions().size());
|
||||
|
||||
Version newVersion = vh2.getRootVersion();
|
||||
|
||||
logger.info("newVersion props: " + newVersion);
|
||||
logger.info("newVersion created: " + newVersion.getCreatedDate() + " [" + newVersion.getCreatedDate().getTime()+"]");
|
||||
|
||||
// check new version - switch to new version service to do the check
|
||||
super.setVersionService(version2Service);
|
||||
checkNewVersion(beforeVersionTime, nextVersion, nextVersionLabel, newVersion, versionableNode);
|
||||
|
||||
// get and compare new version details - - versionNodeService will retrieve these from the new version store
|
||||
|
||||
QName newVersionType = versionNodeService.getType(newVersion.getFrozenStateNodeRef());
|
||||
Set<QName> newVersionAspects = versionNodeService.getAspects(newVersion.getFrozenStateNodeRef());
|
||||
Map<QName, Serializable> newVersionProps = versionNodeService.getProperties(newVersion.getFrozenStateNodeRef());
|
||||
|
||||
logger.info("newVersion props via versionNodeService: " + newVersionProps);
|
||||
|
||||
assertEquals(oldVersionType, newVersionType);
|
||||
|
||||
assertEquals(oldVersionAspects.size(), newVersionAspects.size());
|
||||
for (QName key : oldVersionAspects)
|
||||
{
|
||||
assertTrue(""+key, newVersionAspects.contains(key));
|
||||
}
|
||||
|
||||
assertEquals(oldVersionProps.size(), newVersionProps.size());
|
||||
for (QName key : oldVersionProps.keySet())
|
||||
{
|
||||
assertEquals(""+key, oldVersionProps.get(key), newVersionProps.get(key));
|
||||
}
|
||||
|
||||
logger.info("testMigrateOneVersion: Migrated from oldVHNodeRef = " + oldVHNodeRef + " to newVHNodeRef = " + newVHNodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test migration of a multiple versioned nodes
|
||||
*/
|
||||
public void testMigrateMultipleVersions() throws Exception
|
||||
{
|
||||
if (version2Service.useDeprecatedV1 == true)
|
||||
{
|
||||
logger.info("testMigrateOneVersion: skip");
|
||||
return;
|
||||
}
|
||||
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
|
||||
// Get the next version number, next version label and snapshot the date-time
|
||||
int nextVersion1 = peekNextVersionNumber();
|
||||
String nextVersionLabel1 = peekNextVersionLabel(versionableNode, nextVersion1, versionProperties);
|
||||
long beforeVersionTime1 = System.currentTimeMillis();
|
||||
|
||||
Version version1 = createVersion(versionableNode);
|
||||
logger.info(version1);
|
||||
|
||||
// Get the next version number, next version label and snapshot the date-time
|
||||
int nextVersion2 = peekNextVersionNumber();
|
||||
String nextVersionLabel2 = peekNextVersionLabel(versionableNode, nextVersion2, versionProperties);
|
||||
long beforeVersionTime2 = System.currentTimeMillis();
|
||||
|
||||
Version version2 = createVersion(versionableNode);
|
||||
logger.info(version2);
|
||||
|
||||
// Get the next version number, next version label and snapshot the date-time
|
||||
int nextVersion3 = peekNextVersionNumber();
|
||||
String nextVersionLabel3 = peekNextVersionLabel(versionableNode, nextVersion3, versionProperties);
|
||||
long beforeVersionTime3 = System.currentTimeMillis();
|
||||
|
||||
Version version3 = createVersion(versionableNode);
|
||||
logger.info(version3);
|
||||
|
||||
VersionHistory vh1 = version1Service.getVersionHistory(versionableNode);
|
||||
assertEquals(3, vh1.getAllVersions().size());
|
||||
|
||||
logger.info("testMigrateMultipleVersions: versionedNodeRef = " + versionableNode);
|
||||
|
||||
NodeRef oldVHNodeRef = version1Service.getVersionHistoryNodeRef(versionableNode);
|
||||
|
||||
// Migrate and delete old version history !
|
||||
NodeRef versionedNodeRef = versionMigrator.v1GetVersionedNodeRef(oldVHNodeRef);
|
||||
NodeRef newVHNodeRef = versionMigrator.migrateVersionHistory(oldVHNodeRef, versionedNodeRef);
|
||||
versionMigrator.v1DeleteVersionHistory(oldVHNodeRef);
|
||||
|
||||
VersionHistory vh2 = version2Service.getVersionHistory(versionableNode);
|
||||
assertEquals(3, vh2.getAllVersions().size());
|
||||
|
||||
// TODO move check version history into BaseVersionStoreTest
|
||||
// check new versions - switch to new version service to do the check
|
||||
super.setVersionService(version2Service);
|
||||
|
||||
Version[] newVersions = vh2.getAllVersions().toArray(new Version[]{});
|
||||
|
||||
checkVersion(beforeVersionTime1, nextVersion1, nextVersionLabel1, newVersions[2], versionableNode);
|
||||
checkVersion(beforeVersionTime2, nextVersion2, nextVersionLabel2, newVersions[1], versionableNode);
|
||||
checkNewVersion(beforeVersionTime3, nextVersion3, nextVersionLabel3, newVersions[0], versionableNode);
|
||||
|
||||
logger.info("testMigrateMultipleVersions: Migrated from oldVHNodeRef = " + oldVHNodeRef + " to newVHNodeRef = " + newVHNodeRef);
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,60 +24,38 @@
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* interface conating the constants used by the light weight
|
||||
* version store implementation
|
||||
* Version1 Model Constants used by lightWeightVersionStore implementation
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface VersionModel
|
||||
public interface VersionModel extends VersionBaseModel
|
||||
{
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
public static final String NAMESPACE_URI = "http://www.alfresco.org/model/versionstore/1.0";
|
||||
|
||||
/**
|
||||
* The store protocol
|
||||
*/
|
||||
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
|
||||
|
||||
/**
|
||||
* The store id
|
||||
*/
|
||||
public static final String STORE_ID = "lightWeightVersionStore";
|
||||
|
||||
|
||||
public static final String PROP_VERSION_LABEL = "versionLabel";
|
||||
public static final String PROP_CREATED_DATE = ContentModel.PROP_CREATED.getLocalName();
|
||||
public static final String PROP_CREATOR = ContentModel.PROP_CREATOR.getLocalName();
|
||||
public static final String PROP_VERSION_TYPE = "versionType";
|
||||
public static final String PROP_VERSION_NUMBER = "versionNumber";
|
||||
public static final String PROP_FROZEN_NODE_ID = "frozenNodeId";
|
||||
public static final String PROP_FROZEN_NODE_TYPE = "frozenNodeType";
|
||||
public static final String PROP_FROZEN_NODE_STORE_PROTOCOL = "frozenNodeStoreProtocol";
|
||||
public static final String PROP_FROZEN_NODE_STORE_ID = "frozenNodeStoreId";
|
||||
public static final String PROP_FROZEN_ASPECTS = "frozenAspects";
|
||||
|
||||
/** The version store root aspect */
|
||||
public static final QName ASPECT_VERSION_STORE_ROOT = QName.createQName(NAMESPACE_URI, "versionStoreRoot");
|
||||
public static final QName ASPECT_VERSION_STORE_ROOT = QName.createQName(NAMESPACE_URI, ASPECT_LOCALNAME_VERSION_STORE_ROOT);
|
||||
|
||||
/**
|
||||
* Version history type
|
||||
*/
|
||||
public static final String TYPE_VERSION_HISTORY = "versionHistory";
|
||||
public static final QName TYPE_QNAME_VERSION_HISTORY = QName.createQName(NAMESPACE_URI, TYPE_VERSION_HISTORY);
|
||||
|
||||
/**
|
||||
* Version history properties and associations
|
||||
*/
|
||||
public static final String PROP_VERSIONED_NODE_ID = "versionedNodeId";
|
||||
public static final QName PROP_QNAME_VERSIONED_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_VERSIONED_NODE_ID);
|
||||
public static final QName ASSOC_ROOT_VERSION = QName.createQName(NAMESPACE_URI, "rootVersion");
|
||||
public static final QName ASSOC_ROOT_VERSION = QName.createQName(NAMESPACE_URI, ASSOC_LOCALNAME_ROOT_VERSION);
|
||||
|
||||
/**
|
||||
* Verison type
|
||||
@@ -88,6 +66,12 @@ public interface VersionModel
|
||||
/**
|
||||
* Version type properties and associations
|
||||
*/
|
||||
public static final String PROP_FROZEN_NODE_ID = "frozenNodeId";
|
||||
public static final String PROP_FROZEN_NODE_STORE_PROTOCOL = "frozenNodeStoreProtocol";
|
||||
public static final String PROP_FROZEN_NODE_STORE_ID = "frozenNodeStoreId";
|
||||
public static final String PROP_FROZEN_NODE_TYPE = "frozenNodeType";
|
||||
public static final String PROP_FROZEN_ASPECTS = "frozenAspects";
|
||||
|
||||
public static final QName PROP_QNAME_VERSION_LABEL = QName.createQName(NAMESPACE_URI, PROP_VERSION_LABEL);
|
||||
public static final QName PROP_QNAME_VERSION_NUMBER = QName.createQName(NAMESPACE_URI, PROP_VERSION_NUMBER);
|
||||
public static final QName PROP_QNAME_FROZEN_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_ID);
|
||||
@@ -156,8 +140,6 @@ public interface VersionModel
|
||||
/**
|
||||
* Child relationship names
|
||||
*/
|
||||
public static final String CHILD_VERSION_HISTORIES = "versionHistory";
|
||||
public static final String CHILD_VERSIONS = "version";
|
||||
public static final String CHILD_VERSIONED_ATTRIBUTES = "versionedAttributes";
|
||||
public static final String CHILD_VERSIONED_CHILD_ASSOCS = "versionedChildAssocs";
|
||||
public static final String CHILD_VERSIONED_ASSOCS = "versionedAssocs";
|
||||
@@ -173,7 +155,5 @@ public interface VersionModel
|
||||
/**
|
||||
* Created version associated to the deleted translations of an mlContainer
|
||||
*/
|
||||
public static final String PROP_TRANSLATION_VERIONS = "translationVersions";
|
||||
public static final QName PROP_QNAME_TRANSLATION_VERIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERIONS);
|
||||
|
||||
public static final QName PROP_QNAME_TRANSLATION_VERSIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERSIONS);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -34,6 +34,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
@@ -43,6 +44,9 @@ import org.alfresco.repo.version.common.VersionImpl;
|
||||
import org.alfresco.repo.version.common.VersionUtil;
|
||||
import org.alfresco.repo.version.common.counter.VersionCounterService;
|
||||
import org.alfresco.repo.version.common.versionlabel.SerialVersionLabelPolicy;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.AspectMissingException;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -59,29 +63,32 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The version service implementation.
|
||||
* Version1 Service - implements lightWeightVersionStore
|
||||
*
|
||||
* @author Roy Wetheral
|
||||
*/
|
||||
public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
implements VersionService, VersionModel
|
||||
public class VersionServiceImpl extends AbstractVersionServiceImpl implements VersionService, VersionModel
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(VersionServiceImpl.class);
|
||||
|
||||
/**
|
||||
* Error message I18N id's
|
||||
*/
|
||||
private static final String MSGID_ERR_NOT_FOUND = "version_service.err_not_found";
|
||||
private static final String MSGID_ERR_NO_BRANCHES = "version_service.err_unsupported";
|
||||
private static final String MSGID_ERR_RESTORE_EXISTS = "version_service.err_restore_exists";
|
||||
private static final String MSGID_ERR_ONE_PRECEEDING = "version_service.err_one_preceeding";
|
||||
private static final String MSGID_ERR_RESTORE_NO_VERSION = "version_service.err_restore_no_version";
|
||||
private static final String MSGID_ERR_REVERT_MISMATCH = "version_service.err_revert_mismatch";
|
||||
protected static final String MSGID_ERR_NOT_FOUND = "version_service.err_not_found";
|
||||
protected static final String MSGID_ERR_NO_BRANCHES = "version_service.err_unsupported";
|
||||
protected static final String MSGID_ERR_RESTORE_EXISTS = "version_service.err_restore_exists";
|
||||
protected static final String MSGID_ERR_ONE_PRECEEDING = "version_service.err_one_preceeding";
|
||||
protected static final String MSGID_ERR_RESTORE_NO_VERSION = "version_service.err_restore_no_version";
|
||||
protected static final String MSGID_ERR_REVERT_MISMATCH = "version_service.err_revert_mismatch";
|
||||
|
||||
/**
|
||||
* The version counter service
|
||||
*/
|
||||
private VersionCounterService versionCounterService;
|
||||
protected VersionCounterService versionCounterService;
|
||||
|
||||
/**
|
||||
* The db node service, used as the version store implementation
|
||||
@@ -91,13 +98,12 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
/**
|
||||
* Policy behaviour filter
|
||||
*/
|
||||
private BehaviourFilter policyBehaviourFilter;
|
||||
protected BehaviourFilter policyBehaviourFilter;
|
||||
|
||||
/**
|
||||
* The repository searcher
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private SearchService searcher;
|
||||
protected SearchService searcher; // unused
|
||||
|
||||
/**
|
||||
* Sets the db node service, used as the version store implementation
|
||||
@@ -156,11 +162,18 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
new JavaBehaviour(new SerialVersionLabelPolicy(), "calculateVersionLabel"));
|
||||
}
|
||||
|
||||
// TODO - temp
|
||||
protected void initialiseWithoutBind()
|
||||
{
|
||||
super.initialise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reference to the version store
|
||||
*
|
||||
* @return reference to the version store
|
||||
*/
|
||||
@Override
|
||||
public StoreRef getVersionStoreReference()
|
||||
{
|
||||
return new StoreRef(
|
||||
@@ -176,11 +189,20 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
Map<String, Serializable> versionProperties)
|
||||
throws ReservedVersionNameException, AspectMissingException
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// Get the next version number
|
||||
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
||||
|
||||
// Create the version
|
||||
return createVersion(nodeRef, versionProperties, versionNumber);
|
||||
Version version = createVersion(nodeRef, versionProperties, versionNumber);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("created version (" + versionNumber + " - " + VersionUtil.convertNodeRef(version.getFrozenStateNodeRef()) + ") in " + (System.currentTimeMillis()-startTime) + " ms");
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,11 +216,22 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
boolean versionChildren)
|
||||
throws ReservedVersionNameException, AspectMissingException
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// Get the next version number
|
||||
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
||||
|
||||
// Create the versions
|
||||
return createVersion(nodeRef, versionProperties, versionChildren, versionNumber);
|
||||
Collection<Version> versions = createVersion(nodeRef, versionProperties, versionChildren, versionNumber);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
Version[] versionsArray = versions.toArray(new Version[0]);
|
||||
Version version = versionsArray[versionsArray.length -1]; // last item is the new parent version
|
||||
logger.debug("created version (" + versionNumber + " - " + VersionUtil.convertNodeRef(version.getFrozenStateNodeRef()) + ") in "+ (System.currentTimeMillis()-startTime) +" ms "+(versionChildren ? "(with " + (versions.size() - 1) + " children)" : ""));
|
||||
}
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,6 +290,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
Map<String, Serializable> versionProperties)
|
||||
throws ReservedVersionNameException, AspectMissingException
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
Collection<Version> result = new ArrayList<Version>(nodeRefs.size());
|
||||
|
||||
// Get the next version number
|
||||
@@ -268,6 +303,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
result.add(createVersion(nodeRef, versionProperties, versionNumber));
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("created version list (" + versionNumber + " - " + getVersionStoreReference() + ") in "+ (System.currentTimeMillis()-startTime) +" ms (with " + nodeRefs.size() + " nodes)");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -282,12 +322,13 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
* @throws ReservedVersionNameException
|
||||
* thrown if there is a name clash in the version properties
|
||||
*/
|
||||
private Version createVersion(
|
||||
protected Version createVersion(
|
||||
NodeRef nodeRef,
|
||||
Map<String, Serializable> origVersionProperties,
|
||||
int versionNumber)
|
||||
throws ReservedVersionNameException
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// Copy the version properties (to prevent unexpected side effects to the caller)
|
||||
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
|
||||
@@ -370,7 +411,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
}
|
||||
|
||||
// Create the version data object
|
||||
Version version = getVersion(newVersionRef);
|
||||
Version version = this.getVersion(newVersionRef);
|
||||
|
||||
// Set the new version label on the versioned node
|
||||
this.nodeService.setProperty(
|
||||
@@ -386,6 +427,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
// Invoke the policy behaviour
|
||||
invokeAfterCreateVersion(nodeRef, version);
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("created Version (" + versionNumber + " - " + getVersionStoreReference() + ") " + nodeRef + " in " + (System.currentTimeMillis()-startTime) +" ms");
|
||||
}
|
||||
|
||||
// Return the data object representing the newly created version
|
||||
return version;
|
||||
}
|
||||
@@ -465,30 +511,30 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
Map<QName, Serializable> result = new HashMap<QName, Serializable>(10);
|
||||
|
||||
// Set the version number for the new version
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_NUMBER), Integer.toString(versionNumber));
|
||||
result.put(VersionModel.PROP_QNAME_VERSION_NUMBER, Integer.toString(versionNumber));
|
||||
|
||||
// Set the versionable node id
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_ID), nodeRef.getId());
|
||||
result.put(VersionModel.PROP_QNAME_FROZEN_NODE_ID, nodeRef.getId());
|
||||
|
||||
// Set the versionable node store protocol
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL), nodeRef.getStoreRef().getProtocol());
|
||||
result.put(VersionModel.PROP_QNAME_FROZEN_NODE_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
|
||||
|
||||
// Set the versionable node store id
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_ID), nodeRef.getStoreRef().getIdentifier());
|
||||
result.put(VersionModel.PROP_QNAME_FROZEN_NODE_STORE_ID, nodeRef.getStoreRef().getIdentifier());
|
||||
|
||||
// Store the current node type
|
||||
QName nodeType = this.nodeService.getType(nodeRef);
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_TYPE), nodeType);
|
||||
result.put(VersionModel.PROP_QNAME_FROZEN_NODE_TYPE, nodeType);
|
||||
|
||||
// Store the current aspects
|
||||
Set<QName> aspects = this.nodeService.getAspects(nodeRef);
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_ASPECTS), (Serializable)aspects);
|
||||
result.put(VersionModel.PROP_QNAME_FROZEN_ASPECTS, (Serializable)aspects);
|
||||
|
||||
// Calculate the version label
|
||||
QName classRef = this.nodeService.getType(nodeRef);
|
||||
Version preceedingVersion = getVersion(preceedingNodeRef);
|
||||
String versionLabel = invokeCalculateVersionLabel(classRef, preceedingVersion, versionNumber, versionProperties);
|
||||
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_LABEL), versionLabel);
|
||||
result.put(VersionModel.PROP_QNAME_VERSION_LABEL, versionLabel);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -557,6 +603,27 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Serializable> getVersionMetaData(NodeRef versionNodeRef)
|
||||
{
|
||||
// Get the meta data
|
||||
List<ChildAssociationRef> metaData = this.dbNodeService.getChildAssocs(
|
||||
versionNodeRef,
|
||||
RegexQNamePattern.MATCH_ALL,
|
||||
CHILD_QNAME_VERSION_META_DATA);
|
||||
|
||||
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(metaData.size());
|
||||
|
||||
for (ChildAssociationRef ref : metaData)
|
||||
{
|
||||
NodeRef metaDataValue = (NodeRef)ref.getChildRef();
|
||||
String name = (String)this.dbNodeService.getProperty(metaDataValue, PROP_QNAME_META_DATA_NAME);
|
||||
Serializable value = this.dbNodeService.getProperty(metaDataValue, PROP_QNAME_META_DATA_VALUE);
|
||||
versionProperties.put(name, value);
|
||||
}
|
||||
|
||||
return versionProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze the aspects
|
||||
*
|
||||
@@ -675,7 +742,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
*
|
||||
* @return the node ref to the root node of the version store
|
||||
*/
|
||||
private NodeRef getRootNode()
|
||||
protected NodeRef getRootNode()
|
||||
{
|
||||
// Get the version store root node reference
|
||||
return this.dbNodeService.getRootNode(getVersionStoreReference());
|
||||
@@ -691,12 +758,21 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
* @param nodeRef the node reference
|
||||
* @return a constructed version history object
|
||||
*/
|
||||
private VersionHistory buildVersionHistory(NodeRef versionHistoryRef, NodeRef nodeRef)
|
||||
protected VersionHistory buildVersionHistory(NodeRef versionHistoryRef, NodeRef nodeRef)
|
||||
{
|
||||
VersionHistory versionHistory = null;
|
||||
|
||||
ArrayList<NodeRef> versionHistoryNodeRefs = new ArrayList<NodeRef>();
|
||||
NodeRef currentVersion = getCurrentVersionNodeRef(versionHistoryRef, nodeRef);
|
||||
|
||||
NodeRef currentVersion;
|
||||
if (this.nodeService.exists(nodeRef))
|
||||
{
|
||||
currentVersion = getCurrentVersionNodeRef(versionHistoryRef, nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentVersion = VersionUtil.convertNodeRef(getLatestVersion(nodeRef).getFrozenStateNodeRef());
|
||||
}
|
||||
|
||||
while (currentVersion != null)
|
||||
{
|
||||
@@ -751,7 +827,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
* @param versionRef the version reference
|
||||
* @return object containing verison data
|
||||
*/
|
||||
private Version getVersion(NodeRef versionRef)
|
||||
protected Version getVersion(NodeRef versionRef)
|
||||
{
|
||||
if (versionRef == null)
|
||||
{
|
||||
@@ -768,17 +844,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
}
|
||||
|
||||
// Get the meta data
|
||||
List<ChildAssociationRef> metaData = this.dbNodeService.getChildAssocs(
|
||||
versionRef,
|
||||
RegexQNamePattern.MATCH_ALL,
|
||||
CHILD_QNAME_VERSION_META_DATA);
|
||||
for (ChildAssociationRef ref : metaData)
|
||||
{
|
||||
NodeRef metaDataValue = (NodeRef)ref.getChildRef();
|
||||
String name = (String)this.dbNodeService.getProperty(metaDataValue, PROP_QNAME_META_DATA_NAME);
|
||||
Serializable value = this.dbNodeService.getProperty(metaDataValue, PROP_QNAME_META_DATA_VALUE);
|
||||
versionProperties.put(name, value);
|
||||
}
|
||||
Map<String, Serializable> versionMetaDataProperties = getVersionMetaData(versionRef);
|
||||
versionProperties.putAll(versionMetaDataProperties);
|
||||
|
||||
// Create and return the version object
|
||||
NodeRef newNodeRef = new NodeRef(new StoreRef(STORE_PROTOCOL, STORE_ID), versionRef.getId());
|
||||
@@ -793,7 +860,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
* @param nodeRef a node reference
|
||||
* @return a reference to the version history node, null of none
|
||||
*/
|
||||
private NodeRef getVersionHistoryNodeRef(NodeRef nodeRef)
|
||||
protected NodeRef getVersionHistoryNodeRef(NodeRef nodeRef)
|
||||
{
|
||||
return this.dbNodeService.getChildByName(getRootNode(), CHILD_QNAME_VERSION_HISTORIES, nodeRef.getId());
|
||||
}
|
||||
@@ -1086,6 +1153,39 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
return version;
|
||||
}
|
||||
|
||||
private Version getLatestVersion(NodeRef nodeRef)
|
||||
{
|
||||
Version version = null;
|
||||
StoreRef storeRef = nodeRef.getStoreRef();
|
||||
|
||||
NodeRef versionHistoryNodeRef = getVersionHistoryNodeRef(nodeRef);
|
||||
if (versionHistoryNodeRef != null)
|
||||
{
|
||||
List<ChildAssociationRef> versionsAssoc = this.dbNodeService.getChildAssocs(versionHistoryNodeRef, RegexQNamePattern.MATCH_ALL, VersionModel.CHILD_QNAME_VERSIONS);
|
||||
for (ChildAssociationRef versionAssoc : versionsAssoc)
|
||||
{
|
||||
NodeRef versionNodeRef = versionAssoc.getChildRef();
|
||||
List<AssociationRef> predecessors = this.dbNodeService.getSourceAssocs(versionNodeRef, VersionModel.ASSOC_SUCCESSOR);
|
||||
if (predecessors.size() == 0)
|
||||
{
|
||||
String storeProtocol = (String)this.dbNodeService.getProperty(
|
||||
versionNodeRef,
|
||||
QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL));
|
||||
String storeId = (String)this.dbNodeService.getProperty(
|
||||
versionNodeRef,
|
||||
QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_ID));
|
||||
StoreRef versionStoreRef = new StoreRef(storeProtocol, storeId);
|
||||
if (storeRef.equals(versionStoreRef) == true)
|
||||
{
|
||||
version = getVersion(versionNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.cms.version.VersionService#deleteVersionHistory(NodeRef)
|
||||
*/
|
||||
@@ -1107,4 +1207,58 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defaultOnCreateVersion(
|
||||
QName classRef,
|
||||
NodeRef nodeRef,
|
||||
Map<String, Serializable> versionProperties,
|
||||
PolicyScope nodeDetails)
|
||||
{
|
||||
ClassDefinition classDefinition = this.dictionaryService.getClass(classRef);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
boolean wasMLAware = MLPropertyInterceptor.setMLAware(true);
|
||||
try
|
||||
{
|
||||
// Copy the properties
|
||||
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
|
||||
for (QName propertyName : propertyDefinitions.keySet())
|
||||
{
|
||||
Serializable propValue = this.nodeService.getProperty(nodeRef, propertyName);
|
||||
nodeDetails.addProperty(classRef, propertyName, propValue);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
MLPropertyInterceptor.setMLAware(wasMLAware);
|
||||
}
|
||||
|
||||
// Version the associations (child and target)
|
||||
Map<QName, AssociationDefinition> assocDefs = classDefinition.getAssociations();
|
||||
|
||||
// TODO: Need way of getting child assocs of a given type
|
||||
if (classDefinition.isContainer())
|
||||
{
|
||||
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(nodeRef);
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(childAssocRef.getTypeQName()))
|
||||
{
|
||||
nodeDetails.addChildAssociation(classDefinition.getName(), childAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need way of getting assocs of a given type
|
||||
List<AssociationRef> nodeAssocRefs = this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef nodeAssocRef : nodeAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(nodeAssocRef.getTypeQName()))
|
||||
{
|
||||
nodeDetails.addAssociation(classDefinition.getName(), nodeAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -70,6 +70,11 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
private static final String UPDATED_CONTENT_1 = "updatedContent1";
|
||||
private static final String UPDATED_CONTENT_2 = "updatedContent2";
|
||||
|
||||
public void testSetup()
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the creation of the initial version of a versionable node
|
||||
*/
|
||||
@@ -90,9 +95,39 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
createVersion(versionableNode);
|
||||
// TODO mess with some of the properties and stuff as you version
|
||||
createVersion(versionableNode);
|
||||
|
||||
VersionHistory vh = this.versionService.getVersionHistory(versionableNode);
|
||||
assertNotNull(vh);
|
||||
assertEquals(3, vh.getAllVersions().size());
|
||||
|
||||
// TODO check list of versions ... !
|
||||
}
|
||||
|
||||
// TODO test versioning a non versionable node ie: no version apsect
|
||||
/**
|
||||
* Tests the creation of multiple versions of a versionable node with null version properties
|
||||
*/
|
||||
public void testCreateManyVersionsWithNullVersionProperties()
|
||||
{
|
||||
this.versionProperties = null;
|
||||
|
||||
NodeRef versionableNode = createNewVersionableNode();
|
||||
createVersion(versionableNode);
|
||||
createVersion(versionableNode);
|
||||
createVersion(versionableNode);
|
||||
|
||||
VersionHistory vh = this.versionService.getVersionHistory(versionableNode);
|
||||
assertNotNull(vh);
|
||||
assertEquals(3, vh.getAllVersions().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test versioning a non versionable node ie: no version apsect
|
||||
*/
|
||||
public void testCreateInitialVersionWhenNotVersionable()
|
||||
{
|
||||
NodeRef node = createNewNode(); // not marked as versionable
|
||||
createVersion(node);
|
||||
}
|
||||
|
||||
// TODO test versioning numberious times with branchs implies by different workspaces
|
||||
|
||||
@@ -155,15 +190,28 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
for (Version version : versions)
|
||||
{
|
||||
// Get the frozen id from the version
|
||||
String frozenNodeId = (String)version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID);
|
||||
String frozenNodeId = null;
|
||||
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
frozenNodeId = ((NodeRef)version.getVersionProperty(Version2Model.PROP_FROZEN_NODE_REF)).getId();
|
||||
}
|
||||
else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
frozenNodeId = (String)version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID);
|
||||
}
|
||||
|
||||
assertNotNull("Unable to retrieve the frozen node id from the created version.", frozenNodeId);
|
||||
|
||||
// Get the origional node ref (based on the forzen node)
|
||||
NodeRef origionaNodeRef = this.versionableNodes.get(frozenNodeId);
|
||||
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", origionaNodeRef);
|
||||
NodeRef originalNodeRef = this.versionableNodes.get(frozenNodeId);
|
||||
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", originalNodeRef);
|
||||
|
||||
// Check the new version
|
||||
checkNewVersion(beforeVersionTime, expectedVersionNumber, expectedVersionLabel, version, origionaNodeRef);
|
||||
checkNewVersion(beforeVersionTime, expectedVersionNumber, expectedVersionLabel, version, originalNodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,12 +524,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Check that the initial version has not been created
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
// Add some content
|
||||
ContentWriter contentWriter = VersionServiceImplTest.this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
|
||||
ContentWriter contentWriter = contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
|
||||
assertNotNull(contentWriter);
|
||||
contentWriter.putContent(UPDATED_CONTENT_1);
|
||||
|
||||
@@ -494,7 +542,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(2, versionHistory.getAllVersions().size());
|
||||
|
||||
@@ -520,7 +568,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Add some content
|
||||
ContentWriter contentWriter = VersionServiceImplTest.this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
|
||||
ContentWriter contentWriter = contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, true);
|
||||
assertNotNull(contentWriter);
|
||||
contentWriter.putContent(UPDATED_CONTENT_1);
|
||||
|
||||
@@ -533,7 +581,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
@@ -567,7 +615,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||
assertNull(versionHistory);
|
||||
|
||||
return null;
|
||||
@@ -596,12 +644,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Check that the version history has been created
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
// Remove the versionable aspect
|
||||
VersionServiceImplTest.this.dbNodeService.removeAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
dbNodeService.removeAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -612,11 +660,11 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Check that the version history has been removed
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||
assertNull(versionHistory);
|
||||
|
||||
// Re-add the versionable aspect
|
||||
VersionServiceImplTest.this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||||
dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -627,7 +675,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Check that the version history has been created
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
@@ -658,12 +706,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
// Delete the node
|
||||
VersionServiceImplTest.this.dbNodeService.deleteNode(nodeRef);
|
||||
dbNodeService.deleteNode(nodeRef);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -674,15 +722,15 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Get the archived noderef
|
||||
NodeRef archivedNodeRef = VersionServiceImplTest.this.nodeArchiveService.getArchivedNode(nodeRef);
|
||||
NodeRef archivedNodeRef = nodeArchiveService.getArchivedNode(nodeRef);
|
||||
|
||||
// The archived noderef should still have a link to the version history
|
||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(archivedNodeRef);
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(archivedNodeRef);
|
||||
assertNotNull(versionHistory);
|
||||
assertEquals(1, versionHistory.getAllVersions().size());
|
||||
|
||||
// Delete the node for good
|
||||
VersionServiceImplTest.this.dbNodeService.deleteNode(archivedNodeRef);
|
||||
dbNodeService.deleteNode(archivedNodeRef);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -693,12 +741,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
// Get the archived noderef
|
||||
NodeRef archivedNodeRef = VersionServiceImplTest.this.nodeArchiveService.getArchivedNode(nodeRef);
|
||||
NodeRef archivedNodeRef = nodeArchiveService.getArchivedNode(nodeRef);
|
||||
|
||||
// Check that the version histories have been deleted
|
||||
VersionHistory versionHistory12 = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
||||
VersionHistory versionHistory12 = versionService.getVersionHistory(nodeRef);
|
||||
assertNull(versionHistory12);
|
||||
VersionHistory versionHistory23 = VersionServiceImplTest.this.versionService.getVersionHistory(archivedNodeRef);
|
||||
VersionHistory versionHistory23 = versionService.getVersionHistory(archivedNodeRef);
|
||||
assertNull(versionHistory23);
|
||||
|
||||
return null;
|
||||
@@ -761,8 +809,15 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
final AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// TEMP - for migration testing - force V1 store (override repository property)
|
||||
final Version2ServiceImpl version2ServiceImpl = (Version2ServiceImpl)ctx.getBean("versionService");
|
||||
version2ServiceImpl.setOnlyUseDeprecatedV1(true);
|
||||
|
||||
System.out.println("Using: " + versionService.getVersionStoreReference());
|
||||
|
||||
// Create a new store
|
||||
StoreRef storeRef = new StoreRef("test", "VersionServiceImplTest.main");
|
||||
StoreRef storeRef = new StoreRef("test", "VersionServiceImplTest-main-"+System.currentTimeMillis());
|
||||
if (!nodeService.exists(storeRef))
|
||||
{
|
||||
nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||
@@ -819,5 +874,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
||||
lastReport = now;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Finished: " + fileCount);
|
||||
}
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ public class VersionTestSuite extends TestSuite
|
||||
suite.addTestSuite(VersionServiceImplTest.class);
|
||||
suite.addTestSuite(NodeServiceImplTest.class);
|
||||
suite.addTestSuite(ContentServiceImplTest.class);
|
||||
suite.addTestSuite(VersionMigratorTest.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -205,6 +205,7 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate
|
||||
// Queue create version action
|
||||
Map<String, Serializable> versionDetails = new HashMap<String, Serializable>(1);
|
||||
versionDetails.put(Version.PROP_DESCRIPTION, I18NUtil.getMessage(MSG_INITIAL_VERSION));
|
||||
|
||||
this.versionService.createVersion(nodeRef, versionDetails);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -26,11 +26,9 @@ package org.alfresco.repo.version.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
@@ -39,18 +37,13 @@ import org.alfresco.repo.version.VersionServicePolicies.AfterCreateVersionPolicy
|
||||
import org.alfresco.repo.version.VersionServicePolicies.BeforeCreateVersionPolicy;
|
||||
import org.alfresco.repo.version.VersionServicePolicies.CalculateVersionLabelPolicy;
|
||||
import org.alfresco.repo.version.VersionServicePolicies.OnCreateVersionPolicy;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
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.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionServiceException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
/**
|
||||
* Abstract version service implementation.
|
||||
@@ -223,58 +216,11 @@ public abstract class AbstractVersionServiceImpl
|
||||
* @param versionProperties
|
||||
* @param nodeDetails
|
||||
*/
|
||||
protected void defaultOnCreateVersion(
|
||||
abstract protected void defaultOnCreateVersion(
|
||||
QName classRef,
|
||||
NodeRef nodeRef,
|
||||
Map<String, Serializable> versionProperties,
|
||||
PolicyScope nodeDetails)
|
||||
{
|
||||
ClassDefinition classDefinition = this.dictionaryService.getClass(classRef);
|
||||
if (classDefinition != null)
|
||||
{
|
||||
boolean wasMLAware = MLPropertyInterceptor.setMLAware(true);
|
||||
try
|
||||
{
|
||||
// Copy the properties
|
||||
Map<QName,PropertyDefinition> propertyDefinitions = classDefinition.getProperties();
|
||||
for (QName propertyName : propertyDefinitions.keySet())
|
||||
{
|
||||
Serializable propValue = this.nodeService.getProperty(nodeRef, propertyName);
|
||||
nodeDetails.addProperty(classRef, propertyName, propValue);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
MLPropertyInterceptor.setMLAware(wasMLAware);
|
||||
}
|
||||
|
||||
// Version the associations (child and target)
|
||||
Map<QName, AssociationDefinition> assocDefs = classDefinition.getAssociations();
|
||||
|
||||
// TODO: Need way of getting child assocs of a given type
|
||||
if (classDefinition.isContainer())
|
||||
{
|
||||
List<ChildAssociationRef> childAssocRefs = this.nodeService.getChildAssocs(nodeRef);
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(childAssocRef.getTypeQName()))
|
||||
{
|
||||
nodeDetails.addChildAssociation(classDefinition.getName(), childAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Need way of getting assocs of a given type
|
||||
List<AssociationRef> nodeAssocRefs = this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef nodeAssocRef : nodeAssocRefs)
|
||||
{
|
||||
if (assocDefs.containsKey(nodeAssocRef.getTypeQName()))
|
||||
{
|
||||
nodeDetails.addAssociation(classDefinition.getName(), nodeAssocRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PolicyScope nodeDetails);
|
||||
|
||||
/**
|
||||
* Invoke the calculate version label policy behaviour
|
||||
@@ -314,4 +260,5 @@ public abstract class AbstractVersionServiceImpl
|
||||
return versionLabel;
|
||||
}
|
||||
|
||||
abstract public StoreRef getVersionStoreReference();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -225,11 +225,11 @@ public class VersionHistoryImplTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
Collection versions2 = vh.getSuccessors(this.childVersion1);
|
||||
Collection<Version> versions2 = vh.getSuccessors(this.childVersion1);
|
||||
assertNotNull(versions2);
|
||||
assertTrue(versions2.isEmpty());
|
||||
|
||||
Collection versions3 = vh.getSuccessors(this.childVersion2);
|
||||
Collection<Version> versions3 = vh.getSuccessors(this.childVersion2);
|
||||
assertNotNull(versions3);
|
||||
assertTrue(versions3.isEmpty());
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -28,6 +28,8 @@ import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.version.Version2Model;
|
||||
import org.alfresco.repo.version.VersionBaseModel;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -45,6 +47,7 @@ import org.alfresco.service.cmr.version.VersionType;
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
|
||||
public class VersionImpl implements Version
|
||||
{
|
||||
/**
|
||||
@@ -98,16 +101,21 @@ public class VersionImpl implements Version
|
||||
/**
|
||||
* Helper method to get the created date from the version property data.
|
||||
*
|
||||
* @return the date the version was created
|
||||
* @return the date the version was created (note: not the date of the original node)
|
||||
*/
|
||||
public Date getCreatedDate()
|
||||
{
|
||||
return (Date)this.versionProperties.get(VersionModel.PROP_CREATED_DATE);
|
||||
return (Date)this.versionProperties.get(VersionBaseModel.PROP_CREATED_DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the creator from the version property data.
|
||||
*
|
||||
* @return the creator of the version (note: not the creator of the original node)
|
||||
*/
|
||||
public String getCreator()
|
||||
{
|
||||
return (String)this.versionProperties.get(VersionModel.PROP_CREATOR);
|
||||
return (String)this.versionProperties.get(VersionBaseModel.PROP_CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +125,7 @@ public class VersionImpl implements Version
|
||||
*/
|
||||
public String getVersionLabel()
|
||||
{
|
||||
return (String)this.versionProperties.get(VersionModel.PROP_VERSION_LABEL);
|
||||
return (String)this.versionProperties.get(VersionBaseModel.PROP_VERSION_LABEL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +135,7 @@ public class VersionImpl implements Version
|
||||
*/
|
||||
public VersionType getVersionType()
|
||||
{
|
||||
return (VersionType)this.versionProperties.get(VersionModel.PROP_VERSION_TYPE);
|
||||
return (VersionType)this.versionProperties.get(VersionBaseModel.PROP_VERSION_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +145,7 @@ public class VersionImpl implements Version
|
||||
*/
|
||||
public String getDescription()
|
||||
{
|
||||
return (String)this.versionProperties.get(PROP_DESCRIPTION);
|
||||
return (String)this.versionProperties.get(Version.PROP_DESCRIPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,10 +174,24 @@ public class VersionImpl implements Version
|
||||
*/
|
||||
public NodeRef getVersionedNodeRef()
|
||||
{
|
||||
String storeProtocol = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
|
||||
String storeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
|
||||
String nodeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
|
||||
return new NodeRef(new StoreRef(storeProtocol, storeId), nodeId);
|
||||
NodeRef versionedNodeRef = null;
|
||||
|
||||
// Switch VersionStore depending on configured impl
|
||||
if (nodeRef.getStoreRef().getIdentifier().equals(Version2Model.STORE_ID))
|
||||
{
|
||||
// V2 version store (eg. workspace://version2Store)
|
||||
versionedNodeRef = (NodeRef)this.versionProperties.get(Version2Model.PROP_FROZEN_NODE_REF);
|
||||
}
|
||||
else if (nodeRef.getStoreRef().getIdentifier().equals(VersionModel.STORE_ID))
|
||||
{
|
||||
// Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
|
||||
String storeProtocol = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
|
||||
String storeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
|
||||
String nodeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
|
||||
versionedNodeRef = new NodeRef(new StoreRef(storeProtocol, storeId), nodeId);
|
||||
}
|
||||
|
||||
return versionedNodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,12 +24,22 @@
|
||||
*/
|
||||
package org.alfresco.repo.version.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.Version2Model;
|
||||
import org.alfresco.repo.version.VersionBaseModel;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.version.ReservedVersionNameException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Helper class containing helper methods for the versioning services.
|
||||
@@ -42,14 +52,21 @@ public class VersionUtil
|
||||
* Reserved property names
|
||||
*/
|
||||
public static final String[] RESERVED_PROPERTY_NAMES = new String[]{
|
||||
VersionModel.PROP_CREATED_DATE,
|
||||
VersionModel.PROP_FROZEN_NODE_ID,
|
||||
VersionModel.PROP_FROZEN_NODE_STORE_ID,
|
||||
VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL,
|
||||
VersionModel.PROP_FROZEN_NODE_TYPE,
|
||||
VersionModel.PROP_FROZEN_ASPECTS,
|
||||
VersionModel.PROP_VERSION_LABEL,
|
||||
VersionModel.PROP_VERSION_NUMBER};
|
||||
VersionModel.PROP_FROZEN_NODE_ID, // deprecated
|
||||
VersionModel.PROP_FROZEN_NODE_STORE_ID, // deprecated
|
||||
VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL, // deprecated
|
||||
VersionModel.PROP_FROZEN_NODE_TYPE, // deprecated
|
||||
VersionModel.PROP_FROZEN_ASPECTS, // deprecated
|
||||
VersionBaseModel.PROP_CREATED_DATE,
|
||||
VersionBaseModel.PROP_VERSION_LABEL,
|
||||
VersionBaseModel.PROP_VERSION_NUMBER,
|
||||
VersionBaseModel.PROP_VERSION_DESCRIPTION,
|
||||
Version2Model.PROP_FROZEN_NODE_DBID,
|
||||
Version2Model.PROP_FROZEN_CREATED,
|
||||
Version2Model.PROP_FROZEN_CREATOR,
|
||||
Version2Model.PROP_FROZEN_MODIFIED,
|
||||
Version2Model.PROP_FROZEN_MODIFIER,
|
||||
Version2Model.PROP_FROZEN_ACCESSED};
|
||||
|
||||
/**
|
||||
* Checks that the names of the additional version properties are valid and that they do not clash
|
||||
@@ -93,4 +110,81 @@ public class VersionUtil
|
||||
{
|
||||
return new NodeRef(convertStoreRef(nodeRef.getStoreRef()), nodeRef.getId());
|
||||
}
|
||||
|
||||
|
||||
public static void convertFrozenToOriginalProps(Map<QName, Serializable> props) throws InvalidNodeRefException
|
||||
{
|
||||
if (props != null)
|
||||
{
|
||||
props.remove(Version2Model.PROP_QNAME_VERSION_DESCRIPTION);
|
||||
props.remove(Version2Model.PROP_QNAME_VERSION_NUMBER);
|
||||
|
||||
Set<QName> keys = new HashSet<QName>(props.keySet());
|
||||
for (QName key : keys)
|
||||
{
|
||||
String keyName = key.getLocalName();
|
||||
int idx = keyName.indexOf(Version2Model.PROP_METADATA_PREFIX);
|
||||
if (idx == 0)
|
||||
{
|
||||
props.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
String versionLabel = (String)props.get(Version2Model.PROP_QNAME_VERSION_LABEL);
|
||||
props.put(ContentModel.PROP_VERSION_LABEL, versionLabel);
|
||||
props.remove(Version2Model.PROP_QNAME_VERSION_LABEL);
|
||||
|
||||
// Convert frozen sys:referenceable properties
|
||||
NodeRef nodeRef = (NodeRef)props.get(Version2Model.PROP_QNAME_FROZEN_NODE_REF);
|
||||
if (nodeRef != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
|
||||
props.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
|
||||
props.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_NODE_REF);
|
||||
|
||||
Long dbid = (Long)props.get(Version2Model.PROP_QNAME_FROZEN_NODE_DBID);
|
||||
props.put(ContentModel.PROP_NODE_DBID, dbid);
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_NODE_DBID);
|
||||
|
||||
// Convert frozen cm:auditable properties
|
||||
|
||||
String creator = (String)props.get(Version2Model.PROP_QNAME_FROZEN_CREATOR);
|
||||
if (creator != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_CREATOR, creator);
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_CREATOR);
|
||||
|
||||
Date created = (Date)props.get(Version2Model.PROP_QNAME_FROZEN_CREATED);
|
||||
if (created != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_CREATED, created);
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_CREATED);
|
||||
|
||||
// TODO - check use-cases for get version, revert, restore ....
|
||||
String modifier = (String)props.get(Version2Model.PROP_QNAME_FROZEN_MODIFIER);
|
||||
if (modifier != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_MODIFIER, modifier);
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_MODIFIER);
|
||||
|
||||
Date modified = (Date)props.get(Version2Model.PROP_QNAME_FROZEN_MODIFIED);
|
||||
if (modified != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_MODIFIED, modified);
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_MODIFIED);
|
||||
|
||||
Date accessed = (Date)props.get(Version2Model.PROP_QNAME_FROZEN_ACCESSED);
|
||||
if (accessed != null)
|
||||
{
|
||||
props.put(ContentModel.PROP_ACCESSED, accessed);
|
||||
}
|
||||
props.remove(Version2Model.PROP_QNAME_FROZEN_ACCESSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,12 @@ public class SerialVersionLabelPolicy
|
||||
{
|
||||
serialVersionNumber = new SerialVersionLabel(preceedingVersion.getVersionLabel());
|
||||
|
||||
VersionType versionType = (VersionType)versionProperties.get(VersionModel.PROP_VERSION_TYPE);
|
||||
VersionType versionType = null;
|
||||
if (versionProperties != null)
|
||||
{
|
||||
versionType = (VersionType)versionProperties.get(VersionModel.PROP_VERSION_TYPE);
|
||||
}
|
||||
|
||||
if (VersionType.MAJOR.equals(versionType) == true)
|
||||
{
|
||||
serialVersionNumber.majorIncrement();
|
||||
|
140
source/java/org/alfresco/repo/version/version2_model.xml
Normal file
140
source/java/org/alfresco/repo/version/version2_model.xml
Normal file
@@ -0,0 +1,140 @@
|
||||
<model name="ver2:versionmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Alfresco Version2 Store Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2008-07-18</published>
|
||||
<version>2.0</version>
|
||||
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
</imports>
|
||||
|
||||
<namespaces>
|
||||
<namespace uri="http://www.alfresco.org/model/versionstore/2.0" prefix="ver2"/>
|
||||
</namespaces>
|
||||
|
||||
<types>
|
||||
|
||||
<type name="ver2:versionHistory">
|
||||
|
||||
<parent>cm:cmobject</parent>
|
||||
|
||||
<properties>
|
||||
<property name="ver2:versionedNodeId">
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
</properties>
|
||||
|
||||
<associations>
|
||||
<child-association name="ver2:version">
|
||||
<target>
|
||||
<class>sys:base</class>
|
||||
</target>
|
||||
</child-association>
|
||||
<association name="ver2:rootVersion">
|
||||
<target>
|
||||
<class>sys:base</class>
|
||||
</target>
|
||||
</association>
|
||||
</associations>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
|
||||
<aspect name="ver2:versionStoreRoot">
|
||||
<title>Version Store Root</title>
|
||||
<associations>
|
||||
<child-association name="ver2:versionHistory">
|
||||
<source>
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</source>
|
||||
<target>
|
||||
<class>ver2:versionHistory</class>
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</target>
|
||||
<duplicate>false</duplicate>
|
||||
</child-association>
|
||||
</associations>
|
||||
</aspect>
|
||||
|
||||
<aspect name="ver2:version">
|
||||
<title>Version</title>
|
||||
|
||||
<properties>
|
||||
<property name="ver2:versionNumber">
|
||||
<type>d:int</type>
|
||||
</property>
|
||||
<property name="ver2:versionLabel">
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="ver2:description">
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="ver2:frozenNodeType">
|
||||
<type>d:qname</type>
|
||||
</property>
|
||||
<property name="ver2:frozenAspects">
|
||||
<type>d:qname</type>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
|
||||
<!-- frozen sys:referenceable properties (x4) -->
|
||||
|
||||
<property name="ver2:frozenNodeStoreProtocol">
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
<property name="ver2:frozenNodeStoreId">
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
<property name="ver2:frozenNodeId">
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
<property name="ver2:frozenNodeDbId">
|
||||
<type>d:long</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
|
||||
<!-- frozen cm:auditable properties (x5) -->
|
||||
|
||||
<property name="ver2:frozenCreated">
|
||||
<title>Created</title>
|
||||
<type>d:datetime</type>
|
||||
<protected>true</protected>
|
||||
</property>
|
||||
<property name="ver2:frozenCreator">
|
||||
<title>Creator</title>
|
||||
<type>d:text</type>
|
||||
<protected>true</protected>
|
||||
</property>
|
||||
<property name="ver2:frozenModified">
|
||||
<title>Modified</title>
|
||||
<type>d:datetime</type>
|
||||
<protected>true</protected>
|
||||
</property>
|
||||
<property name="ver2:frozenModifier">
|
||||
<title>Modifier</title>
|
||||
<type>d:text</type>
|
||||
<protected>true</protected>
|
||||
</property>
|
||||
<property name="ver2:frozenAccessed">
|
||||
<title>Accessed</title>
|
||||
<type>d:datetime</type>
|
||||
<protected>true</protected>
|
||||
</property>
|
||||
|
||||
</properties>
|
||||
|
||||
</aspect>
|
||||
|
||||
</aspects>
|
||||
|
||||
</model>
|
@@ -1,5 +1,7 @@
|
||||
<model name="ver:versionmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<!-- deprecated -->
|
||||
|
||||
<description>Alfresco Version Store Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2005-05-30</published>
|
||||
|
@@ -28,6 +28,7 @@ import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.version.VersionBaseModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
|
||||
@@ -44,7 +45,7 @@ public interface Version extends Serializable
|
||||
/**
|
||||
* Names of the system version properties
|
||||
*/
|
||||
public static final String PROP_DESCRIPTION = "description";
|
||||
public static final String PROP_DESCRIPTION = VersionBaseModel.PROP_DESCRIPTION;
|
||||
|
||||
/**
|
||||
* Helper method to get the created date from the version property data.
|
||||
@@ -103,7 +104,7 @@ public interface Version extends Serializable
|
||||
* Note that this reference will be to the current state of the versioned
|
||||
* node which may now correspond to a later version.
|
||||
*
|
||||
* @return a node reference
|
||||
* @return a node reference (to the versioned node in the 'live' store)
|
||||
*/
|
||||
public NodeRef getVersionedNodeRef();
|
||||
|
||||
@@ -111,7 +112,7 @@ public interface Version extends Serializable
|
||||
* Gets the reference to the node that contains the frozen state of the
|
||||
* version.
|
||||
*
|
||||
* @return a node reference
|
||||
* @return a node reference (to the version node in the 'version' store)
|
||||
*/
|
||||
public NodeRef getFrozenStateNodeRef();
|
||||
}
|
||||
|
Reference in New Issue
Block a user