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>
|
</property>
|
||||||
</bean>
|
</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">
|
<bean id="spacesArchiveBootstrap" parent="spacesArchiveStoreImporter" singleton="false">
|
||||||
<property name="bootstrapViews">
|
<property name="bootstrapViews">
|
||||||
<list>
|
<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">
|
<property name="nodeService">
|
||||||
<ref bean="NodeService" />
|
<ref bean="NodeService" />
|
||||||
</property>
|
</property>
|
||||||
@@ -671,9 +671,15 @@
|
|||||||
<property name="policyBehaviourFilter">
|
<property name="policyBehaviourFilter">
|
||||||
<ref bean="policyBehaviourFilter" />
|
<ref bean="policyBehaviourFilter" />
|
||||||
</property>
|
</property>
|
||||||
|
<property name="permissionService">
|
||||||
|
<ref bean="permissionService" />
|
||||||
|
</property>
|
||||||
|
<property name="onlyUseDeprecatedV1">
|
||||||
|
<value>${version.store.onlyUseDeprecatedV1}</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="versionNodeService" class="org.alfresco.repo.version.NodeServiceImpl">
|
<bean id="versionNodeService" class="org.alfresco.repo.version.Node2ServiceImpl">
|
||||||
<property name="dbNodeService">
|
<property name="dbNodeService">
|
||||||
<ref bean="dbNodeService" />
|
<ref bean="dbNodeService" />
|
||||||
</property>
|
</property>
|
||||||
@@ -682,6 +688,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</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">
|
<bean id="versionCounterService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||||
<property name="proxyInterfaces">
|
<property name="proxyInterfaces">
|
||||||
<value>org.alfresco.repo.version.common.counter.VersionCounterService</value>
|
<value>org.alfresco.repo.version.common.counter.VersionCounterService</value>
|
||||||
@@ -798,7 +825,10 @@
|
|||||||
<!-- Implementation models -->
|
<!-- Implementation models -->
|
||||||
<value>org/alfresco/repo/action/actionModel.xml</value>
|
<value>org/alfresco/repo/action/actionModel.xml</value>
|
||||||
<value>org/alfresco/repo/rule/ruleModel.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 -->
|
<!-- Email model -->
|
||||||
<value>alfresco/model/emailServerModel.xml</value>
|
<value>alfresco/model/emailServerModel.xml</value>
|
||||||
|
@@ -165,7 +165,7 @@
|
|||||||
<prop key="packageName">spaces_archive</prop>
|
<prop key="packageName">spaces_archive</prop>
|
||||||
</props>
|
</props>
|
||||||
<props>
|
<props>
|
||||||
<prop key="storeRef">workspace://lightWeightVersionStore</prop>
|
<prop key="storeRef">${version.store.version2Store}</prop>
|
||||||
<prop key="packageName">versions</prop>
|
<prop key="packageName">versions</prop>
|
||||||
</props>
|
</props>
|
||||||
</list>
|
</list>
|
||||||
@@ -331,7 +331,13 @@
|
|||||||
|
|
||||||
<bean id="versionStoreImporter" parent="storeImporter" abstract="true">
|
<bean id="versionStoreImporter" parent="storeImporter" abstract="true">
|
||||||
<property name="storeUrl">
|
<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>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
@@ -223,3 +223,6 @@ patch.createSiteStore.result=Created the AVM site data store.
|
|||||||
|
|
||||||
patch.sitePermissionRefactorPatch.description=Create permission groups for sites.
|
patch.sitePermissionRefactorPatch.description=Create permission groups for sites.
|
||||||
patch.sitePermissionRefactorPatch.result=Groups have been created for all sites and user's allocated accordingly.
|
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_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.
|
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_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_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.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" >
|
<property name="maxErrorsPerTransaction" >
|
||||||
<value>5</value> <!-- limit output (exception and log) to the first N violation messages -->
|
<value>5</value> <!-- limit output (exception and log) to the first N violation messages -->
|
||||||
</property>
|
</property>
|
||||||
|
<property name="storesToIgnore">
|
||||||
|
<list>
|
||||||
|
<value>${version.store.version2Store}</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- tags nodes that are incomplete w.r.t. properties-->
|
<!-- tags nodes that are incomplete w.r.t. properties-->
|
||||||
@@ -142,6 +147,11 @@
|
|||||||
<property name="nodeService">
|
<property name="nodeService">
|
||||||
<ref bean="nodeService" />
|
<ref bean="nodeService" />
|
||||||
</property>
|
</property>
|
||||||
|
<property name="storesToIgnore">
|
||||||
|
<list>
|
||||||
|
<value>${version.store.version2Store}</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- NodeService implemented to persist to Database. Resource management enabled. -->
|
<!-- NodeService implemented to persist to Database. Resource management enabled. -->
|
||||||
|
@@ -1488,4 +1488,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</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>
|
</beans>
|
||||||
|
@@ -185,6 +185,12 @@ spaces.content_forms.childname=app:forms
|
|||||||
spaces.user_homes.childname=app:user_homes
|
spaces.user_homes.childname=app:user_homes
|
||||||
spaces.sites.childname=st:sites
|
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
|
# Folders for storing people
|
||||||
system.system_container.childname=sys:system
|
system.system_container.childname=sys:system
|
||||||
system.people_container.childname=sys:people
|
system.people_container.childname=sys:people
|
||||||
|
@@ -470,4 +470,36 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</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>
|
</beans>
|
@@ -19,4 +19,4 @@ version.build=@build-number@
|
|||||||
|
|
||||||
# Schema 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
|
import org.alfresco.repo.version.Version2Model;
|
||||||
import org.alfresco.repo.version.VersionModel;
|
import org.alfresco.repo.version.VersionModel;
|
||||||
import org.alfresco.repo.version.common.VersionUtil;
|
import org.alfresco.repo.version.common.VersionUtil;
|
||||||
import org.alfresco.service.cmr.ml.EditionService;
|
import org.alfresco.service.cmr.ml.EditionService;
|
||||||
@@ -257,9 +259,29 @@ public class EditionServiceImpl implements EditionService
|
|||||||
|
|
||||||
Map<QName, Serializable> properties = versionNodeService.getProperties(mlContainerEdition.getFrozenStateNodeRef());
|
Map<QName, Serializable> properties = versionNodeService.getProperties(mlContainerEdition.getFrozenStateNodeRef());
|
||||||
|
|
||||||
|
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
|
// get the serialisation of the version histories in the version properties
|
||||||
List<VersionHistory> versionHistories = (List<VersionHistory>)
|
versionHistories = (List<VersionHistory>)
|
||||||
properties.get(VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
|
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)
|
if (versionHistories == null)
|
||||||
{
|
{
|
||||||
@@ -296,8 +318,21 @@ public class EditionServiceImpl implements EditionService
|
|||||||
// properties in which the version histories will be stored
|
// properties in which the version histories will be stored
|
||||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||||
|
|
||||||
|
// 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
|
// add the version history of the translation as property of the Edition
|
||||||
properties.put(VersionModel.PROP_QNAME_QNAME, VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
|
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_IS_MULTI_VALUE, true);
|
||||||
properties.put(VersionModel.PROP_QNAME_MULTI_VALUE, (Serializable) translationVersionHistories);
|
properties.put(VersionModel.PROP_QNAME_MULTI_VALUE, (Serializable) translationVersionHistories);
|
||||||
|
|
||||||
@@ -309,6 +344,12 @@ public class EditionServiceImpl implements EditionService
|
|||||||
VersionModel.TYPE_QNAME_VERSIONED_PROPERTY,
|
VersionModel.TYPE_QNAME_VERSIONED_PROPERTY,
|
||||||
properties);
|
properties);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unexpected versionstore: " + versionService.getVersionStoreReference().getIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Util method to add the usefull properties to the existing properties of the given, mlContainer
|
* Util method to add the usefull properties to the existing properties of the given, mlContainer
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
package org.alfresco.repo.node.integrity;
|
package org.alfresco.repo.node.integrity;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -79,6 +80,7 @@ public class IncompleteNodeTagger
|
|||||||
private PolicyComponent policyComponent;
|
private PolicyComponent policyComponent;
|
||||||
private DictionaryService dictionaryService;
|
private DictionaryService dictionaryService;
|
||||||
private NodeService nodeService;
|
private NodeService nodeService;
|
||||||
|
private List<String> storesToIgnore = new ArrayList<String>(0);
|
||||||
|
|
||||||
public IncompleteNodeTagger()
|
public IncompleteNodeTagger()
|
||||||
{
|
{
|
||||||
@@ -108,6 +110,15 @@ public class IncompleteNodeTagger
|
|||||||
this.nodeService = nodeService;
|
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
|
* Registers the system-level policy behaviours
|
||||||
*/
|
*/
|
||||||
@@ -235,11 +246,14 @@ public class IncompleteNodeTagger
|
|||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||||
save(nodeRef);
|
save(nodeRef);
|
||||||
saveAssoc(nodeRef, null);
|
saveAssoc(nodeRef, null);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -248,9 +262,12 @@ public class IncompleteNodeTagger
|
|||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
Map<QName, Serializable> before,
|
Map<QName, Serializable> before,
|
||||||
Map<QName, Serializable> after)
|
Map<QName, Serializable> after)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
save(nodeRef);
|
save(nodeRef);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -260,6 +277,8 @@ public class IncompleteNodeTagger
|
|||||||
* not processed.
|
* not processed.
|
||||||
*/
|
*/
|
||||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||||
{
|
{
|
||||||
@@ -270,11 +289,14 @@ public class IncompleteNodeTagger
|
|||||||
}
|
}
|
||||||
save(nodeRef);
|
save(nodeRef);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recheck the node as an aspect was removed.
|
* Recheck the node as an aspect was removed.
|
||||||
*/
|
*/
|
||||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
if (aspectTypeQName.equals(ContentModel.ASPECT_INCOMPLETE))
|
||||||
{
|
{
|
||||||
@@ -285,6 +307,7 @@ public class IncompleteNodeTagger
|
|||||||
}
|
}
|
||||||
save(nodeRef);
|
save(nodeRef);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -293,36 +316,48 @@ public class IncompleteNodeTagger
|
|||||||
* node will handle it.
|
* node will handle it.
|
||||||
*/
|
*/
|
||||||
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNew)
|
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNew)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
if (!isNew)
|
if (!isNew)
|
||||||
{
|
{
|
||||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
saveAssoc(childAssocRef.getParentRef(), childAssocRef.getTypeQName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
saveAssoc(nodeAssocRef.getSourceRef(), nodeAssocRef.getTypeQName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process all the nodes that require checking within the transaction.
|
* Process all the nodes that require checking within the transaction.
|
||||||
|
@@ -107,6 +107,7 @@ public class IntegrityChecker
|
|||||||
private boolean failOnViolation;
|
private boolean failOnViolation;
|
||||||
private int maxErrorsPerTransaction;
|
private int maxErrorsPerTransaction;
|
||||||
private boolean traceOn;
|
private boolean traceOn;
|
||||||
|
private List<String> storesToIgnore = new ArrayList<String>(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downgrade violations to warnings within the current transaction. This is temporary and
|
* Downgrade violations to warnings within the current transaction. This is temporary and
|
||||||
@@ -207,6 +208,15 @@ public class IntegrityChecker
|
|||||||
this.maxErrorsPerTransaction = maxLogNumberPerTransaction;
|
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
|
* Registers the system-level policy behaviours
|
||||||
*/
|
*/
|
||||||
@@ -320,6 +330,8 @@ public class IntegrityChecker
|
|||||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||||
{
|
{
|
||||||
NodeRef childRef = childAssocRef.getChildRef();
|
NodeRef childRef = childAssocRef.getChildRef();
|
||||||
|
if (! storesToIgnore.contains(childRef.getStoreRef().toString()))
|
||||||
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check properties on child node
|
// check properties on child node
|
||||||
event = new PropertiesIntegrityEvent(
|
event = new PropertiesIntegrityEvent(
|
||||||
@@ -358,6 +370,7 @@ public class IntegrityChecker
|
|||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see PropertiesIntegrityEvent
|
* @see PropertiesIntegrityEvent
|
||||||
@@ -366,12 +379,15 @@ public class IntegrityChecker
|
|||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
Map<QName, Serializable> before,
|
Map<QName, Serializable> before,
|
||||||
Map<QName, Serializable> after)
|
Map<QName, Serializable> after)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check properties on node
|
// check properties on node
|
||||||
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
event = new PropertiesIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No checking performed: The association changes will be handled
|
* No checking performed: The association changes will be handled
|
||||||
@@ -385,6 +401,8 @@ public class IntegrityChecker
|
|||||||
* @see AssocTargetMultiplicityIntegrityEvent
|
* @see AssocTargetMultiplicityIntegrityEvent
|
||||||
*/
|
*/
|
||||||
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check properties on node
|
// check properties on node
|
||||||
@@ -413,17 +431,20 @@ public class IntegrityChecker
|
|||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AspectsIntegrityEvent
|
* @see AspectsIntegrityEvent
|
||||||
*/
|
*/
|
||||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeRef.getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check mandatory aspects
|
// check mandatory aspects
|
||||||
event = new AspectsIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
event = new AspectsIntegrityEvent(nodeService, dictionaryService, nodeRef);
|
||||||
save(event);
|
save(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -442,6 +463,8 @@ public class IntegrityChecker
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||||
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check source type
|
// check source type
|
||||||
event = new AssocSourceTypeIntegrityEvent(
|
event = new AssocSourceTypeIntegrityEvent(
|
||||||
@@ -482,12 +505,15 @@ public class IntegrityChecker
|
|||||||
childAssocRef.getQName());
|
childAssocRef.getQName());
|
||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AssocSourceMultiplicityIntegrityEvent
|
* @see AssocSourceMultiplicityIntegrityEvent
|
||||||
* @see AssocTargetMultiplicityIntegrityEvent
|
* @see AssocTargetMultiplicityIntegrityEvent
|
||||||
*/
|
*/
|
||||||
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(childAssocRef.getChildRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check source multiplicity
|
// check source multiplicity
|
||||||
@@ -507,6 +533,7 @@ public class IntegrityChecker
|
|||||||
true);
|
true);
|
||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AssocSourceTypeIntegrityEvent
|
* @see AssocSourceTypeIntegrityEvent
|
||||||
@@ -515,6 +542,8 @@ public class IntegrityChecker
|
|||||||
* @see AssocTargetMultiplicityIntegrityEvent
|
* @see AssocTargetMultiplicityIntegrityEvent
|
||||||
*/
|
*/
|
||||||
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
public void onCreateAssociation(AssociationRef nodeAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check source type
|
// check source type
|
||||||
@@ -548,12 +577,15 @@ public class IntegrityChecker
|
|||||||
false);
|
false);
|
||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AssocSourceMultiplicityIntegrityEvent
|
* @see AssocSourceMultiplicityIntegrityEvent
|
||||||
* @see AssocTargetMultiplicityIntegrityEvent
|
* @see AssocTargetMultiplicityIntegrityEvent
|
||||||
*/
|
*/
|
||||||
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
public void onDeleteAssociation(AssociationRef nodeAssocRef)
|
||||||
|
{
|
||||||
|
if (! storesToIgnore.contains(nodeAssocRef.getSourceRef().getStoreRef().toString()))
|
||||||
{
|
{
|
||||||
IntegrityEvent event = null;
|
IntegrityEvent event = null;
|
||||||
// check source multiplicity
|
// check source multiplicity
|
||||||
@@ -573,6 +605,7 @@ public class IntegrityChecker
|
|||||||
true);
|
true);
|
||||||
save(event);
|
save(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs several types of checks, querying specifically for events that
|
* Runs several types of checks, querying specifically for events that
|
||||||
|
@@ -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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -133,6 +133,11 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
this.dictionaryDAO = dictionaryDAO;
|
this.dictionaryDAO = dictionaryDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVersionService(VersionService versionService)
|
||||||
|
{
|
||||||
|
this.versionService = versionService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called during the transaction setup
|
* Called during the transaction setup
|
||||||
*/
|
*/
|
||||||
@@ -148,7 +153,6 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
|
|
||||||
// Get the services by name from the application context
|
// Get the services by name from the application context
|
||||||
this.dbNodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
this.dbNodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||||
this.versionService = (VersionService)applicationContext.getBean("versionService");
|
|
||||||
this.versionCounterDaoService = (VersionCounterService)applicationContext.getBean("versionCounterService");
|
this.versionCounterDaoService = (VersionCounterService)applicationContext.getBean("versionCounterService");
|
||||||
this.contentService = (ContentService)applicationContext.getBean("contentService");
|
this.contentService = (ContentService)applicationContext.getBean("contentService");
|
||||||
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
|
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
|
||||||
@@ -158,6 +162,8 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
this.nodeArchiveService = (NodeArchiveService) applicationContext.getBean("nodeArchiveService");
|
this.nodeArchiveService = (NodeArchiveService) applicationContext.getBean("nodeArchiveService");
|
||||||
this.nodeService = (NodeService)applicationContext.getBean("nodeService");
|
this.nodeService = (NodeService)applicationContext.getBean("nodeService");
|
||||||
|
|
||||||
|
setVersionService((VersionService)applicationContext.getBean("versionService"));
|
||||||
|
|
||||||
authenticationService.clearCurrentSecurityContext();
|
authenticationService.clearCurrentSecurityContext();
|
||||||
|
|
||||||
// Create the test model
|
// Create the test model
|
||||||
@@ -214,6 +220,16 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
* @return the node reference
|
* @return the node reference
|
||||||
*/
|
*/
|
||||||
protected NodeRef createNewVersionableNode()
|
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
|
// Use this map to retrive the versionable nodes in later tests
|
||||||
this.versionableNodes = new HashMap<String, NodeRef>();
|
this.versionableNodes = new HashMap<String, NodeRef>();
|
||||||
@@ -225,7 +241,10 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
QName.createQName("{test}MyVersionableNode"),
|
QName.createQName("{test}MyVersionableNode"),
|
||||||
TEST_TYPE_QNAME,
|
TEST_TYPE_QNAME,
|
||||||
this.nodeProperties).getChildRef();
|
this.nodeProperties).getChildRef();
|
||||||
|
if (versionable)
|
||||||
|
{
|
||||||
this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||||
|
}
|
||||||
|
|
||||||
assertNotNull(nodeRef);
|
assertNotNull(nodeRef);
|
||||||
this.versionableNodes.put(nodeRef.getId(), nodeRef);
|
this.versionableNodes.put(nodeRef.getId(), nodeRef);
|
||||||
@@ -241,7 +260,12 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
TEST_CHILD_ASSOC_1,
|
TEST_CHILD_ASSOC_1,
|
||||||
TEST_TYPE_QNAME,
|
TEST_TYPE_QNAME,
|
||||||
this.nodeProperties).getChildRef();
|
this.nodeProperties).getChildRef();
|
||||||
|
|
||||||
|
if (versionable)
|
||||||
|
{
|
||||||
this.dbNodeService.addAspect(child1, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
this.dbNodeService.addAspect(child1, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||||
|
}
|
||||||
|
|
||||||
assertNotNull(child1);
|
assertNotNull(child1);
|
||||||
this.versionableNodes.put(child1.getId(), child1);
|
this.versionableNodes.put(child1.getId(), child1);
|
||||||
NodeRef child2 = this.dbNodeService.createNode(
|
NodeRef child2 = this.dbNodeService.createNode(
|
||||||
@@ -250,7 +274,12 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
TEST_CHILD_ASSOC_2,
|
TEST_CHILD_ASSOC_2,
|
||||||
TEST_TYPE_QNAME,
|
TEST_TYPE_QNAME,
|
||||||
this.nodeProperties).getChildRef();
|
this.nodeProperties).getChildRef();
|
||||||
|
|
||||||
|
if (versionable)
|
||||||
|
{
|
||||||
this.dbNodeService.addAspect(child2, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
this.dbNodeService.addAspect(child2, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||||
|
}
|
||||||
|
|
||||||
assertNotNull(child2);
|
assertNotNull(child2);
|
||||||
this.versionableNodes.put(child2.getId(), child2);
|
this.versionableNodes.put(child2.getId(), child2);
|
||||||
|
|
||||||
@@ -304,6 +333,25 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
return newVersion;
|
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
|
* Gets the next version label
|
||||||
*/
|
*/
|
||||||
@@ -322,15 +370,17 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
* @param newVersion the new version
|
* @param newVersion the new version
|
||||||
* @param versionableNode the versioned node
|
* @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);
|
assertNotNull(newVersion);
|
||||||
|
|
||||||
// Check the version label and version number
|
// Check the version label and version number
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"The expected version number was not used.",
|
"The expected version number was not used.",
|
||||||
Integer.toString(expectedVersionNumber),
|
Integer.toString(expectedVersionNumber),
|
||||||
newVersion.getVersionProperty(VersionModel.PROP_VERSION_NUMBER).toString());
|
newVersion.getVersionProperty(VersionBaseModel.PROP_VERSION_NUMBER).toString());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"The expected version label was not used.",
|
"The expected version label was not used.",
|
||||||
expectedVersionLabel,
|
expectedVersionLabel,
|
||||||
@@ -347,9 +397,11 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
// Check the creator
|
// Check the creator
|
||||||
assertEquals(USER_NAME, newVersion.getCreator());
|
assertEquals(USER_NAME, newVersion.getCreator());
|
||||||
|
|
||||||
// Check the properties of the verison
|
// Check the metadata properties of the version
|
||||||
Map<String, Serializable> props = newVersion.getVersionProperties();
|
Map<String, Serializable> props = newVersion.getVersionProperties();
|
||||||
assertNotNull("The version properties collection should not be null.", props);
|
assertNotNull("The version properties collection should not be null.", props);
|
||||||
|
if (versionProperties != null)
|
||||||
|
{
|
||||||
// TODO sort this out - need to check for the reserved properties too
|
// TODO sort this out - need to check for the reserved properties too
|
||||||
//assertEquals(versionProperties.size(), props.size());
|
//assertEquals(versionProperties.size(), props.size());
|
||||||
for (String key : versionProperties.keySet())
|
for (String key : versionProperties.keySet())
|
||||||
@@ -358,10 +410,27 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
versionProperties.get(key),
|
versionProperties.get(key),
|
||||||
newVersion.getVersionProperty(key));
|
newVersion.getVersionProperty(key));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the node reference is correct
|
// Check that the node reference is correct
|
||||||
NodeRef nodeRef = newVersion.getFrozenStateNodeRef();
|
NodeRef nodeRef = newVersion.getFrozenStateNodeRef();
|
||||||
assertNotNull(nodeRef);
|
assertNotNull(nodeRef);
|
||||||
|
|
||||||
|
// 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(
|
assertEquals(
|
||||||
VersionModel.STORE_ID,
|
VersionModel.STORE_ID,
|
||||||
nodeRef.getStoreRef().getIdentifier());
|
nodeRef.getStoreRef().getIdentifier());
|
||||||
@@ -369,6 +438,12 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
VersionModel.STORE_PROTOCOL,
|
VersionModel.STORE_PROTOCOL,
|
||||||
nodeRef.getStoreRef().getProtocol());
|
nodeRef.getStoreRef().getProtocol());
|
||||||
assertNotNull(nodeRef.getId());
|
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 ??
|
// TODO: How do we check the frozen attributes ??
|
||||||
|
|
||||||
@@ -379,6 +454,43 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
|
|||||||
assertEquals(newVersion.getVersionLabel(), currentVersionLabel);
|
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.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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.model.ContentModel;
|
||||||
import org.alfresco.repo.version.common.VersionUtil;
|
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.DictionaryService;
|
||||||
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
|
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
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.QName;
|
||||||
import org.alfresco.service.namespace.QNamePattern;
|
import org.alfresco.service.namespace.QNamePattern;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
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
|
public class NodeServiceImpl implements NodeService, VersionModel
|
||||||
{
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(NodeServiceImpl.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error messages
|
* 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.";
|
"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)
|
if (isMultiValue.booleanValue() == false)
|
||||||
{
|
{
|
||||||
value = this.dbNodeService.getProperty(versionedAttribute, PROP_QNAME_VALUE);
|
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
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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
|
// Get the properties of the versioned state
|
||||||
Map<QName, Serializable> versionedProperties = this.lightWeightVersionStoreNodeService.getProperties(version.getFrozenStateNodeRef());
|
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())
|
for (QName key : origProps.keySet())
|
||||||
{
|
{
|
||||||
assertTrue(versionedProperties.containsKey(key));
|
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
|
// TODO do futher versioning and check by changing values
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,46 +175,47 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
|||||||
*/
|
*/
|
||||||
public void testGetChildAssocs()
|
public void testGetChildAssocs()
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isTraceEnabled())
|
||||||
{
|
{
|
||||||
// Let's have a look at the version store ..
|
// Let's have a look at the version store ..
|
||||||
System.out.println(NodeStoreInspector.dumpNodeStore(
|
logger.trace(NodeStoreInspector.dumpNodeStore(
|
||||||
this.dbNodeService,
|
this.dbNodeService,
|
||||||
this.versionService.getVersionStoreReference()) + "\n\n");
|
this.versionService.getVersionStoreReference()) + "\n\n");
|
||||||
logger.debug("");
|
logger.trace("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new versionable node
|
// Create a new versionable node
|
||||||
NodeRef versionableNode = createNewVersionableNode();
|
NodeRef versionableNode = createNewVersionableNode();
|
||||||
Collection<ChildAssociationRef> origionalChildren = this.dbNodeService.getChildAssocs(versionableNode);
|
Collection<ChildAssociationRef> originalChildren = this.dbNodeService.getChildAssocs(versionableNode);
|
||||||
assertNotNull(origionalChildren);
|
assertNotNull(originalChildren);
|
||||||
|
|
||||||
// Store the origional children in a map for easy navigation later
|
// Store the original children in a map for easy navigation later
|
||||||
HashMap<String, ChildAssociationRef> origionalChildAssocRefs = new HashMap<String, ChildAssociationRef>();
|
HashMap<String, ChildAssociationRef> originalChildAssocRefs = new HashMap<String, ChildAssociationRef>();
|
||||||
for (ChildAssociationRef ref : origionalChildren)
|
for (ChildAssociationRef ref : originalChildren)
|
||||||
{
|
{
|
||||||
origionalChildAssocRefs.put(ref.getChildRef().getId(), ref);
|
originalChildAssocRefs.put(ref.getChildRef().getId(), ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new version
|
// Create a new version
|
||||||
Version version = createVersion(versionableNode, this.versionProperties);
|
Version version = createVersion(versionableNode, this.versionProperties);
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isTraceEnabled())
|
||||||
{
|
{
|
||||||
// Let's have a look at the version store ..
|
// Let's have a look at the version store ..
|
||||||
System.out.println(NodeStoreInspector.dumpNodeStore(
|
logger.trace(NodeStoreInspector.dumpNodeStore(
|
||||||
this.dbNodeService,
|
this.dbNodeService,
|
||||||
this.versionService.getVersionStoreReference()));
|
this.versionService.getVersionStoreReference()));
|
||||||
|
logger.trace("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the children of the versioned node
|
// Get the children of the versioned node
|
||||||
Collection<ChildAssociationRef> versionedChildren = this.lightWeightVersionStoreNodeService.getChildAssocs(version.getFrozenStateNodeRef());
|
Collection<ChildAssociationRef> versionedChildren = this.lightWeightVersionStoreNodeService.getChildAssocs(version.getFrozenStateNodeRef());
|
||||||
assertNotNull(versionedChildren);
|
assertNotNull(versionedChildren);
|
||||||
assertEquals(origionalChildren.size(), versionedChildren.size());
|
assertEquals(originalChildren.size(), versionedChildren.size());
|
||||||
|
|
||||||
for (ChildAssociationRef versionedChildRef : versionedChildren)
|
for (ChildAssociationRef versionedChildRef : versionedChildren)
|
||||||
{
|
{
|
||||||
ChildAssociationRef origChildAssocRef = origionalChildAssocRefs.get(versionedChildRef.getChildRef().getId());
|
ChildAssociationRef origChildAssocRef = originalChildAssocRefs.get(versionedChildRef.getChildRef().getId());
|
||||||
assertNotNull(origChildAssocRef);
|
assertNotNull(origChildAssocRef);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@@ -219,9 +232,34 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getAssociationTargets
|
* Test getAssociationTargets
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public void testGetAssociationTargets()
|
public void testGetAssociationTargets()
|
||||||
{
|
{
|
||||||
|
// 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)
|
||||||
|
|
||||||
// Create a new versionable node
|
// Create a new versionable node
|
||||||
NodeRef versionableNode = createNewVersionableNode();
|
NodeRef versionableNode = createNewVersionableNode();
|
||||||
|
|
||||||
@@ -239,6 +277,7 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
|||||||
assertNotNull(assocs);
|
assertNotNull(assocs);
|
||||||
assertEquals(origAssocs.size(), assocs.size());
|
assertEquals(origAssocs.size(), assocs.size());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test hasAspect
|
* Test hasAspect
|
||||||
@@ -277,7 +316,10 @@ public class NodeServiceImplTest extends BaseVersionStoreTest
|
|||||||
Set<QName> aspects = this.lightWeightVersionStoreNodeService.getAspects(version.getFrozenStateNodeRef());
|
Set<QName> aspects = this.lightWeightVersionStoreNodeService.getAspects(version.getFrozenStateNodeRef());
|
||||||
assertEquals(origAspects.size(), aspects.size());
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,60 +24,38 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.version;
|
package org.alfresco.repo.version;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.service.cmr.version.VersionService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interface conating the constants used by the light weight
|
* Version1 Model Constants used by lightWeightVersionStore implementation
|
||||||
* version store implementation
|
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
*/
|
*/
|
||||||
public interface VersionModel
|
public interface VersionModel extends VersionBaseModel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Namespace
|
* Namespace
|
||||||
*/
|
*/
|
||||||
public static final String NAMESPACE_URI = "http://www.alfresco.org/model/versionstore/1.0";
|
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
|
* The store id
|
||||||
*/
|
*/
|
||||||
public static final String STORE_ID = "lightWeightVersionStore";
|
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 */
|
/** 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
|
* 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);
|
public static final QName TYPE_QNAME_VERSION_HISTORY = QName.createQName(NAMESPACE_URI, TYPE_VERSION_HISTORY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version history properties and associations
|
* 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 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
|
* Verison type
|
||||||
@@ -88,6 +66,12 @@ public interface VersionModel
|
|||||||
/**
|
/**
|
||||||
* Version type properties and associations
|
* 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_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_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);
|
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
|
* 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_ATTRIBUTES = "versionedAttributes";
|
||||||
public static final String CHILD_VERSIONED_CHILD_ASSOCS = "versionedChildAssocs";
|
public static final String CHILD_VERSIONED_CHILD_ASSOCS = "versionedChildAssocs";
|
||||||
public static final String CHILD_VERSIONED_ASSOCS = "versionedAssocs";
|
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
|
* 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_VERSIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERSIONS);
|
||||||
public static final QName PROP_QNAME_TRANSLATION_VERIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERIONS);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -34,6 +34,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
import org.alfresco.repo.policy.JavaBehaviour;
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
import org.alfresco.repo.policy.PolicyScope;
|
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.VersionUtil;
|
||||||
import org.alfresco.repo.version.common.counter.VersionCounterService;
|
import org.alfresco.repo.version.common.counter.VersionCounterService;
|
||||||
import org.alfresco.repo.version.common.versionlabel.SerialVersionLabelPolicy;
|
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.AspectMissingException;
|
||||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
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.QName;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.util.ParameterCheck;
|
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
|
* @author Roy Wetheral
|
||||||
*/
|
*/
|
||||||
public class VersionServiceImpl extends AbstractVersionServiceImpl
|
public class VersionServiceImpl extends AbstractVersionServiceImpl implements VersionService, VersionModel
|
||||||
implements VersionService, VersionModel
|
|
||||||
{
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(VersionServiceImpl.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error message I18N id's
|
* Error message I18N id's
|
||||||
*/
|
*/
|
||||||
private static final String MSGID_ERR_NOT_FOUND = "version_service.err_not_found";
|
protected static final String MSGID_ERR_NOT_FOUND = "version_service.err_not_found";
|
||||||
private static final String MSGID_ERR_NO_BRANCHES = "version_service.err_unsupported";
|
protected static final String MSGID_ERR_NO_BRANCHES = "version_service.err_unsupported";
|
||||||
private static final String MSGID_ERR_RESTORE_EXISTS = "version_service.err_restore_exists";
|
protected 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";
|
protected 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";
|
protected 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_REVERT_MISMATCH = "version_service.err_revert_mismatch";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version counter service
|
* The version counter service
|
||||||
*/
|
*/
|
||||||
private VersionCounterService versionCounterService;
|
protected VersionCounterService versionCounterService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The db node service, used as the version store implementation
|
* The db node service, used as the version store implementation
|
||||||
@@ -91,13 +98,12 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
/**
|
/**
|
||||||
* Policy behaviour filter
|
* Policy behaviour filter
|
||||||
*/
|
*/
|
||||||
private BehaviourFilter policyBehaviourFilter;
|
protected BehaviourFilter policyBehaviourFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The repository searcher
|
* The repository searcher
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
protected SearchService searcher; // unused
|
||||||
private SearchService searcher;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the db node service, used as the version store implementation
|
* 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"));
|
new JavaBehaviour(new SerialVersionLabelPolicy(), "calculateVersionLabel"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO - temp
|
||||||
|
protected void initialiseWithoutBind()
|
||||||
|
{
|
||||||
|
super.initialise();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the reference to the version store
|
* Gets the reference to the version store
|
||||||
*
|
*
|
||||||
* @return reference to the version store
|
* @return reference to the version store
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public StoreRef getVersionStoreReference()
|
public StoreRef getVersionStoreReference()
|
||||||
{
|
{
|
||||||
return new StoreRef(
|
return new StoreRef(
|
||||||
@@ -176,11 +189,20 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
Map<String, Serializable> versionProperties)
|
Map<String, Serializable> versionProperties)
|
||||||
throws ReservedVersionNameException, AspectMissingException
|
throws ReservedVersionNameException, AspectMissingException
|
||||||
{
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Get the next version number
|
// Get the next version number
|
||||||
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
||||||
|
|
||||||
// Create the version
|
// 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)
|
boolean versionChildren)
|
||||||
throws ReservedVersionNameException, AspectMissingException
|
throws ReservedVersionNameException, AspectMissingException
|
||||||
{
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Get the next version number
|
// Get the next version number
|
||||||
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
int versionNumber = this.versionCounterService.nextVersionNumber(getVersionStoreReference());
|
||||||
|
|
||||||
// Create the versions
|
// 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)
|
Map<String, Serializable> versionProperties)
|
||||||
throws ReservedVersionNameException, AspectMissingException
|
throws ReservedVersionNameException, AspectMissingException
|
||||||
{
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
Collection<Version> result = new ArrayList<Version>(nodeRefs.size());
|
Collection<Version> result = new ArrayList<Version>(nodeRefs.size());
|
||||||
|
|
||||||
// Get the next version number
|
// Get the next version number
|
||||||
@@ -268,6 +303,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
result.add(createVersion(nodeRef, versionProperties, versionNumber));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,12 +322,13 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
* @throws ReservedVersionNameException
|
* @throws ReservedVersionNameException
|
||||||
* thrown if there is a name clash in the version properties
|
* thrown if there is a name clash in the version properties
|
||||||
*/
|
*/
|
||||||
private Version createVersion(
|
protected Version createVersion(
|
||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
Map<String, Serializable> origVersionProperties,
|
Map<String, Serializable> origVersionProperties,
|
||||||
int versionNumber)
|
int versionNumber)
|
||||||
throws ReservedVersionNameException
|
throws ReservedVersionNameException
|
||||||
{
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Copy the version properties (to prevent unexpected side effects to the caller)
|
// Copy the version properties (to prevent unexpected side effects to the caller)
|
||||||
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
|
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
|
||||||
@@ -370,7 +411,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the version data object
|
// Create the version data object
|
||||||
Version version = getVersion(newVersionRef);
|
Version version = this.getVersion(newVersionRef);
|
||||||
|
|
||||||
// Set the new version label on the versioned node
|
// Set the new version label on the versioned node
|
||||||
this.nodeService.setProperty(
|
this.nodeService.setProperty(
|
||||||
@@ -386,6 +427,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
// Invoke the policy behaviour
|
// Invoke the policy behaviour
|
||||||
invokeAfterCreateVersion(nodeRef, version);
|
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 the data object representing the newly created version
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
@@ -465,30 +511,30 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
Map<QName, Serializable> result = new HashMap<QName, Serializable>(10);
|
Map<QName, Serializable> result = new HashMap<QName, Serializable>(10);
|
||||||
|
|
||||||
// Set the version number for the new version
|
// 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
|
// 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
|
// 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
|
// 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
|
// Store the current node type
|
||||||
QName nodeType = this.nodeService.getType(nodeRef);
|
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
|
// Store the current aspects
|
||||||
Set<QName> aspects = this.nodeService.getAspects(nodeRef);
|
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
|
// Calculate the version label
|
||||||
QName classRef = this.nodeService.getType(nodeRef);
|
QName classRef = this.nodeService.getType(nodeRef);
|
||||||
Version preceedingVersion = getVersion(preceedingNodeRef);
|
Version preceedingVersion = getVersion(preceedingNodeRef);
|
||||||
String versionLabel = invokeCalculateVersionLabel(classRef, preceedingVersion, versionNumber, versionProperties);
|
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;
|
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
|
* Freeze the aspects
|
||||||
*
|
*
|
||||||
@@ -675,7 +742,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
*
|
*
|
||||||
* @return the node ref to the root node of the version store
|
* @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
|
// Get the version store root node reference
|
||||||
return this.dbNodeService.getRootNode(getVersionStoreReference());
|
return this.dbNodeService.getRootNode(getVersionStoreReference());
|
||||||
@@ -691,12 +758,21 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
* @param nodeRef the node reference
|
* @param nodeRef the node reference
|
||||||
* @return a constructed version history object
|
* @return a constructed version history object
|
||||||
*/
|
*/
|
||||||
private VersionHistory buildVersionHistory(NodeRef versionHistoryRef, NodeRef nodeRef)
|
protected VersionHistory buildVersionHistory(NodeRef versionHistoryRef, NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
VersionHistory versionHistory = null;
|
VersionHistory versionHistory = null;
|
||||||
|
|
||||||
ArrayList<NodeRef> versionHistoryNodeRefs = new ArrayList<NodeRef>();
|
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)
|
while (currentVersion != null)
|
||||||
{
|
{
|
||||||
@@ -751,7 +827,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
* @param versionRef the version reference
|
* @param versionRef the version reference
|
||||||
* @return object containing verison data
|
* @return object containing verison data
|
||||||
*/
|
*/
|
||||||
private Version getVersion(NodeRef versionRef)
|
protected Version getVersion(NodeRef versionRef)
|
||||||
{
|
{
|
||||||
if (versionRef == null)
|
if (versionRef == null)
|
||||||
{
|
{
|
||||||
@@ -768,17 +844,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the meta data
|
// Get the meta data
|
||||||
List<ChildAssociationRef> metaData = this.dbNodeService.getChildAssocs(
|
Map<String, Serializable> versionMetaDataProperties = getVersionMetaData(versionRef);
|
||||||
versionRef,
|
versionProperties.putAll(versionMetaDataProperties);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and return the version object
|
// Create and return the version object
|
||||||
NodeRef newNodeRef = new NodeRef(new StoreRef(STORE_PROTOCOL, STORE_ID), versionRef.getId());
|
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
|
* @param nodeRef a node reference
|
||||||
* @return a reference to the version history node, null of none
|
* @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());
|
return this.dbNodeService.getChildByName(getRootNode(), CHILD_QNAME_VERSION_HISTORIES, nodeRef.getId());
|
||||||
}
|
}
|
||||||
@@ -1086,6 +1153,39 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
|
|||||||
return version;
|
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)
|
* @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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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_1 = "updatedContent1";
|
||||||
private static final String UPDATED_CONTENT_2 = "updatedContent2";
|
private static final String UPDATED_CONTENT_2 = "updatedContent2";
|
||||||
|
|
||||||
|
public void testSetup()
|
||||||
|
{
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the creation of the initial version of a versionable node
|
* Tests the creation of the initial version of a versionable node
|
||||||
*/
|
*/
|
||||||
@@ -90,9 +95,39 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
createVersion(versionableNode);
|
createVersion(versionableNode);
|
||||||
// TODO mess with some of the properties and stuff as you version
|
// TODO mess with some of the properties and stuff as you version
|
||||||
createVersion(versionableNode);
|
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
|
// TODO test versioning numberious times with branchs implies by different workspaces
|
||||||
|
|
||||||
@@ -155,15 +190,28 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
for (Version version : versions)
|
for (Version version : versions)
|
||||||
{
|
{
|
||||||
// Get the frozen id from the version
|
// 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);
|
assertNotNull("Unable to retrieve the frozen node id from the created version.", frozenNodeId);
|
||||||
|
|
||||||
// Get the origional node ref (based on the forzen node)
|
// Get the origional node ref (based on the forzen node)
|
||||||
NodeRef origionaNodeRef = this.versionableNodes.get(frozenNodeId);
|
NodeRef originalNodeRef = this.versionableNodes.get(frozenNodeId);
|
||||||
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", origionaNodeRef);
|
assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", originalNodeRef);
|
||||||
|
|
||||||
// Check the new version
|
// 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
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Check that the initial version has not been created
|
// Check that the initial version has not been created
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
// Add some content
|
// 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);
|
assertNotNull(contentWriter);
|
||||||
contentWriter.putContent(UPDATED_CONTENT_1);
|
contentWriter.putContent(UPDATED_CONTENT_1);
|
||||||
|
|
||||||
@@ -494,7 +542,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
{
|
{
|
||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(2, versionHistory.getAllVersions().size());
|
assertEquals(2, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
@@ -520,7 +568,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Add some content
|
// 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);
|
assertNotNull(contentWriter);
|
||||||
contentWriter.putContent(UPDATED_CONTENT_1);
|
contentWriter.putContent(UPDATED_CONTENT_1);
|
||||||
|
|
||||||
@@ -533,7 +581,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
{
|
{
|
||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(versionableNode);
|
VersionHistory versionHistory = versionService.getVersionHistory(versionableNode);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
@@ -567,7 +615,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
{
|
{
|
||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||||
assertNull(versionHistory);
|
assertNull(versionHistory);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -596,12 +644,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Check that the version history has been created
|
// Check that the version history has been created
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
// Remove the versionable aspect
|
// Remove the versionable aspect
|
||||||
VersionServiceImplTest.this.dbNodeService.removeAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
dbNodeService.removeAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -612,11 +660,11 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Check that the version history has been removed
|
// Check that the version history has been removed
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||||
assertNull(versionHistory);
|
assertNull(versionHistory);
|
||||||
|
|
||||||
// Re-add the versionable aspect
|
// Re-add the versionable aspect
|
||||||
VersionServiceImplTest.this.dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
dbNodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -627,7 +675,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Check that the version history has been created
|
// Check that the version history has been created
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
@@ -658,12 +706,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
{
|
{
|
||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
VersionHistory versionHistory = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
|
||||||
assertNotNull(versionHistory);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
// Delete the node
|
// Delete the node
|
||||||
VersionServiceImplTest.this.dbNodeService.deleteNode(nodeRef);
|
dbNodeService.deleteNode(nodeRef);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -674,15 +722,15 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Get the archived noderef
|
// 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
|
// 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);
|
assertNotNull(versionHistory);
|
||||||
assertEquals(1, versionHistory.getAllVersions().size());
|
assertEquals(1, versionHistory.getAllVersions().size());
|
||||||
|
|
||||||
// Delete the node for good
|
// Delete the node for good
|
||||||
VersionServiceImplTest.this.dbNodeService.deleteNode(archivedNodeRef);
|
dbNodeService.deleteNode(archivedNodeRef);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -693,12 +741,12 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
public Object execute() throws Exception
|
public Object execute() throws Exception
|
||||||
{
|
{
|
||||||
// Get the archived noderef
|
// Get the archived noderef
|
||||||
NodeRef archivedNodeRef = VersionServiceImplTest.this.nodeArchiveService.getArchivedNode(nodeRef);
|
NodeRef archivedNodeRef = nodeArchiveService.getArchivedNode(nodeRef);
|
||||||
|
|
||||||
// Check that the version histories have been deleted
|
// Check that the version histories have been deleted
|
||||||
VersionHistory versionHistory12 = VersionServiceImplTest.this.versionService.getVersionHistory(nodeRef);
|
VersionHistory versionHistory12 = versionService.getVersionHistory(nodeRef);
|
||||||
assertNull(versionHistory12);
|
assertNull(versionHistory12);
|
||||||
VersionHistory versionHistory23 = VersionServiceImplTest.this.versionService.getVersionHistory(archivedNodeRef);
|
VersionHistory versionHistory23 = versionService.getVersionHistory(archivedNodeRef);
|
||||||
assertNull(versionHistory23);
|
assertNull(versionHistory23);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -761,8 +809,15 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
final AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
final AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||||
|
|
||||||
authenticationComponent.setSystemUserAsCurrentUser();
|
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
|
// Create a new store
|
||||||
StoreRef storeRef = new StoreRef("test", "VersionServiceImplTest.main");
|
StoreRef storeRef = new StoreRef("test", "VersionServiceImplTest-main-"+System.currentTimeMillis());
|
||||||
if (!nodeService.exists(storeRef))
|
if (!nodeService.exists(storeRef))
|
||||||
{
|
{
|
||||||
nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||||
@@ -819,5 +874,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
lastReport = now;
|
lastReport = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("Finished: " + fileCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,7 @@ public class VersionTestSuite extends TestSuite
|
|||||||
suite.addTestSuite(VersionServiceImplTest.class);
|
suite.addTestSuite(VersionServiceImplTest.class);
|
||||||
suite.addTestSuite(NodeServiceImplTest.class);
|
suite.addTestSuite(NodeServiceImplTest.class);
|
||||||
suite.addTestSuite(ContentServiceImplTest.class);
|
suite.addTestSuite(ContentServiceImplTest.class);
|
||||||
|
suite.addTestSuite(VersionMigratorTest.class);
|
||||||
return suite;
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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
|
// Queue create version action
|
||||||
Map<String, Serializable> versionDetails = new HashMap<String, Serializable>(1);
|
Map<String, Serializable> versionDetails = new HashMap<String, Serializable>(1);
|
||||||
versionDetails.put(Version.PROP_DESCRIPTION, I18NUtil.getMessage(MSG_INITIAL_VERSION));
|
versionDetails.put(Version.PROP_DESCRIPTION, I18NUtil.getMessage(MSG_INITIAL_VERSION));
|
||||||
|
|
||||||
this.versionService.createVersion(nodeRef, versionDetails);
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
|
||||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||||
import org.alfresco.repo.policy.PolicyComponent;
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
import org.alfresco.repo.policy.PolicyScope;
|
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.BeforeCreateVersionPolicy;
|
||||||
import org.alfresco.repo.version.VersionServicePolicies.CalculateVersionLabelPolicy;
|
import org.alfresco.repo.version.VersionServicePolicies.CalculateVersionLabelPolicy;
|
||||||
import org.alfresco.repo.version.VersionServicePolicies.OnCreateVersionPolicy;
|
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.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.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
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.Version;
|
||||||
import org.alfresco.service.cmr.version.VersionServiceException;
|
import org.alfresco.service.cmr.version.VersionServiceException;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract version service implementation.
|
* Abstract version service implementation.
|
||||||
@@ -223,58 +216,11 @@ public abstract class AbstractVersionServiceImpl
|
|||||||
* @param versionProperties
|
* @param versionProperties
|
||||||
* @param nodeDetails
|
* @param nodeDetails
|
||||||
*/
|
*/
|
||||||
protected void defaultOnCreateVersion(
|
abstract protected void defaultOnCreateVersion(
|
||||||
QName classRef,
|
QName classRef,
|
||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
Map<String, Serializable> versionProperties,
|
Map<String, Serializable> versionProperties,
|
||||||
PolicyScope nodeDetails)
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the calculate version label policy behaviour
|
* Invoke the calculate version label policy behaviour
|
||||||
@@ -314,4 +260,5 @@ public abstract class AbstractVersionServiceImpl
|
|||||||
return versionLabel;
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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);
|
assertNotNull(versions2);
|
||||||
assertTrue(versions2.isEmpty());
|
assertTrue(versions2.isEmpty());
|
||||||
|
|
||||||
Collection versions3 = vh.getSuccessors(this.childVersion2);
|
Collection<Version> versions3 = vh.getSuccessors(this.childVersion2);
|
||||||
assertNotNull(versions3);
|
assertNotNull(versions3);
|
||||||
assertTrue(versions3.isEmpty());
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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.Date;
|
||||||
import java.util.Map;
|
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.repo.version.VersionModel;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
@@ -45,6 +47,7 @@ import org.alfresco.service.cmr.version.VersionType;
|
|||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class VersionImpl implements Version
|
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.
|
* 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()
|
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()
|
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()
|
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()
|
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()
|
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()
|
public NodeRef getVersionedNodeRef()
|
||||||
{
|
{
|
||||||
|
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 storeProtocol = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
|
||||||
String storeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
|
String storeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
|
||||||
String nodeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
|
String nodeId = (String)this.versionProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
|
||||||
return new NodeRef(new StoreRef(storeProtocol, storeId), nodeId);
|
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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -24,12 +24,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.version.common;
|
package org.alfresco.repo.version.common;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
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.repo.version.VersionModel;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.cmr.version.ReservedVersionNameException;
|
import org.alfresco.service.cmr.version.ReservedVersionNameException;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class containing helper methods for the versioning services.
|
* Helper class containing helper methods for the versioning services.
|
||||||
@@ -42,14 +52,21 @@ public class VersionUtil
|
|||||||
* Reserved property names
|
* Reserved property names
|
||||||
*/
|
*/
|
||||||
public static final String[] RESERVED_PROPERTY_NAMES = new String[]{
|
public static final String[] RESERVED_PROPERTY_NAMES = new String[]{
|
||||||
VersionModel.PROP_CREATED_DATE,
|
VersionModel.PROP_FROZEN_NODE_ID, // deprecated
|
||||||
VersionModel.PROP_FROZEN_NODE_ID,
|
VersionModel.PROP_FROZEN_NODE_STORE_ID, // deprecated
|
||||||
VersionModel.PROP_FROZEN_NODE_STORE_ID,
|
VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL, // deprecated
|
||||||
VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL,
|
VersionModel.PROP_FROZEN_NODE_TYPE, // deprecated
|
||||||
VersionModel.PROP_FROZEN_NODE_TYPE,
|
VersionModel.PROP_FROZEN_ASPECTS, // deprecated
|
||||||
VersionModel.PROP_FROZEN_ASPECTS,
|
VersionBaseModel.PROP_CREATED_DATE,
|
||||||
VersionModel.PROP_VERSION_LABEL,
|
VersionBaseModel.PROP_VERSION_LABEL,
|
||||||
VersionModel.PROP_VERSION_NUMBER};
|
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
|
* 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());
|
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());
|
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)
|
if (VersionType.MAJOR.equals(versionType) == true)
|
||||||
{
|
{
|
||||||
serialVersionNumber.majorIncrement();
|
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">
|
<model name="ver:versionmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||||
|
|
||||||
|
<!-- deprecated -->
|
||||||
|
|
||||||
<description>Alfresco Version Store Model</description>
|
<description>Alfresco Version Store Model</description>
|
||||||
<author>Alfresco</author>
|
<author>Alfresco</author>
|
||||||
<published>2005-05-30</published>
|
<published>2005-05-30</published>
|
||||||
|
@@ -28,6 +28,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.repo.version.VersionBaseModel;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ public interface Version extends Serializable
|
|||||||
/**
|
/**
|
||||||
* Names of the system version properties
|
* 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.
|
* 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
|
* Note that this reference will be to the current state of the versioned
|
||||||
* node which may now correspond to a later version.
|
* 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();
|
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
|
* Gets the reference to the node that contains the frozen state of the
|
||||||
* version.
|
* version.
|
||||||
*
|
*
|
||||||
* @return a node reference
|
* @return a node reference (to the version node in the 'version' store)
|
||||||
*/
|
*/
|
||||||
public NodeRef getFrozenStateNodeRef();
|
public NodeRef getFrozenStateNodeRef();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user