mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Phase one of merge of EC multilingual work
These files are their changes plus adjustments for formatting and immediate clashes I anticipate that this will break the build, but there are too many changes coming to risk it. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5740 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -78,6 +78,12 @@
|
|||||||
<!-- There are no audtiable methods in the mime type service -->
|
<!-- There are no audtiable methods in the mime type service -->
|
||||||
<Service name="MimetypeService" mode="none" enabled="false"/>
|
<Service name="MimetypeService" mode="none" enabled="false"/>
|
||||||
|
|
||||||
|
<!-- The ContentFilterLanguagesService -->
|
||||||
|
<Service name="ContentFilterLanguagesService" mode="none" >
|
||||||
|
<Method name="getFilterLanguages" mode="all"/>
|
||||||
|
<Method name="getMissingLanguages" mode="all"/>
|
||||||
|
<Method name="getDefaultLanguage" mode="all"/>
|
||||||
|
</Service>
|
||||||
<Service name="NodeService" mode="none">
|
<Service name="NodeService" mode="none">
|
||||||
<Method name="createStore" mode="all"/>
|
<Method name="createStore" mode="all"/>
|
||||||
<Method name="createNode" mode="all"/>
|
<Method name="createNode" mode="all"/>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<view:acl view:inherit="false">
|
<view:acl view:inherit="false">
|
||||||
<view:ace view:access="ALLOWED">
|
<view:ace view:access="ALLOWED">
|
||||||
<view:authority>GROUP_EVERYONE</view:authority>
|
<view:authority>GROUP_EVERYONE</view:authority>
|
||||||
<view:permission>Consumer</view:permission>
|
<view:permission>Coordinator</view:permission>
|
||||||
</view:ace>
|
</view:ace>
|
||||||
</view:acl>
|
</view:acl>
|
||||||
</cm:mlRoot>
|
</cm:mlRoot>
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
<ref bean="nodeDaoService" />
|
<ref bean="nodeDaoService" />
|
||||||
</property>
|
</property>
|
||||||
<property name="avmNodeDAO">
|
<property name="avmNodeDAO">
|
||||||
<ref bean="avmNodeDAO"/>
|
<ref bean="avmNodeDAO"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="transactionService" >
|
<property name="transactionService" >
|
||||||
<ref bean="transactionComponent" />
|
<ref bean="transactionComponent" />
|
||||||
@@ -99,6 +99,24 @@
|
|||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="contentFilterLanguagesConfigService" class="org.alfresco.config.xml.XMLConfigService" init-method="init">
|
||||||
|
<constructor-arg>
|
||||||
|
<bean class="org.alfresco.config.source.UrlConfigSource">
|
||||||
|
<constructor-arg>
|
||||||
|
<list>
|
||||||
|
<value>classpath:alfresco/ml/content-filter-lang.xml</value>
|
||||||
|
</list>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<bean id="contentFilterLanguagesService" class="org.alfresco.repo.model.ml.ContentFilterLanguagesMap" init-method="init" >
|
||||||
|
<constructor-arg>
|
||||||
|
<ref bean="contentFilterLanguagesConfigService" />
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
<bean id="openOfficeConnection" class="net.sf.jooreports.openoffice.connection.SocketOpenOfficeConnection" />
|
<bean id="openOfficeConnection" class="net.sf.jooreports.openoffice.connection.SocketOpenOfficeConnection" />
|
||||||
<bean id="openOfficeConnectionTester" class="org.alfresco.util.OpenOfficeConnectionTester" init-method="checkConnection" >
|
<bean id="openOfficeConnectionTester" class="org.alfresco.util.OpenOfficeConnectionTester" init-method="checkConnection" >
|
||||||
<property name="connection">
|
<property name="connection">
|
||||||
|
@@ -114,10 +114,10 @@
|
|||||||
value="${alfresco.jmx.dir}/alfresco-jmxrmi.access"/>
|
value="${alfresco.jmx.dir}/alfresco-jmxrmi.access"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="FileServerConfig"
|
<bean id="FileServerConfig"
|
||||||
class="org.alfresco.filesys.server.config.FileServerConfig">
|
class="org.alfresco.filesys.server.config.FileServerConfig">
|
||||||
<property name="fileServerConfiguration"><ref bean="fileServerConfiguration"/></property>
|
<property name="fileServerConfiguration"><ref bean="fileServerConfiguration"/></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Datasource bean -->
|
<!-- Datasource bean -->
|
||||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||||
@@ -155,12 +155,12 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="retryingTransactionHelper" class="org.alfresco.repo.transaction.RetryingTransactionHelper">
|
<bean id="retryingTransactionHelper" class="org.alfresco.repo.transaction.RetryingTransactionHelper">
|
||||||
<property name="transactionService">
|
<property name="transactionService">
|
||||||
<ref bean="transactionComponent"/>
|
<ref bean="transactionComponent"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="maxRetries">
|
<property name="maxRetries">
|
||||||
<value>20</value>
|
<value>20</value>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="readWriteTransactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
|
<bean id="readWriteTransactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
|
||||||
@@ -210,24 +210,25 @@
|
|||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
<bean id="resourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
<bean id="resourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
||||||
<property name="resourceBundles">
|
<property name="resourceBundles">
|
||||||
<list>
|
<list>
|
||||||
<value>alfresco.messages.system-messages</value>
|
<value>alfresco.messages.system-messages</value>
|
||||||
<value>alfresco.messages.module-messages</value>
|
<value>alfresco.messages.module-messages</value>
|
||||||
<value>alfresco.messages.dictionary-messages</value>
|
<value>alfresco.messages.dictionary-messages</value>
|
||||||
<value>alfresco.messages.version-service</value>
|
<value>alfresco.messages.version-service</value>
|
||||||
<value>alfresco.messages.permissions-service</value>
|
<value>alfresco.messages.permissions-service</value>
|
||||||
<value>alfresco.messages.content-service</value>
|
<value>alfresco.messages.content-service</value>
|
||||||
<value>alfresco.messages.coci-service</value>
|
<value>alfresco.messages.coci-service</value>
|
||||||
<value>alfresco.messages.template-service</value>
|
<value>alfresco.messages.template-service</value>
|
||||||
<value>alfresco.messages.lock-service</value>
|
<value>alfresco.messages.lock-service</value>
|
||||||
<value>alfresco.messages.patch-service</value>
|
<value>alfresco.messages.patch-service</value>
|
||||||
<value>alfresco.messages.schema-update</value>
|
<value>alfresco.messages.schema-update</value>
|
||||||
<value>alfresco.messages.webdav-messages</value>
|
<value>alfresco.messages.webdav-messages</value>
|
||||||
<value>alfresco.messages.copy-service</value>
|
<value>alfresco.messages.copy-service</value>
|
||||||
<value>alfresco.messages.avm-messages</value>
|
<value>alfresco.messages.avm-messages</value>
|
||||||
</list>
|
<value>alfresco.messages.content-filter-languages</value>
|
||||||
</property>
|
</list>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
@@ -426,10 +427,10 @@
|
|||||||
<property name="lockPollInterval">
|
<property name="lockPollInterval">
|
||||||
<value>${lucene.lock.poll.interval}</value>
|
<value>${lucene.lock.poll.interval}</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="defaultMLIndexAnalysisMode">
|
<property name="defaultMLIndexAnalysisMode">
|
||||||
<value>EXACT_LANGUAGE_AND_ALL</value>
|
<value>EXACT_LANGUAGE_AND_ALL</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="defaultMLSearchAnalysisMode">
|
<property name="defaultMLSearchAnalysisMode">
|
||||||
<value>EXACT_LANGUAGE_AND_ALL</value>
|
<value>EXACT_LANGUAGE_AND_ALL</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
@@ -547,23 +548,23 @@
|
|||||||
|
|
||||||
<bean id="namespaceDAO" class="org.alfresco.repo.dictionary.NamespaceDAOImpl" />
|
<bean id="namespaceDAO" class="org.alfresco.repo.dictionary.NamespaceDAOImpl" />
|
||||||
|
|
||||||
<bean id="dictionaryModelType" class="org.alfresco.repo.dictionary.DictionaryModelType" init-method="init">
|
<bean id="dictionaryModelType" class="org.alfresco.repo.dictionary.DictionaryModelType" init-method="init">
|
||||||
<property name="dictionaryDAO">
|
<property name="dictionaryDAO">
|
||||||
<ref bean="dictionaryDAO" />
|
<ref bean="dictionaryDAO" />
|
||||||
</property>
|
</property>
|
||||||
<property name="namespaceDAO">
|
<property name="namespaceDAO">
|
||||||
<ref bean="namespaceDAO" />
|
<ref bean="namespaceDAO" />
|
||||||
</property>
|
</property>
|
||||||
<property name="nodeService">
|
<property name="nodeService">
|
||||||
<ref bean="nodeService"/>
|
<ref bean="nodeService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="contentService">
|
<property name="contentService">
|
||||||
<ref bean="contentService"/>
|
<ref bean="contentService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="policyComponent">
|
<property name="policyComponent">
|
||||||
<ref bean="policyComponent"/>
|
<ref bean="policyComponent"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="dictionaryDAO" class="org.alfresco.repo.dictionary.DictionaryDAOImpl">
|
<bean id="dictionaryDAO" class="org.alfresco.repo.dictionary.DictionaryDAOImpl">
|
||||||
<constructor-arg index="0">
|
<constructor-arg index="0">
|
||||||
@@ -585,7 +586,7 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="dictionaryModelBootstrap" class="org.alfresco.repo.dictionary.DictionaryBootstrap" init-method="bootstrap" abstract="true">
|
<bean id="dictionaryModelBootstrap" class="org.alfresco.repo.dictionary.DictionaryBootstrap" init-method="bootstrap" abstract="true">
|
||||||
<property name="dictionaryDAO"><ref local="dictionaryDAO"/></property>
|
<property name="dictionaryDAO"><ref local="dictionaryDAO"/></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="resourceBundles">
|
<bean id="dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="resourceBundles">
|
||||||
@@ -636,23 +637,23 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="dictionaryRepositoryBootstrap" class="org.alfresco.repo.dictionary.DictionaryRepositoryBootstrap" init-method="bootstrap">
|
<bean id="dictionaryRepositoryBootstrap" class="org.alfresco.repo.dictionary.DictionaryRepositoryBootstrap" init-method="bootstrap">
|
||||||
<property name="dictionaryDAO">
|
<property name="dictionaryDAO">
|
||||||
<ref local="dictionaryDAO"/>
|
<ref local="dictionaryDAO"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="contentService">
|
<property name="contentService">
|
||||||
<ref bean="contentService"/>
|
<ref bean="contentService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="searchService">
|
<property name="searchService">
|
||||||
<ref bean="searchService"/>
|
<ref bean="searchService"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="transactionService">
|
<property name="transactionService">
|
||||||
<ref bean="transactionComponent"/>
|
<ref bean="transactionComponent"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="authenticationComponent">
|
<property name="authenticationComponent">
|
||||||
<ref bean="authenticationComponent"/>
|
<ref bean="authenticationComponent"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Copy Service -->
|
<!-- Copy Service -->
|
||||||
@@ -825,6 +826,52 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Multilingual Document-->
|
||||||
|
<bean id="multilingualDocumentAspect" class="org.alfresco.repo.model.ml.MultilingualDocumentAspect" init-method="init">
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="multilingualContentService">
|
||||||
|
<ref bean="MultilingualContentService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Empty translation -->
|
||||||
|
<bean id="emptyTranslationAspect" class="org.alfresco.repo.model.ml.EmptyTranslationAspect" init-method="init">
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Multilingual Container -->
|
||||||
|
<bean id="mlContainerType" class="org.alfresco.repo.model.ml.MLContainerType" init-method="init">
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="multilingualContentService">
|
||||||
|
<ref bean="MultilingualContentService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Folder -->
|
||||||
|
<bean id="folderType" class="org.alfresco.repo.model.filefolder.FolderType" init-method="init">
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService" />
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Referenceable -->
|
<!-- Referenceable -->
|
||||||
<bean id="referenceableAspect" class="org.alfresco.repo.node.ReferenceableAspect" init-method="init">
|
<bean id="referenceableAspect" class="org.alfresco.repo.node.ReferenceableAspect" init-method="init">
|
||||||
<property name="policyComponent">
|
<property name="policyComponent">
|
||||||
|
194
config/alfresco/messages/content-filter-languages.properties
Normal file
194
config/alfresco/messages/content-filter-languages.properties
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
## Translations of ISO 639-1 languages codes
|
||||||
|
|
||||||
|
content_filter_lang.aa=Afar
|
||||||
|
content_filter_lang.ab=Abkhazian
|
||||||
|
content_filter_lang.ae=Avestan
|
||||||
|
content_filter_lang.af=Afrikaans
|
||||||
|
content_filter_lang.ak=Akan
|
||||||
|
content_filter_lang.am=Amharic
|
||||||
|
content_filter_lang.an=Aragonese
|
||||||
|
content_filter_lang.ar=Arabic
|
||||||
|
content_filter_lang.as=Assamese
|
||||||
|
content_filter_lang.av=Avaric
|
||||||
|
content_filter_lang.ay=Aymara
|
||||||
|
content_filter_lang.az=Azerbaijani
|
||||||
|
content_filter_lang.ba=Bashkir
|
||||||
|
content_filter_lang.be=Belarusian
|
||||||
|
content_filter_lang.bg=Bulgarian
|
||||||
|
content_filter_lang.bh=Bihari
|
||||||
|
content_filter_lang.bi=Bislama
|
||||||
|
content_filter_lang.bm=Bambara
|
||||||
|
content_filter_lang.bn=Bengali
|
||||||
|
content_filter_lang.bo=Tibetan
|
||||||
|
content_filter_lang.br=Breton
|
||||||
|
content_filter_lang.bs=Bosnian
|
||||||
|
content_filter_lang.ca=Catalan; Valencian
|
||||||
|
content_filter_lang.ce=Chechen
|
||||||
|
content_filter_lang.ch=Chamorro
|
||||||
|
content_filter_lang.co=Corsican
|
||||||
|
content_filter_lang.cr=Cree
|
||||||
|
content_filter_lang.cs=Czech
|
||||||
|
content_filter_lang.cu=Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic
|
||||||
|
content_filter_lang.cv=Chuvash
|
||||||
|
content_filter_lang.cy=Welsh
|
||||||
|
content_filter_lang.da=Danish
|
||||||
|
content_filter_lang.de=German
|
||||||
|
content_filter_lang.dv=Divehi; Dhivehi; Maldivian
|
||||||
|
content_filter_lang.dz=Dzongkha
|
||||||
|
content_filter_lang.ee=Ewe
|
||||||
|
content_filter_lang.el=Greek
|
||||||
|
content_filter_lang.en=English
|
||||||
|
content_filter_lang.eo=Esperanto
|
||||||
|
content_filter_lang.es=Spanish
|
||||||
|
content_filter_lang.et=Estonian
|
||||||
|
content_filter_lang.eu=Basque
|
||||||
|
content_filter_lang.fa=Persian
|
||||||
|
content_filter_lang.ff=Fulah
|
||||||
|
content_filter_lang.fi=Finnish
|
||||||
|
content_filter_lang.fj=Fijian
|
||||||
|
content_filter_lang.fo=Faroese
|
||||||
|
content_filter_lang.fr=French
|
||||||
|
content_filter_lang.fy=Western Frisian
|
||||||
|
content_filter_lang.ga=Irish
|
||||||
|
content_filter_lang.gd=Gaelic; Scottish Gaelic
|
||||||
|
content_filter_lang.gl=Galician
|
||||||
|
content_filter_lang.gn=Guarani
|
||||||
|
content_filter_lang.gu=Gujarati
|
||||||
|
content_filter_lang.gv=Manx
|
||||||
|
content_filter_lang.ha=Hausa
|
||||||
|
content_filter_lang.he=Hebrew
|
||||||
|
content_filter_lang.hi=Hindi
|
||||||
|
content_filter_lang.ho=Hiri Motu
|
||||||
|
content_filter_lang.hr=Croatian
|
||||||
|
content_filter_lang.ht=Haitian; Haitian Creole
|
||||||
|
content_filter_lang.hu=Hungarian
|
||||||
|
content_filter_lang.hy=Armenian
|
||||||
|
content_filter_lang.hz=Herero
|
||||||
|
content_filter_lang.ia=Interlingua (International Auxiliary Language Association)
|
||||||
|
content_filter_lang.id=Indonesian
|
||||||
|
content_filter_lang.ie=Interlingue
|
||||||
|
content_filter_lang.ig=Igbo
|
||||||
|
content_filter_lang.ii=Sichuan Yi
|
||||||
|
content_filter_lang.ik=Inupiaq
|
||||||
|
content_filter_lang.io=Ido
|
||||||
|
content_filter_lang.is=Icelandic
|
||||||
|
content_filter_lang.it=Italian
|
||||||
|
content_filter_lang.iu=Inuktitut
|
||||||
|
content_filter_lang.ja=Japanese
|
||||||
|
content_filter_lang.jv=Javanese
|
||||||
|
content_filter_lang.ka=Georgian
|
||||||
|
content_filter_lang.kg=Kongo
|
||||||
|
content_filter_lang.ki=Kikuyu; Gikuyu
|
||||||
|
content_filter_lang.kj=Kuanyama; Kwanyama
|
||||||
|
content_filter_lang.kk=Kazakh
|
||||||
|
content_filter_lang.kl=Kalaallisut; Greenlandic
|
||||||
|
content_filter_lang.km=Khmer
|
||||||
|
content_filter_lang.kn=Kannada
|
||||||
|
content_filter_lang.ko=Korean
|
||||||
|
content_filter_lang.kr=Kanuri
|
||||||
|
content_filter_lang.ks=Kashmiri
|
||||||
|
content_filter_lang.ku=Kurdish
|
||||||
|
content_filter_lang.kv=Komi
|
||||||
|
content_filter_lang.kw=Cornish
|
||||||
|
content_filter_lang.ky=Kirghiz
|
||||||
|
content_filter_lang.la=Latin
|
||||||
|
content_filter_lang.lb=Luxembourgish; Letzeburgesch
|
||||||
|
content_filter_lang.lg=Ganda
|
||||||
|
content_filter_lang.li=Limburgan; Limburger; Limburgish
|
||||||
|
content_filter_lang.ln=Lingala
|
||||||
|
content_filter_lang.lo=Lao
|
||||||
|
content_filter_lang.lt=Lithuanian
|
||||||
|
content_filter_lang.lu=Luba-Katanga
|
||||||
|
content_filter_lang.lv=Latvian
|
||||||
|
content_filter_lang.mg=Malagasy
|
||||||
|
content_filter_lang.mh=Marshallese
|
||||||
|
content_filter_lang.mi=Maori
|
||||||
|
content_filter_lang.mk=Macedonian
|
||||||
|
content_filter_lang.ml=Malayalam
|
||||||
|
content_filter_lang.mn=Mongolian
|
||||||
|
content_filter_lang.mo=Moldavian
|
||||||
|
content_filter_lang.mr=Marathi
|
||||||
|
content_filter_lang.ms=Malay
|
||||||
|
content_filter_lang.mt=Maltese
|
||||||
|
content_filter_lang.my=Burmese
|
||||||
|
content_filter_lang.na=Nauru
|
||||||
|
content_filter_lang.nb=Norwegian Bokm\u00e5l
|
||||||
|
content_filter_lang.nd=Ndebele, North; North Ndebele
|
||||||
|
content_filter_lang.ne=Nepali
|
||||||
|
content_filter_lang.ng=Ndonga
|
||||||
|
content_filter_lang.nl=Dutch
|
||||||
|
content_filter_lang.nn=Norwegian Nynorsk
|
||||||
|
content_filter_lang.no=Norwegian
|
||||||
|
content_filter_lang.nr=Ndebele, South; South Ndebele
|
||||||
|
content_filter_lang.nv=Navajo; Navaho
|
||||||
|
content_filter_lang.ny=Chichewa; Chewa; Nyanja
|
||||||
|
content_filter_lang.oc=Occitan (post 1500); Proven\u00e7al
|
||||||
|
content_filter_lang.oj=Ojibwa
|
||||||
|
content_filter_lang.om=Oromo
|
||||||
|
content_filter_lang.or=Oriya
|
||||||
|
content_filter_lang.os=Ossetian; Ossetic
|
||||||
|
content_filter_lang.pa=Panjabi; Punjabi
|
||||||
|
content_filter_lang.pi=Pali
|
||||||
|
content_filter_lang.pl=Polish
|
||||||
|
content_filter_lang.ps=Pushto
|
||||||
|
content_filter_lang.pt=Portuguese
|
||||||
|
content_filter_lang.qu=Quechua
|
||||||
|
content_filter_lang.rm=Raeto-Romance
|
||||||
|
content_filter_lang.rn=Rundi
|
||||||
|
content_filter_lang.ro=Romanian
|
||||||
|
content_filter_lang.ru=Russian
|
||||||
|
content_filter_lang.rw=Kinyarwanda
|
||||||
|
content_filter_lang.sa=Sanskrit
|
||||||
|
content_filter_lang.sc=Sardinian
|
||||||
|
content_filter_lang.sd=Sindhi
|
||||||
|
content_filter_lang.se=Northern Sami
|
||||||
|
content_filter_lang.sg=Sango
|
||||||
|
content_filter_lang.si=Sinhala; Sinhalese
|
||||||
|
content_filter_lang.sk=Slovak
|
||||||
|
content_filter_lang.sl=Slovenian
|
||||||
|
content_filter_lang.sm=Samoan
|
||||||
|
content_filter_lang.sn=Shona
|
||||||
|
content_filter_lang.so=Somali
|
||||||
|
content_filter_lang.sq=Albanian
|
||||||
|
content_filter_lang.sr=Serbian
|
||||||
|
content_filter_lang.ss=Swati
|
||||||
|
content_filter_lang.st=Sotho, Southern
|
||||||
|
content_filter_lang.su=Sundanese
|
||||||
|
content_filter_lang.sv=Swedish
|
||||||
|
content_filter_lang.sw=Swahili
|
||||||
|
content_filter_lang.ta=Tamil
|
||||||
|
content_filter_lang.te=Telugu
|
||||||
|
content_filter_lang.tg=Tajik
|
||||||
|
content_filter_lang.th=Thai
|
||||||
|
content_filter_lang.ti=Tigrinya
|
||||||
|
content_filter_lang.tk=Turkmen
|
||||||
|
content_filter_lang.tl=Tagalog
|
||||||
|
content_filter_lang.tn=Tswana
|
||||||
|
content_filter_lang.to=Tonga (Tonga Islands)
|
||||||
|
content_filter_lang.tr=Turkish
|
||||||
|
content_filter_lang.tr=Turkish
|
||||||
|
content_filter_lang.ts=Tsonga
|
||||||
|
content_filter_lang.tt=Tatar
|
||||||
|
content_filter_lang.tw=Twi
|
||||||
|
content_filter_lang.ty=Tahitian
|
||||||
|
content_filter_lang.ug=Uighur; Uyghur
|
||||||
|
content_filter_lang.uk=Ukrainian
|
||||||
|
content_filter_lang.ur=Urdu
|
||||||
|
content_filter_lang.uz=Uzbek
|
||||||
|
content_filter_lang.ve=Venda
|
||||||
|
content_filter_lang.vi=Vietnamese
|
||||||
|
content_filter_lang.vo=Volap\u00fck
|
||||||
|
content_filter_lang.wa=Walloon
|
||||||
|
content_filter_lang.wo=Wolof
|
||||||
|
content_filter_lang.xh=Xhosa
|
||||||
|
content_filter_lang.yi=Yiddish
|
||||||
|
content_filter_lang.yo=Yoruba
|
||||||
|
content_filter_lang.za=Zhuang; Chuang
|
||||||
|
content_filter_lang.zh=Chinese
|
||||||
|
content_filter_lang.zu=Zulu
|
||||||
|
|
||||||
|
## Duplicate messages to take in account the old
|
||||||
|
## ISO code.
|
||||||
|
content_filter_lang.iw=Hebrew
|
||||||
|
content_filter_lang.in=Indonesian
|
||||||
|
content_filter_lang.ji=Yiddish
|
@@ -18,6 +18,9 @@ sys_systemmodel.type.sys_reference.description=Reference
|
|||||||
sys_systemmodel.property.sys_reference.title=Reference
|
sys_systemmodel.property.sys_reference.title=Reference
|
||||||
sys_systemmodel.property.sys_reference.description=Reference
|
sys_systemmodel.property.sys_reference.description=Reference
|
||||||
|
|
||||||
|
sys_systemmodel.property.sys_locale.title=Locale
|
||||||
|
sys_systemmodel.property.sys_locale.description=Locale
|
||||||
|
|
||||||
sys_systemmodel.aspect.aspect_root.title=Root
|
sys_systemmodel.aspect.aspect_root.title=Root
|
||||||
sys_systemmodel.aspect.aspect_root.description=Root
|
sys_systemmodel.aspect.aspect_root.description=Root
|
||||||
|
|
||||||
|
455
config/alfresco/ml/content-filter-lang.xml
Normal file
455
config/alfresco/ml/content-filter-lang.xml
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
<alfresco-config area="content-filter-lang">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Define which standardized languages list to use.
|
||||||
|
Can be a personal one.
|
||||||
|
-->
|
||||||
|
<config evaluator="string-compare" condition="Standard In Use">
|
||||||
|
<standard>ISO_639-1_EU-Order</standard>
|
||||||
|
</config>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Define a ordered map of languages matched by his unique language code.
|
||||||
|
-->
|
||||||
|
<config evaluator="string-compare" condition="Languages Filter Map">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ISO 639-1 (alpha-2) uses 2 car codes.
|
||||||
|
|
||||||
|
The list is ordered by language code ascending.
|
||||||
|
-->
|
||||||
|
<ISO_639-1>
|
||||||
|
<lang order="1" code="aa">Afar</lang>
|
||||||
|
<lang order="2" code="ab">Abkhazian</lang>
|
||||||
|
<lang order="3" code="ae">Avestan</lang>
|
||||||
|
<lang order="4" code="af">Afrikaans</lang>
|
||||||
|
<lang order="5" code="ak">Akan</lang>
|
||||||
|
<lang order="6" code="am">Amharic</lang>
|
||||||
|
<lang order="7" code="an">Aragonese</lang>
|
||||||
|
<lang order="8" code="ar">Arabic</lang>
|
||||||
|
<lang order="9" code="as">Assamese</lang>
|
||||||
|
<lang order="10" code="av">Avaric</lang>
|
||||||
|
<lang order="11" code="ay">Aymara</lang>
|
||||||
|
<lang order="12" code="az">Azerbaijani</lang>
|
||||||
|
<lang order="13" code="ba">Bashkir</lang>
|
||||||
|
<lang order="14" code="be">Belarusian</lang>
|
||||||
|
<lang order="15" code="bg">Bulgarian</lang>
|
||||||
|
<lang order="16" code="bh">Bihari</lang>
|
||||||
|
<lang order="17" code="bi">Bislama</lang>
|
||||||
|
<lang order="18" code="bm">Bambara</lang>
|
||||||
|
<lang order="19" code="bn">Bengali</lang>
|
||||||
|
<lang order="20" code="bo">Tibetan</lang>
|
||||||
|
<lang order="21" code="br">Breton</lang>
|
||||||
|
<lang order="22" code="bs">Bosnian</lang>
|
||||||
|
<lang order="23" code="ca">Catalan; Valencian</lang>
|
||||||
|
<lang order="24" code="ce">Chechen</lang>
|
||||||
|
<lang order="25" code="ch">Chamorro</lang>
|
||||||
|
<lang order="26" code="co">Corsican</lang>
|
||||||
|
<lang order="27" code="cr">Cree</lang>
|
||||||
|
<lang order="28" code="cs">Czech</lang>
|
||||||
|
<lang order="29" code="cu">
|
||||||
|
Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic
|
||||||
|
</lang>
|
||||||
|
<lang order="30" code="cv">Chuvash</lang>
|
||||||
|
<lang order="31" code="cy">Welsh</lang>
|
||||||
|
<lang order="32" code="da">Danish</lang>
|
||||||
|
<lang order="33" code="de">German</lang>
|
||||||
|
<lang order="34" code="dv">
|
||||||
|
Divehi; Dhivehi; Maldivian
|
||||||
|
</lang>
|
||||||
|
<lang order="35" code="dz">Dzongkha</lang>
|
||||||
|
<lang order="36" code="ee">Ewe</lang>
|
||||||
|
<lang order="37" code="el">Greek</lang>
|
||||||
|
<lang order="38" code="en">English</lang>
|
||||||
|
<lang order="39" code="eo">Esperanto</lang>
|
||||||
|
<lang order="40" code="es">Spanish</lang>
|
||||||
|
<lang order="41" code="et">Estonian</lang>
|
||||||
|
<lang order="42" code="eu">Basque</lang>
|
||||||
|
<lang order="43" code="fa">Persian</lang>
|
||||||
|
<lang order="44" code="ff">Fulah</lang>
|
||||||
|
<lang order="45" code="fi">Finnish</lang>
|
||||||
|
<lang order="46" code="fj">Fijian</lang>
|
||||||
|
<lang order="47" code="fo">Faroese</lang>
|
||||||
|
<lang order="48" code="fr">French</lang>
|
||||||
|
<lang order="49" code="fy">Western Frisian</lang>
|
||||||
|
<lang order="50" code="ga">Irish</lang>
|
||||||
|
<lang order="51" code="gd">
|
||||||
|
Gaelic; Scottish Gaelic
|
||||||
|
</lang>
|
||||||
|
<lang order="52" code="gl">Galician</lang>
|
||||||
|
<lang order="53" code="gn">Guarani</lang>
|
||||||
|
<lang order="54" code="gu">Gujarati</lang>
|
||||||
|
<lang order="55" code="gv">Manx</lang>
|
||||||
|
<lang order="56" code="ha">Hausa</lang>
|
||||||
|
<lang order="57" code="he">Hebrew</lang>
|
||||||
|
<lang order="58" code="hi">Hindi</lang>
|
||||||
|
<lang order="59" code="ho">Hiri Motu</lang>
|
||||||
|
<lang order="60" code="hr">Croatian</lang>
|
||||||
|
<lang order="61" code="ht">
|
||||||
|
Haitian; Haitian Creole
|
||||||
|
</lang>
|
||||||
|
<lang order="62" code="hu">Hungarian</lang>
|
||||||
|
<lang order="63" code="hy">Armenian</lang>
|
||||||
|
<lang order="64" code="hz">Herero</lang>
|
||||||
|
<lang order="65" code="ia">
|
||||||
|
Interlingua (International Auxiliary Language Association)
|
||||||
|
</lang>
|
||||||
|
<lang order="66" code="id">Indonesian</lang>
|
||||||
|
<lang order="67" code="ie">Interlingue</lang>
|
||||||
|
<lang order="68" code="ig">Igbo</lang>
|
||||||
|
<lang order="69" code="ii">Sichuan Yi</lang>
|
||||||
|
<lang order="70" code="ik">Inupiaq</lang>
|
||||||
|
<lang order="71" code="io">Ido</lang>
|
||||||
|
<lang order="72" code="is">Icelandic</lang>
|
||||||
|
<lang order="73" code="it">Italian</lang>
|
||||||
|
<lang order="74" code="iu">Inuktitut</lang>
|
||||||
|
<lang order="75" code="ja">Japanese</lang>
|
||||||
|
<lang order="76" code="jv">Javanese</lang>
|
||||||
|
<lang order="77" code="ka">Georgian</lang>
|
||||||
|
<lang order="78" code="kg">Kongo</lang>
|
||||||
|
<lang order="79" code="ki">Kikuyu; Gikuyu</lang>
|
||||||
|
<lang order="80" code="kj">Kuanyama; Kwanyama</lang>
|
||||||
|
<lang order="81" code="kk">Kazakh</lang>
|
||||||
|
<lang order="82" code="kl">
|
||||||
|
Kalaallisut; Greenlandic
|
||||||
|
</lang>
|
||||||
|
<lang order="83" code="km">Khmer</lang>
|
||||||
|
<lang order="84" code="kn">Kannada</lang>
|
||||||
|
<lang order="85" code="ko">Korean</lang>
|
||||||
|
<lang order="86" code="kr">Kanuri</lang>
|
||||||
|
<lang order="87" code="ks">Kashmiri</lang>
|
||||||
|
<lang order="88" code="ku">Kurdish</lang>
|
||||||
|
<lang order="89" code="kv">Komi</lang>
|
||||||
|
<lang order="90" code="kw">Cornish</lang>
|
||||||
|
<lang order="91" code="ky">Kirghiz</lang>
|
||||||
|
<lang order="92" code="la">Latin</lang>
|
||||||
|
<lang order="93" code="lb">
|
||||||
|
Luxembourgish; Letzeburgesch
|
||||||
|
</lang>
|
||||||
|
<lang order="94" code="lg">Ganda</lang>
|
||||||
|
<lang order="95" code="li">
|
||||||
|
Limburgan; Limburger; Limburgish
|
||||||
|
</lang>
|
||||||
|
<lang order="96" code="ln">Lingala</lang>
|
||||||
|
<lang order="97" code="lo">Lao</lang>
|
||||||
|
<lang order="98" code="lt">Lithuanian</lang>
|
||||||
|
<lang order="99" code="lu">Luba-Katanga</lang>
|
||||||
|
<lang order="100" code="lv">Latvian</lang>
|
||||||
|
<lang order="101" code="mg">Malagasy</lang>
|
||||||
|
<lang order="102" code="mh">Marshallese</lang>
|
||||||
|
<lang order="103" code="mi">Maori</lang>
|
||||||
|
<lang order="104" code="mk">Macedonian</lang>
|
||||||
|
<lang order="105" code="ml">Malayalam</lang>
|
||||||
|
<lang order="106" code="mn">Mongolian</lang>
|
||||||
|
<lang order="107" code="mo">Moldavian</lang>
|
||||||
|
<lang order="108" code="mr">Marathi</lang>
|
||||||
|
<lang order="109" code="ms">Malay</lang>
|
||||||
|
<lang order="110" code="mt">Maltese</lang>
|
||||||
|
<lang order="111" code="my">Burmese</lang>
|
||||||
|
<lang order="112" code="na">Nauru</lang>
|
||||||
|
<lang order="113" code="nb">Norvégien Bokmål</lang>
|
||||||
|
<lang order="114" code="nd">
|
||||||
|
Ndebele, North; North Ndebele
|
||||||
|
</lang>
|
||||||
|
<lang order="115" code="ne">Nepali</lang>
|
||||||
|
<lang order="116" code="ng">Ndonga</lang>
|
||||||
|
<lang order="117" code="nl">Dutch</lang>
|
||||||
|
<lang order="118" code="nn">Norwegian Nynorsk</lang>
|
||||||
|
<lang order="119" code="no">Norwegian</lang>
|
||||||
|
<lang order="120" code="nr">
|
||||||
|
Ndebele, South; South Ndebele
|
||||||
|
</lang>
|
||||||
|
<lang order="121" code="nv">Navajo; Navaho</lang>
|
||||||
|
<lang order="122" code="ny">
|
||||||
|
Chichewa; Chewa; Nyanja
|
||||||
|
</lang>
|
||||||
|
<lang order="123" code="oc">
|
||||||
|
Occitan (post 1500); Provençal
|
||||||
|
</lang>
|
||||||
|
<lang order="124" code="oj">Ojibwa</lang>
|
||||||
|
<lang order="125" code="om">Oromo</lang>
|
||||||
|
<lang order="126" code="or">Oriya</lang>
|
||||||
|
<lang order="127" code="os">Ossetian; Ossetic</lang>
|
||||||
|
<lang order="128" code="pa">Panjabi; Punjabi</lang>
|
||||||
|
<lang order="129" code="pi">Pali</lang>
|
||||||
|
<lang order="130" code="pl">Polish</lang>
|
||||||
|
<lang order="131" code="ps">Pushto</lang>
|
||||||
|
<lang order="132" code="pt">Portuguese</lang>
|
||||||
|
<lang order="133" code="qu">Quechua</lang>
|
||||||
|
<lang order="134" code="rm">Raeto-Romance</lang>
|
||||||
|
<lang order="135" code="rn">Rundi</lang>
|
||||||
|
<lang order="136" code="ro">Romanian</lang>
|
||||||
|
<lang order="137" code="ru">Russian</lang>
|
||||||
|
<lang order="138" code="rw">Kinyarwanda</lang>
|
||||||
|
<lang order="139" code="sa">Sanskrit</lang>
|
||||||
|
<lang order="140" code="sc">Sardinian</lang>
|
||||||
|
<lang order="141" code="sd">Sindhi</lang>
|
||||||
|
<lang order="142" code="se">Northern Sami</lang>
|
||||||
|
<lang order="143" code="sg">Sango</lang>
|
||||||
|
<lang order="144" code="si">Sinhala; Sinhalese</lang>
|
||||||
|
<lang order="145" code="sk">Slovak</lang>
|
||||||
|
<lang order="146" code="sl">Slovenian</lang>
|
||||||
|
<lang order="147" code="sm">Samoan</lang>
|
||||||
|
<lang order="148" code="sn">Shona</lang>
|
||||||
|
<lang order="149" code="so">Somali</lang>
|
||||||
|
<lang order="150" code="sq">Albanian</lang>
|
||||||
|
<lang order="151" code="sr">Serbian</lang>
|
||||||
|
<lang order="152" code="ss">Swati</lang>
|
||||||
|
<lang order="153" code="st">Sotho, Southern</lang>
|
||||||
|
<lang order="154" code="su">Sundanese</lang>
|
||||||
|
<lang order="155" code="sv">Swedish</lang>
|
||||||
|
<lang order="156" code="sw">Swahili</lang>
|
||||||
|
<lang order="157" code="ta">Tamil</lang>
|
||||||
|
<lang order="158" code="te">Telugu</lang>
|
||||||
|
<lang order="159" code="tg">Tajik</lang>
|
||||||
|
<lang order="160" code="th">Thai</lang>
|
||||||
|
<lang order="161" code="ti">Tigrinya</lang>
|
||||||
|
<lang order="162" code="tk">Turkmen</lang>
|
||||||
|
<lang order="163" code="tl">Tagalog</lang>
|
||||||
|
<lang order="164" code="tn">Tswana</lang>
|
||||||
|
<lang order="165" code="to">Tonga (Tonga Islands)</lang>
|
||||||
|
<lang order="166" code="tr">Turkish</lang>
|
||||||
|
<lang order="167" code="tr">Turkish</lang>
|
||||||
|
<lang order="168" code="ts">Tsonga</lang>
|
||||||
|
<lang order="169" code="tt">Tatar</lang>
|
||||||
|
<lang order="170" code="tw">Twi</lang>
|
||||||
|
<lang order="171" code="ty">Tahitian</lang>
|
||||||
|
<lang order="172" code="ug">Uighur; Uyghur</lang>
|
||||||
|
<lang order="173" code="uk">Ukrainian</lang>
|
||||||
|
<lang order="174" code="ur">Urdu</lang>
|
||||||
|
<lang order="175" code="uz">Uzbek</lang>
|
||||||
|
<lang order="176" code="ve">Venda</lang>
|
||||||
|
<lang order="177" code="vi">Vietnamese</lang>
|
||||||
|
<lang order="178" code="vo">Volapük</lang>
|
||||||
|
<lang order="179" code="wa">Walloon</lang>
|
||||||
|
<lang order="180" code="wo">Wolof</lang>
|
||||||
|
<lang order="181" code="xh">Xhosa</lang>
|
||||||
|
<lang order="182" code="yi">Yiddish</lang>
|
||||||
|
<lang order="183" code="yo">Yoruba</lang>
|
||||||
|
<lang order="184" code="za">Zhuang; Chuang</lang>
|
||||||
|
<lang order="185" code="zh">Chinese</lang>
|
||||||
|
<lang order="186" code="zu">Zulu</lang>
|
||||||
|
</ISO_639-1>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ISO 639-1 (alpha-2) uses 2 car codes.
|
||||||
|
|
||||||
|
The list is ordered for the European Commission needs.
|
||||||
|
-->
|
||||||
|
<ISO_639-1_EU-Order>
|
||||||
|
<lang order="1" code="bg">Bulgarian</lang>
|
||||||
|
<lang order="2" code="cs">Czech</lang>
|
||||||
|
<lang order="3" code="da">Danish</lang>
|
||||||
|
<lang order="4" code="de">German</lang>
|
||||||
|
<lang order="5" code="et">Estonian</lang>
|
||||||
|
<lang order="6" code="el">Greek</lang>
|
||||||
|
<lang order="7" code="en" default="true">English</lang>
|
||||||
|
<lang order="8" code="es">Spanish</lang>
|
||||||
|
<lang order="9" code="fr">French</lang>
|
||||||
|
<lang order="10" code="ga">Irish</lang>
|
||||||
|
<lang order="11" code="it">Italian</lang>
|
||||||
|
<lang order="12" code="lv">Latvian</lang>
|
||||||
|
<lang order="13" code="lt">Lithuanian</lang>
|
||||||
|
<lang order="14" code="hu">Hungarian</lang>
|
||||||
|
<lang order="15" code="mt">Maltese</lang>
|
||||||
|
<lang order="16" code="nl">Dutch</lang>
|
||||||
|
<lang order="17" code="pl">Polish</lang>
|
||||||
|
<lang order="18" code="pt">Portuguese</lang>
|
||||||
|
<lang order="19" code="ro">Romanian</lang>
|
||||||
|
<lang order="20" code="sk">Slovak</lang>
|
||||||
|
<lang order="21" code="sl">Slovenian</lang>
|
||||||
|
<lang order="22" code="fi">Finnish</lang>
|
||||||
|
<lang order="23" code="sv">Swedish</lang>
|
||||||
|
<lang order="24" code="hr">Croatian</lang>
|
||||||
|
<lang order="25" code="tr">Turkish</lang>
|
||||||
|
<lang order="26" code="aa">Afar</lang>
|
||||||
|
<lang order="27" code="ab">Abkhazian</lang>
|
||||||
|
<lang order="28" code="af">Afrikaans</lang>
|
||||||
|
<lang order="29" code="ak">Akan</lang>
|
||||||
|
<lang order="30" code="sq">Albanian</lang>
|
||||||
|
<lang order="31" code="am">Amharic</lang>
|
||||||
|
<lang order="32" code="ar">Arabic</lang>
|
||||||
|
<lang order="33" code="an">Aragonese</lang>
|
||||||
|
<lang order="34" code="hy">Armenian</lang>
|
||||||
|
<lang order="35" code="as">Assamese</lang>
|
||||||
|
<lang order="36" code="av">Avaric</lang>
|
||||||
|
<lang order="37" code="ae">Avestan</lang>
|
||||||
|
<lang order="38" code="ay">Aymara</lang>
|
||||||
|
<lang order="39" code="az">Azerbaijani</lang>
|
||||||
|
<lang order="40" code="ba">Bashkir</lang>
|
||||||
|
<lang order="41" code="bm">Bambara</lang>
|
||||||
|
<lang order="42" code="eu">Basque</lang>
|
||||||
|
<lang order="43" code="be">Belarusian</lang>
|
||||||
|
<lang order="44" code="bn">Bengali</lang>
|
||||||
|
<lang order="45" code="bh">Bihari</lang>
|
||||||
|
<lang order="46" code="bi">Bislama</lang>
|
||||||
|
<lang order="47" code="bs">Bosnian</lang>
|
||||||
|
<lang order="48" code="br">Breton</lang>
|
||||||
|
<lang order="49" code="my">Burmese</lang>
|
||||||
|
<lang order="50" code="ca">Catalan; Valencian</lang>
|
||||||
|
<lang order="51" code="ch">Chamorro</lang>
|
||||||
|
<lang order="52" code="ce">Chechen</lang>
|
||||||
|
<lang order="53" code="zh">Chinese</lang>
|
||||||
|
<lang order="54" code="cu">
|
||||||
|
Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic
|
||||||
|
</lang>
|
||||||
|
<lang order="55" code="cv">Chuvash</lang>
|
||||||
|
<lang order="56" code="kw">Cornish</lang>
|
||||||
|
<lang order="57" code="co">Corsican</lang>
|
||||||
|
<lang order="58" code="cr">Cree</lang>
|
||||||
|
<lang order="59" code="dv">
|
||||||
|
Divehi; Dhivehi; Maldivian
|
||||||
|
</lang>
|
||||||
|
<lang order="60" code="dz">Dzongkha</lang>
|
||||||
|
<lang order="61" code="eo">Esperanto</lang>
|
||||||
|
<lang order="62" code="ee">Ewe</lang>
|
||||||
|
<lang order="63" code="fo">Faroese</lang>
|
||||||
|
<lang order="64" code="fj">Fijian</lang>
|
||||||
|
<lang order="65" code="fy">Western Frisian</lang>
|
||||||
|
<lang order="66" code="ff">Fulah</lang>
|
||||||
|
<lang order="67" code="ka">Georgian</lang>
|
||||||
|
<lang order="68" code="gd">
|
||||||
|
Gaelic; Scottish Gaelic
|
||||||
|
</lang>
|
||||||
|
<lang order="69" code="gl">Galician</lang>
|
||||||
|
<lang order="70" code="gv">Manx</lang>
|
||||||
|
<lang order="71" code="gn">Guarani</lang>
|
||||||
|
<lang order="72" code="gu">Gujarati</lang>
|
||||||
|
<lang order="73" code="ht">
|
||||||
|
Haitian; Haitian Creole
|
||||||
|
</lang>
|
||||||
|
<lang order="74" code="ha">Hausa</lang>
|
||||||
|
<lang order="75" code="he">Hebrew</lang>
|
||||||
|
<lang order="76" code="hz">Herero</lang>
|
||||||
|
<lang order="77" code="hi">Hindi</lang>
|
||||||
|
<lang order="78" code="ho">Hiri Motu</lang>
|
||||||
|
<lang order="79" code="ig">Igbo</lang>
|
||||||
|
<lang order="80" code="is">Icelandic</lang>
|
||||||
|
<lang order="81" code="io">Ido</lang>
|
||||||
|
<lang order="82" code="ii">Sichuan Yi</lang>
|
||||||
|
<lang order="83" code="iu">Inuktitut</lang>
|
||||||
|
<lang order="84" code="ie">Interlingue</lang>
|
||||||
|
<lang order="85" code="ia">
|
||||||
|
Interlingua (International Auxiliary Language Association)
|
||||||
|
</lang>
|
||||||
|
<lang order="86" code="id">Indonesian</lang>
|
||||||
|
<lang order="87" code="ik">Inupiaq</lang>
|
||||||
|
<lang order="88" code="jv">Javanese</lang>
|
||||||
|
<lang order="89" code="ja">Japanese</lang>
|
||||||
|
<lang order="90" code="kl">
|
||||||
|
Kalaallisut; Greenlandic
|
||||||
|
</lang>
|
||||||
|
<lang order="91" code="kn">Kannada</lang>
|
||||||
|
<lang order="92" code="ks">Kashmiri</lang>
|
||||||
|
<lang order="93" code="kr">Kanuri</lang>
|
||||||
|
<lang order="94" code="kk">Kazakh</lang>
|
||||||
|
<lang order="95" code="km">Khmer</lang>
|
||||||
|
<lang order="96" code="ki">Kikuyu; Gikuyu</lang>
|
||||||
|
<lang order="97" code="rw">Kinyarwanda</lang>
|
||||||
|
<lang order="98" code="ky">Kirghiz</lang>
|
||||||
|
<lang order="99" code="kv">Komi</lang>
|
||||||
|
<lang order="100" code="kg">Kongo</lang>
|
||||||
|
<lang order="101" code="ko">Korean</lang>
|
||||||
|
<lang order="102" code="kj">Kuanyama; Kwanyama</lang>
|
||||||
|
<lang order="103" code="ku">Kurdish</lang>
|
||||||
|
<lang order="104" code="lo">Lao</lang>
|
||||||
|
<lang order="105" code="la">Latin</lang>
|
||||||
|
<lang order="106" code="li">
|
||||||
|
Limburgan; Limburger; Limburgish
|
||||||
|
</lang>
|
||||||
|
<lang order="107" code="ln">Lingala</lang>
|
||||||
|
<lang order="108" code="lb">
|
||||||
|
Luxembourgish; Letzeburgesch
|
||||||
|
</lang>
|
||||||
|
<lang order="109" code="lu">Luba-Katanga</lang>
|
||||||
|
<lang order="110" code="lg">Ganda</lang>
|
||||||
|
<lang order="111" code="mk">Macedonian</lang>
|
||||||
|
<lang order="112" code="mh">Marshallese</lang>
|
||||||
|
<lang order="113" code="ml">Malayalam</lang>
|
||||||
|
<lang order="114" code="mi">Maori</lang>
|
||||||
|
<lang order="115" code="mr">Marathi</lang>
|
||||||
|
<lang order="116" code="ms">Malay</lang>
|
||||||
|
<lang order="117" code="mg">Malagasy</lang>
|
||||||
|
<lang order="118" code="mo">Moldavian</lang>
|
||||||
|
<lang order="119" code="mn">Mongolian</lang>
|
||||||
|
<lang order="120" code="na">Nauru</lang>
|
||||||
|
<lang order="121" code="nv">Navajo; Navaho</lang>
|
||||||
|
<lang order="122" code="nr">
|
||||||
|
Ndebele, South; South Ndebele
|
||||||
|
</lang>
|
||||||
|
<lang order="123" code="nd">
|
||||||
|
Ndebele, North; North Ndebele
|
||||||
|
</lang>
|
||||||
|
<lang order="124" code="ng">Ndonga</lang>
|
||||||
|
<lang order="125" code="ne">Nepali</lang>
|
||||||
|
<lang order="126" code="nn">Norwegian Nynorsk</lang>
|
||||||
|
<lang order="127" code="nb">Norvégien Bokmål</lang>
|
||||||
|
<lang order="128" code="no">Norwegian</lang>
|
||||||
|
<lang order="129" code="ny">
|
||||||
|
Chichewa; Chewa; Nyanja
|
||||||
|
</lang>
|
||||||
|
<lang order="130" code="oc">
|
||||||
|
Occitan (post 1500); Provençal
|
||||||
|
</lang>
|
||||||
|
<lang order="131" code="oj">Ojibwa</lang>
|
||||||
|
<lang order="132" code="or">Oriya</lang>
|
||||||
|
<lang order="133" code="om">Oromo</lang>
|
||||||
|
<lang order="134" code="os">Ossetian; Ossetic</lang>
|
||||||
|
<lang order="135" code="pa">Panjabi; Punjabi</lang>
|
||||||
|
<lang order="136" code="fa">Persian</lang>
|
||||||
|
<lang order="137" code="pi">Pali</lang>
|
||||||
|
<lang order="138" code="ps">Pushto</lang>
|
||||||
|
<lang order="139" code="qu">Quechua</lang>
|
||||||
|
<lang order="140" code="rm">Raeto-Romance</lang>
|
||||||
|
<lang order="141" code="rn">Rundi</lang>
|
||||||
|
<lang order="142" code="ru">Russian</lang>
|
||||||
|
<lang order="143" code="sg">Sango</lang>
|
||||||
|
<lang order="144" code="sa">Sanskrit</lang>
|
||||||
|
<lang order="145" code="sr">Serbian</lang>
|
||||||
|
<lang order="146" code="si">Sinhala; Sinhalese</lang>
|
||||||
|
<lang order="147" code="se">Northern Sami</lang>
|
||||||
|
<lang order="148" code="sm">Samoan</lang>
|
||||||
|
<lang order="149" code="sn">Shona</lang>
|
||||||
|
<lang order="150" code="sd">Sindhi</lang>
|
||||||
|
<lang order="151" code="so">Somali</lang>
|
||||||
|
<lang order="152" code="st">Sotho, Southern</lang>
|
||||||
|
<lang order="153" code="sc">Sardinian</lang>
|
||||||
|
<lang order="154" code="ss">Swati</lang>
|
||||||
|
<lang order="155" code="su">Sundanese</lang>
|
||||||
|
<lang order="156" code="sw">Swahili</lang>
|
||||||
|
<lang order="157" code="ty">Tahitian</lang>
|
||||||
|
<lang order="158" code="ta">Tamil</lang>
|
||||||
|
<lang order="159" code="tt">Tatar</lang>
|
||||||
|
<lang order="160" code="te">Telugu</lang>
|
||||||
|
<lang order="161" code="tg">Tajik</lang>
|
||||||
|
<lang order="162" code="tl">Tagalog</lang>
|
||||||
|
<lang order="163" code="th">Thai</lang>
|
||||||
|
<lang order="164" code="bo">Tibetan</lang>
|
||||||
|
<lang order="165" code="ti">Tigrinya</lang>
|
||||||
|
<lang order="166" code="to">Tonga (Tonga Islands)</lang>
|
||||||
|
<lang order="167" code="tn">Tswana</lang>
|
||||||
|
<lang order="168" code="ts">Tsonga</lang>
|
||||||
|
<lang order="169" code="tk">Turkmen</lang>
|
||||||
|
<lang order="170" code="tr">Turkish</lang>
|
||||||
|
<lang order="171" code="tw">Twi</lang>
|
||||||
|
<lang order="172" code="ug">Uighur; Uyghur</lang>
|
||||||
|
<lang order="173" code="uk">Ukrainian</lang>
|
||||||
|
<lang order="174" code="ur">Urdu</lang>
|
||||||
|
<lang order="175" code="uz">Uzbek</lang>
|
||||||
|
<lang order="176" code="ve">Venda</lang>
|
||||||
|
<lang order="177" code="vi">Vietnamese</lang>
|
||||||
|
<lang order="178" code="vo">Volapük</lang>
|
||||||
|
<lang order="179" code="cy">Welsh</lang>
|
||||||
|
<lang order="180" code="wa">Walloon</lang>
|
||||||
|
<lang order="181" code="wo">Wolof</lang>
|
||||||
|
<lang order="182" code="xh">Xhosa</lang>
|
||||||
|
<lang order="183" code="yi">Yiddish</lang>
|
||||||
|
<lang order="184" code="yo">Yoruba</lang>
|
||||||
|
<lang order="185" code="za">Zhuang; Chuang</lang>
|
||||||
|
<lang order="186" code="zu">Zulu</lang>
|
||||||
|
</ISO_639-1_EU-Order>
|
||||||
|
</config>
|
||||||
|
</alfresco-config>
|
||||||
|
|
||||||
|
|
@@ -40,11 +40,23 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Multilingual specific service -->
|
<!-- Multilingual specific service -->
|
||||||
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
|
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
|
||||||
<property name="nodeService"><ref bean="NodeService" /></property>
|
<property name="nodeService">
|
||||||
<property name="searchService"><ref bean="SearchService" /></property>
|
<ref bean="NodeService" />
|
||||||
<property name="versionService"><ref bean="VersionService" /></property>
|
</property>
|
||||||
|
<property name="searchService">
|
||||||
|
<ref bean="SearchService" />
|
||||||
|
</property>
|
||||||
|
<property name="versionService">
|
||||||
|
<ref bean="VersionService" />
|
||||||
|
</property>
|
||||||
|
<property name="contentFilterLanguagesService">
|
||||||
|
<ref bean="ContentFilterLanguagesService" />
|
||||||
|
</property>
|
||||||
|
<property name="fileFolderService">
|
||||||
|
<ref bean="FileFolderService" />
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
<parameter name="expression"><value><![CDATA[(.*[\"\*\\\>\<\?\/\:\|\xA3\xAC\%\&\+\;]+.*)|(.*[\.]?.*[\.]+$)|(.*[ ]+$)]]></value></parameter>
|
<parameter name="expression"><value><![CDATA[(.*[\"\*\\\>\<\?\/\:\|\xA3\xAC\%\&\+\;]+.*)|(.*[\.]?.*[\.]+$)|(.*[ ]+$)]]></value></parameter>
|
||||||
<parameter name="requiresMatch"><value>false</value></parameter>
|
<parameter name="requiresMatch"><value>false</value></parameter>
|
||||||
</constraint>
|
</constraint>
|
||||||
<constraint name="cm:userNameConstraint" type="org.alfresco.repo.dictionary.constraint.UserNameConstraint" />
|
<constraint name="cm:userNameConstraint" type="org.alfresco.repo.dictionary.constraint.UserNameConstraint" />
|
||||||
</constraints>
|
</constraints>
|
||||||
|
|
||||||
<types>
|
<types>
|
||||||
@@ -143,12 +143,12 @@
|
|||||||
<title>Person</title>
|
<title>Person</title>
|
||||||
<parent>sys:base</parent>
|
<parent>sys:base</parent>
|
||||||
<properties>
|
<properties>
|
||||||
<!-- The tokenisation set here is ignored - it is fixed for this type -->
|
<!-- The tokenisation set here is ignored - it is fixed for this type -->
|
||||||
<!-- This is so you can not break person lookup -->
|
<!-- This is so you can not break person lookup -->
|
||||||
<property name="cm:userName">
|
<property name="cm:userName">
|
||||||
<type>d:text</type>
|
<type>d:text</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint ref="cm:userNameConstraint" />
|
<constraint ref="cm:userNameConstraint" />
|
||||||
</constraints>
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
@@ -260,6 +260,8 @@
|
|||||||
</associations>
|
</associations>
|
||||||
<mandatory-aspects>
|
<mandatory-aspects>
|
||||||
<aspect>cm:versionable</aspect>
|
<aspect>cm:versionable</aspect>
|
||||||
|
<aspect>cm:author</aspect>
|
||||||
|
<aspect>sys:localized</aspect>
|
||||||
</mandatory-aspects>
|
</mandatory-aspects>
|
||||||
</type>
|
</type>
|
||||||
|
|
||||||
@@ -572,7 +574,7 @@
|
|||||||
<protected>true</protected>
|
<protected>true</protected>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
</aspect>
|
</aspect>
|
||||||
|
|
||||||
<aspect name="cm:versionable">
|
<aspect name="cm:versionable">
|
||||||
@@ -723,6 +725,12 @@
|
|||||||
</mandatory-aspects>
|
</mandatory-aspects>
|
||||||
</aspect>
|
</aspect>
|
||||||
|
|
||||||
|
<aspect name="cm:mlEmptyTranslation">
|
||||||
|
<title>Empty Translation</title>
|
||||||
|
<mandatory-aspects>
|
||||||
|
<aspect>cm:mlDocument</aspect>
|
||||||
|
</mandatory-aspects>
|
||||||
|
</aspect>
|
||||||
</aspects>
|
</aspects>
|
||||||
|
|
||||||
</model>
|
</model>
|
||||||
|
@@ -67,6 +67,7 @@
|
|||||||
<list>
|
<list>
|
||||||
<idref local="NodeService_transaction"/>
|
<idref local="NodeService_transaction"/>
|
||||||
<idref local="AuditMethodInterceptor"/>
|
<idref local="AuditMethodInterceptor"/>
|
||||||
|
<idref local="mlTranslationInterceptor"/>
|
||||||
<idref local="exceptionTranslator"/>
|
<idref local="exceptionTranslator"/>
|
||||||
<idref bean="NodeService_security"/>
|
<idref bean="NodeService_security"/>
|
||||||
</list>
|
</list>
|
||||||
@@ -121,6 +122,10 @@
|
|||||||
|
|
||||||
<alias name="mimetypeService" alias="MimetypeService"/>
|
<alias name="mimetypeService" alias="MimetypeService"/>
|
||||||
|
|
||||||
|
<!-- Content Filter Languages Service -->
|
||||||
|
|
||||||
|
<alias name="contentFilterLanguagesService" alias="ContentFilterLanguagesService"/>
|
||||||
|
|
||||||
<!-- Search Service -->
|
<!-- Search Service -->
|
||||||
|
|
||||||
<bean id="SearchService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="SearchService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
@@ -655,6 +660,15 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="mlTranslationInterceptor" class="org.alfresco.repo.node.MLTranslationInterceptor">
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="nodeService"/>
|
||||||
|
</property>
|
||||||
|
<property name="multilingualContentService">
|
||||||
|
<ref bean="multilingualContentService"/>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="FileFolderService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
<bean id="FileFolderService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||||
<property name="transactionManager">
|
<property name="transactionManager">
|
||||||
<ref bean="transactionManager"/>
|
<ref bean="transactionManager"/>
|
||||||
@@ -723,13 +737,13 @@
|
|||||||
<!-- The AVMService -->
|
<!-- The AVMService -->
|
||||||
|
|
||||||
<bean id="avmService" class="org.alfresco.repo.avm.AVMServiceImpl">
|
<bean id="avmService" class="org.alfresco.repo.avm.AVMServiceImpl">
|
||||||
<property name="avmRepository">
|
<property name="avmRepository">
|
||||||
<ref bean="avmRepository"/>
|
<ref bean="avmRepository"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="transactionListener">
|
<property name="transactionListener">
|
||||||
<ref bean="lookupCacheListener"/>
|
<ref bean="lookupCacheListener"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="avmServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="avmServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
<property name="advice">
|
<property name="advice">
|
||||||
@@ -885,21 +899,21 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>compare</value>
|
<value>compare</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Write transaction advisor for sync service. -->
|
<!-- Write transaction advisor for sync service. -->
|
||||||
<bean id="avmSyncServiceWriteTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="avmSyncServiceWriteTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
<property name="advice">
|
<property name="advice">
|
||||||
<ref bean="retryingWriteTxnAdvice"/>
|
<ref bean="retryingWriteTxnAdvice"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>update</value>
|
<value>update</value>
|
||||||
<value>flatten</value>
|
<value>flatten</value>
|
||||||
<value>resetLayer</value>
|
<value>resetLayer</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
@@ -921,7 +935,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Attribute Service -->
|
<!-- Attribute Service -->
|
||||||
|
|
||||||
<!-- Read transaction advisor for attribute service. -->
|
<!-- Read transaction advisor for attribute service. -->
|
||||||
<bean id="attributeServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="attributeServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
@@ -930,25 +944,25 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>getAttributes</value>
|
<value>getAttributes</value>
|
||||||
<value>query</value>
|
<value>query</value>
|
||||||
<value>getKeys</value>
|
<value>getKeys</value>
|
||||||
<value>exists</value>
|
<value>exists</value>
|
||||||
<value>getCount</value>
|
<value>getCount</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Write transaction advisor for attribute service. -->
|
<!-- Write transaction advisor for attribute service. -->
|
||||||
<bean id="attributeServiceWriteTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="attributeServiceWriteTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
<property name="advice">
|
<property name="advice">
|
||||||
<ref bean="retryingWriteTxnAdvice"/>
|
<ref bean="retryingWriteTxnAdvice"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>setAttribute</value>
|
<value>setAttribute</value>
|
||||||
<value>removeAttribute</value>
|
<value>removeAttribute</value>
|
||||||
<value>addAttribute</value>
|
<value>addAttribute</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
@@ -970,13 +984,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Deployment Service. -->
|
<!-- Deployment Service. -->
|
||||||
|
|
||||||
<bean id="deploymentService" class="org.alfresco.repo.deploy.DeploymentServiceImpl">
|
<bean id="deploymentService" class="org.alfresco.repo.deploy.DeploymentServiceImpl">
|
||||||
<property name="avmService">
|
<property name="avmService">
|
||||||
<ref bean="indexingAVMService"/>
|
<ref bean="indexingAVMService"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<bean id="deploymentServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="deploymentServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
@@ -985,7 +999,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>deployDifference</value>
|
<value>deployDifference</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
@@ -1004,7 +1018,7 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="DeploymentService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="DeploymentService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
<property name="proxyInterfaces">
|
<property name="proxyInterfaces">
|
||||||
<list>
|
<list>
|
||||||
<value>org.alfresco.service.cmr.avm.deploy.DeploymentService</value>
|
<value>org.alfresco.service.cmr.avm.deploy.DeploymentService</value>
|
||||||
</list>
|
</list>
|
||||||
@@ -1020,7 +1034,7 @@
|
|||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
<!-- AVM Locking Service. -->
|
<!-- AVM Locking Service. -->
|
||||||
|
|
||||||
<bean id="avmLockingServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
<bean id="avmLockingServiceReadTxnAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
|
||||||
<property name="advice">
|
<property name="advice">
|
||||||
@@ -1028,9 +1042,9 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>getLock</value>
|
<value>getLock</value>
|
||||||
<value>getUserLocks</value>
|
<value>getUserLocks</value>
|
||||||
<value>getWebProjectLocks</value>
|
<value>getWebProjectLocks</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
@@ -1041,16 +1055,16 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="mappedNames">
|
<property name="mappedNames">
|
||||||
<list>
|
<list>
|
||||||
<value>addWebProject</value>
|
<value>addWebProject</value>
|
||||||
<value>lockPath</value>
|
<value>lockPath</value>
|
||||||
<value>removeLock</value>
|
<value>removeLock</value>
|
||||||
<value>removeWebProject</value>
|
<value>removeWebProject</value>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="AVMLockingService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="AVMLockingService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
<property name="proxyInterfaces">
|
<property name="proxyInterfaces">
|
||||||
<list>
|
<list>
|
||||||
<value>org.alfresco.service.cmr.avm.locking.AVMLockingService</value>
|
<value>org.alfresco.service.cmr.avm.locking.AVMLockingService</value>
|
||||||
</list>
|
</list>
|
||||||
@@ -1140,6 +1154,7 @@
|
|||||||
<list>
|
<list>
|
||||||
<idref local="MultilingualContentService_transaction"/>
|
<idref local="MultilingualContentService_transaction"/>
|
||||||
<idref local="exceptionTranslator"/>
|
<idref local="exceptionTranslator"/>
|
||||||
|
<idref bean="MultilingualContentService_security"/>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -61,7 +61,7 @@
|
|||||||
<property name="accessCache">
|
<property name="accessCache">
|
||||||
<ref bean="permissionsAccessCache" />
|
<ref bean="permissionsAccessCache" />
|
||||||
</property>
|
</property>
|
||||||
<property name="policyComponent">
|
<property name="policyComponent">
|
||||||
<ref bean="policyComponent" />
|
<ref bean="policyComponent" />
|
||||||
</property>
|
</property>
|
||||||
<!-- Dynamic authorites are evaluated in the context of a store/node etc -->
|
<!-- Dynamic authorites are evaluated in the context of a store/node etc -->
|
||||||
@@ -519,6 +519,32 @@
|
|||||||
|
|
||||||
<bean id="VersionService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
<bean id="VersionService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||||
|
|
||||||
|
<!-- =============================== -->
|
||||||
|
<!-- Multilingual Content Service -->
|
||||||
|
<!-- =============================== -->
|
||||||
|
|
||||||
|
<!-- The version service does not have any restrictions applied at the moment. It -->
|
||||||
|
<!-- does not use a node service that would apply any permissions. -->
|
||||||
|
|
||||||
|
<bean id="MultilingualContentService_security" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||||
|
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||||
|
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
|
||||||
|
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
|
||||||
|
<property name="objectDefinitionSource">
|
||||||
|
<value>
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.getTranslationContainer=ACL_NODE.0.sys:base.Read
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.getTranslations=ACL_NODE.0.sys:base.Read
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.getTranslationForLocale=ACL_NODE.0.sys:base.Read
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.getMissingTranslations=ACL_ALLOW
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.getPivotTranslation=ACL_NODE.0.sys:base.Read
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.makeTranslation=ACL_NODE.0.sys:base.Write
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.addTranslation=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.Write
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.addEmptyTranslation=ACL_NODE.0.sys:base.Read
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.createEdition=ACL_NODE.0.sys:base.Write
|
||||||
|
org.alfresco.service.cmr.ml.MultilingualContentService.renameWithMLExtension=ACL_NODE.0.sys:base.Write
|
||||||
|
</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
<!-- ============================== -->
|
<!-- ============================== -->
|
||||||
<!-- The Check-out/Check-in service -->
|
<!-- The Check-out/Check-in service -->
|
||||||
<!-- ============================== -->
|
<!-- ============================== -->
|
||||||
|
@@ -212,6 +212,7 @@ public interface ContentModel
|
|||||||
static final QName TYPE_MULTILINGUAL_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer");
|
static final QName TYPE_MULTILINGUAL_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer");
|
||||||
static final QName ASSOC_MULTILINGUAL_CHILD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlChild");
|
static final QName ASSOC_MULTILINGUAL_CHILD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlChild");
|
||||||
static final QName ASPECT_MULTILINGUAL_DOCUMENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlDocument");
|
static final QName ASPECT_MULTILINGUAL_DOCUMENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlDocument");
|
||||||
|
static final QName ASPECT_MULTILINGUAL_EMPTY_TRANSLATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlEmptyTranslation");
|
||||||
|
|
||||||
//
|
//
|
||||||
// User Model Definitions
|
// User Model Definitions
|
||||||
|
@@ -27,10 +27,13 @@ package org.alfresco.repo.content;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
|
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
|
||||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
|
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
|
||||||
@@ -47,6 +50,7 @@ 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.InvalidTypeException;
|
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
@@ -59,6 +63,7 @@ import org.alfresco.service.cmr.repository.NodeService;
|
|||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
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.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.EqualsHelper;
|
import org.alfresco.util.EqualsHelper;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
@@ -143,9 +148,9 @@ public class RoutingContentService implements ContentService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
{
|
{
|
||||||
this.policyComponent = policyComponent;
|
this.policyComponent = policyComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAvmService(AVMService service)
|
public void setAvmService(AVMService service)
|
||||||
{
|
{
|
||||||
@@ -162,23 +167,23 @@ public class RoutingContentService implements ContentService
|
|||||||
*/
|
*/
|
||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
// Bind on update properties behaviour
|
// Bind on update properties behaviour
|
||||||
this.policyComponent.bindClassBehaviour(
|
this.policyComponent.bindClassBehaviour(
|
||||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||||
this,
|
this,
|
||||||
new JavaBehaviour(this, "onUpdateProperties"));
|
new JavaBehaviour(this, "onUpdateProperties"));
|
||||||
|
|
||||||
// Register on content update policy
|
// Register on content update policy
|
||||||
this.onContentUpdateDelegate = this.policyComponent.registerClassPolicy(OnContentUpdatePolicy.class);
|
this.onContentUpdateDelegate = this.policyComponent.registerClassPolicy(OnContentUpdatePolicy.class);
|
||||||
this.onContentReadDelegate = this.policyComponent.registerClassPolicy(OnContentReadPolicy.class);
|
this.onContentReadDelegate = this.policyComponent.registerClassPolicy(OnContentReadPolicy.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update properties policy behaviour
|
* Update properties policy behaviour
|
||||||
*
|
*
|
||||||
* @param nodeRef the node reference
|
* @param nodeRef the node reference
|
||||||
* @param before the before values of the properties
|
* @param before the before values of the properties
|
||||||
* @param after the after values of the properties
|
* @param after the after values of the properties
|
||||||
*/
|
*/
|
||||||
public void onUpdateProperties(
|
public void onUpdateProperties(
|
||||||
NodeRef nodeRef,
|
NodeRef nodeRef,
|
||||||
@@ -293,8 +298,9 @@ public class RoutingContentService implements ContentService
|
|||||||
|
|
||||||
if (contentData == null)
|
if (contentData == null)
|
||||||
{
|
{
|
||||||
// if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY
|
|
||||||
PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName);
|
PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName);
|
||||||
|
|
||||||
|
// if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY
|
||||||
if (contentPropDef != null &&
|
if (contentPropDef != null &&
|
||||||
(!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) ||
|
(!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) ||
|
||||||
contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY))))
|
contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY))))
|
||||||
@@ -310,8 +316,66 @@ public class RoutingContentService implements ContentService
|
|||||||
// check that the URL is available
|
// check that the URL is available
|
||||||
if (contentData == null || contentData.getContentUrl() == null)
|
if (contentData == null || contentData.getContentUrl() == null)
|
||||||
{
|
{
|
||||||
// there is no URL - the interface specifies that this is not an error condition
|
// if the node is an empty translation, the reader must be the reader of its pivot translation
|
||||||
return null;
|
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT)
|
||||||
|
&& nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||||
|
{
|
||||||
|
// NOTE : don't use the MultilingualContentService here because :
|
||||||
|
// A valid SecureContext can't be provided in the RequestContext
|
||||||
|
|
||||||
|
List<ChildAssociationRef> parentAssocRefs = nodeService.getParentAssocs(
|
||||||
|
nodeRef,
|
||||||
|
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||||
|
RegexQNamePattern.MATCH_ALL);
|
||||||
|
|
||||||
|
if (parentAssocRefs.size() == 1)
|
||||||
|
{
|
||||||
|
// Get the ml container and its locale
|
||||||
|
NodeRef container = parentAssocRefs.get(0).getParentRef();
|
||||||
|
Locale containerLocale = (Locale) nodeService.getProperty(container, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
// Get each translation
|
||||||
|
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(
|
||||||
|
container,
|
||||||
|
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||||
|
RegexQNamePattern.MATCH_ALL);
|
||||||
|
|
||||||
|
|
||||||
|
// found the pivot translation
|
||||||
|
NodeRef pivot = null;
|
||||||
|
|
||||||
|
for(ChildAssociationRef assoc : assocRefs)
|
||||||
|
{
|
||||||
|
pivot = assoc.getChildRef();
|
||||||
|
Locale pivotLocale = (Locale) nodeService.getProperty(pivot, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
if(containerLocale.equals(pivotLocale))
|
||||||
|
{
|
||||||
|
break; // the pivot is set
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pivot = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the reader of this pivot translation if it's different to
|
||||||
|
// the node in parameter
|
||||||
|
|
||||||
|
if (pivot != null && !nodeRef.getId().equals(pivot.getId()))
|
||||||
|
{
|
||||||
|
return getReader(pivot, propertyQName, fireContentReadPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there is no URL - the interface specifies that this is not an error condition
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
String contentUrl = contentData.getContentUrl();
|
String contentUrl = contentData.getContentUrl();
|
||||||
|
|
||||||
|
119
source/java/org/alfresco/repo/model/filefolder/FolderType.java
Normal file
119
source/java/org/alfresco/repo/model/filefolder/FolderType.java
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.filefolder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
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.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing behaviour for the folder type.
|
||||||
|
*
|
||||||
|
* {@link ContentModel#TYPE_FOLDER folder type}
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class FolderType implements
|
||||||
|
NodeServicePolicies.BeforeDeleteNodePolicy
|
||||||
|
{
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the Folder type
|
||||||
|
*
|
||||||
|
* Ensures that the {@link ContentModel#TYPE_FOLDER} folder type
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.TYPE_FOLDER,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent the policy component to register behaviour with
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService the Node Service to set
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since the multilingual document don't keep their <b>mlDocument</b> aspect, the <b>mlEmptyTranslation<b>
|
||||||
|
* can't be archived and the deletion of a container doesn't call the right policies, the deletion of a
|
||||||
|
* folder must explicitly remove this aspect.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
List<ChildAssociationRef> childAssociations = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
|
||||||
|
|
||||||
|
for(ChildAssociationRef childAssoc : childAssociations)
|
||||||
|
{
|
||||||
|
NodeRef child = childAssoc.getChildRef();
|
||||||
|
|
||||||
|
if(nodeService.exists(child))
|
||||||
|
{
|
||||||
|
// Remove the mlDocument aspect of each multilingual node contained in the folder.
|
||||||
|
// The policies of this aspect perform the right logic.
|
||||||
|
if(nodeService.hasAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
nodeService.removeAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||||
|
}
|
||||||
|
// Recurse the process if needed
|
||||||
|
else if(nodeService.getType(child).equals(ContentModel.TYPE_FOLDER))
|
||||||
|
{
|
||||||
|
beforeDeleteNode(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.filefolder;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.model.ml.tools.AbstractMultilingualTestCases;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multilingual container type test cases
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.ml.MLContainerType
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class FolderTypeTest extends AbstractMultilingualTestCases {
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testRemoveSpace() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef trans2 = createContent();
|
||||||
|
NodeRef trans3 = createContent();
|
||||||
|
NodeRef empty;
|
||||||
|
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trans2, pivot, Locale.GERMAN);
|
||||||
|
multilingualContentService.addTranslation(trans3, pivot, Locale.ITALIAN);;
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "Empty_" + System.currentTimeMillis(), Locale.ENGLISH);
|
||||||
|
|
||||||
|
|
||||||
|
NodeRef space = fileFolderService.create(
|
||||||
|
nodeService.getPrimaryParent(pivot).getParentRef(),
|
||||||
|
"folder_" + System.currentTimeMillis(),
|
||||||
|
ContentModel.TYPE_FOLDER).getNodeRef();
|
||||||
|
|
||||||
|
nodeService.moveNode(pivot, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(pivot).getQName());
|
||||||
|
nodeService.moveNode(trans2, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(trans2).getQName());
|
||||||
|
nodeService.moveNode(trans3, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(trans3).getQName());
|
||||||
|
nodeService.moveNode(empty, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(empty).getQName());
|
||||||
|
|
||||||
|
// Ensure that the nodes are correctly moved
|
||||||
|
assertEquals("Move nodes failed", 4, nodeService.getChildAssocs(space).size());
|
||||||
|
|
||||||
|
// 1. Delete space
|
||||||
|
|
||||||
|
nodeService.deleteNode(space);
|
||||||
|
|
||||||
|
// Ensute that the space is deleted
|
||||||
|
assertFalse("The deletion of the space failed", nodeService.exists(space));
|
||||||
|
|
||||||
|
// Ensure that the nodes are archived
|
||||||
|
assertTrue("The space " + space + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||||
|
assertTrue("The node " + pivot + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||||
|
assertTrue("The node " + trans2 + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||||
|
assertTrue("The node " + trans3 + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||||
|
|
||||||
|
// Ensure that the mlContainer is deleted and not archived
|
||||||
|
assertFalse("The mlContainer " + mlContainer + " must be deleted", nodeService.exists(mlContainer));
|
||||||
|
assertFalse("The mlContainer " + mlContainer + " can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(mlContainer)));
|
||||||
|
|
||||||
|
// 2. Restore space
|
||||||
|
nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(space));
|
||||||
|
|
||||||
|
// Ensure that the nodes are restaured
|
||||||
|
assertFalse("The space " + space + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(space)));
|
||||||
|
assertFalse("The node " + pivot + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||||
|
assertFalse("The node " + trans2 + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||||
|
assertFalse("The node " + trans3 + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||||
|
|
||||||
|
// Ensure that the mlContainer is not restored
|
||||||
|
assertFalse("The mlContainer " + mlContainer + " must be deleted and can't be restored", nodeService.exists(mlContainer));
|
||||||
|
|
||||||
|
// 3. Delete space and remove it from the arhives
|
||||||
|
|
||||||
|
nodeService.deleteNode(space);
|
||||||
|
nodeService.deleteNode(nodeArchiveService.getArchivedNode(space));
|
||||||
|
|
||||||
|
assertFalse("The space " + space + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(space)));
|
||||||
|
assertFalse("The node " + pivot + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||||
|
assertFalse("The node " + trans2 + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||||
|
assertFalse("The node " + trans3 + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||||
|
|
||||||
|
assertFalse("The space " + space + "must be deleted", nodeService.exists(space));
|
||||||
|
assertFalse("The node " + pivot + "must be deleted", nodeService.exists(pivot));
|
||||||
|
assertFalse("The node " + trans2 + "must be deleted", nodeService.exists(trans2));
|
||||||
|
assertFalse("The node " + trans3 + "must be deleted", nodeService.exists(trans3));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.config.Config;
|
||||||
|
import org.alfresco.config.ConfigElement;
|
||||||
|
import org.alfresco.config.ConfigLookupContext;
|
||||||
|
import org.alfresco.config.ConfigService;
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a an implementation of the <b>Content Filter Languages Service</b>
|
||||||
|
*
|
||||||
|
* {@link org.alfresco.service.cmr.ml.ContentFilterLanguagesService Content Filter Languages Service}
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class ContentFilterLanguagesMap implements ContentFilterLanguagesService
|
||||||
|
{
|
||||||
|
private static final String CONFIG_AREA = "content-filter-lang";
|
||||||
|
|
||||||
|
private static final String CONFIG_CONDITION = "Languages Filter Map";
|
||||||
|
|
||||||
|
private static final String USED_STANDARD_CONFIG_CONDITION = "Standard In Use";
|
||||||
|
private static final String USED_STANDARD_ELEMENT = "standard";
|
||||||
|
|
||||||
|
private static final String DEFAULT_LANGUAGE_LIST_STANDARD = "ISO 639-1";
|
||||||
|
|
||||||
|
private static final String ATTR_CODE = "code";
|
||||||
|
private static final String ATTR_ORDER = "order";
|
||||||
|
private static final String ATTR_DEFAULT = "default";
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(ContentFilterLanguagesMap.class);
|
||||||
|
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
private List<String> orderedLangCodes;
|
||||||
|
private Map<String, String> languagesByCode;
|
||||||
|
|
||||||
|
private String defaultLanguage = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param configService the config service to use to read languages
|
||||||
|
*/
|
||||||
|
public ContentFilterLanguagesMap(ConfigService configService)
|
||||||
|
{
|
||||||
|
this.configService = configService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getFilterLanguages()
|
||||||
|
*/
|
||||||
|
public List<String> getFilterLanguages()
|
||||||
|
{
|
||||||
|
return orderedLangCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getMissingLanguages(java.util.List)
|
||||||
|
*/
|
||||||
|
public List<String> getMissingLanguages(List<String> availableLanguages)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(availableLanguages == null || availableLanguages.size() == 0)
|
||||||
|
{
|
||||||
|
return orderedLangCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> returnList = new ArrayList<String>(orderedLangCodes.size() - availableLanguages.size());
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for(String lang : orderedLangCodes)
|
||||||
|
{
|
||||||
|
if(!availableLanguages.contains(lang))
|
||||||
|
{
|
||||||
|
returnList.add(index, lang);
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getLabelByCode(java.lang.String)
|
||||||
|
*/
|
||||||
|
public String getLabelByCode(String code)
|
||||||
|
{
|
||||||
|
// get the translated language label
|
||||||
|
String label;
|
||||||
|
|
||||||
|
label = I18NUtil.getMessage(MESSAGE_PREFIX + code);
|
||||||
|
|
||||||
|
// if not found, get the default name (found in content-filter-lang.xml)
|
||||||
|
if(label == null || label.length() == 0)
|
||||||
|
{
|
||||||
|
label = languagesByCode.get(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not found, return the language code
|
||||||
|
if(label == null || label.length() == 0)
|
||||||
|
{
|
||||||
|
label = code + " (label not found)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getOrderByCode(java.lang.String)
|
||||||
|
*/
|
||||||
|
public int getOrderByCode(String code)
|
||||||
|
{
|
||||||
|
if (orderedLangCodes.contains(code))
|
||||||
|
{
|
||||||
|
return orderedLangCodes.indexOf(code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Language code not found : " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultLanguage()
|
||||||
|
{
|
||||||
|
return this.defaultLanguage ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the map using the configuration service provided
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
ConfigLookupContext clContext = new ConfigLookupContext(CONFIG_AREA);
|
||||||
|
|
||||||
|
// get which standart is defined by the user (ISO 639-1 by default)
|
||||||
|
String standard = DEFAULT_LANGUAGE_LIST_STANDARD;
|
||||||
|
|
||||||
|
Config configStandard = configService.getConfig(USED_STANDARD_CONFIG_CONDITION, clContext);
|
||||||
|
|
||||||
|
if(configStandard != null
|
||||||
|
&& configStandard.getConfigElement(USED_STANDARD_ELEMENT) != null)
|
||||||
|
{
|
||||||
|
standard = configStandard.getConfigElement(USED_STANDARD_ELEMENT).getValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("No standard configured, use by default : " + DEFAULT_LANGUAGE_LIST_STANDARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Config configConditions = configService.getConfig(CONFIG_CONDITION, clContext);
|
||||||
|
Map<String, ConfigElement> configElements = configConditions.getConfigElements();
|
||||||
|
|
||||||
|
ConfigElement configLanguages = null;
|
||||||
|
|
||||||
|
// get the list of languages of the matched standard
|
||||||
|
if(configElements.containsKey(standard))
|
||||||
|
{
|
||||||
|
configLanguages = configElements.get(standard);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the santard is not matched, get the first list
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configLanguages = configElements.values().iterator().next();
|
||||||
|
logger.warn("Ignoring prefered standard doesn't found, choose : " + configLanguages.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ConfigElement> languages = configLanguages.getChildren();
|
||||||
|
|
||||||
|
// get the size of the lists
|
||||||
|
int listSize = languages.size();
|
||||||
|
this.orderedLangCodes = new ArrayList<String>(listSize);
|
||||||
|
this.languagesByCode = new HashMap<String, String>(listSize);
|
||||||
|
|
||||||
|
// construct the languages map and list
|
||||||
|
for (ConfigElement langElem : languages)
|
||||||
|
{
|
||||||
|
String code = convertToOldISOCode(langElem.getAttribute(ATTR_CODE));
|
||||||
|
String order = langElem.getAttribute(ATTR_ORDER);
|
||||||
|
String value = langElem.getValue();
|
||||||
|
String def = langElem.getAttribute(ATTR_DEFAULT);
|
||||||
|
|
||||||
|
orderedLangCodes.add(Integer.parseInt(order) - 1, code);
|
||||||
|
|
||||||
|
languagesByCode.put(code, value);
|
||||||
|
|
||||||
|
if(def != null && Boolean.parseBoolean(def))
|
||||||
|
{
|
||||||
|
if(defaultLanguage != null)
|
||||||
|
{
|
||||||
|
logger.warn("Ignoring default attribute is not unique le last matched will be used");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.defaultLanguage = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the collections read-only
|
||||||
|
this.orderedLangCodes = Collections.unmodifiableList(this.orderedLangCodes);
|
||||||
|
this.languagesByCode = Collections.unmodifiableMap(this.languagesByCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#convertToOldISOCode(java.lang.String)
|
||||||
|
*/
|
||||||
|
public String convertToOldISOCode(String code)
|
||||||
|
{
|
||||||
|
if(code.equalsIgnoreCase("he"))
|
||||||
|
code = "iw";
|
||||||
|
else if(code.equalsIgnoreCase("id"))
|
||||||
|
code = "in";
|
||||||
|
else if(code.equalsIgnoreCase("yi"))
|
||||||
|
code = "ji";
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#convertToNewISOCode(java.lang.String)
|
||||||
|
*/
|
||||||
|
public String convertToNewISOCode(String code) {
|
||||||
|
|
||||||
|
if(code.equalsIgnoreCase("iw"))
|
||||||
|
code = "he";
|
||||||
|
else if(code.equalsIgnoreCase("in"))
|
||||||
|
code = "id";
|
||||||
|
else if(code.equalsIgnoreCase("ji"))
|
||||||
|
code = "yi";
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.ContentServicePolicies;
|
||||||
|
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.policy.PolicyScope;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
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.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing behaviour for the multilingual empty translation aspect.
|
||||||
|
* An empty translation is a document's properties translation. This kind of node
|
||||||
|
* doesn't have a content.
|
||||||
|
*
|
||||||
|
* {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class EmptyTranslationAspect implements
|
||||||
|
CopyServicePolicies.OnCopyNodePolicy,
|
||||||
|
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||||
|
NodeServicePolicies.OnRemoveAspectPolicy,
|
||||||
|
ContentServicePolicies.OnContentUpdatePolicy
|
||||||
|
{
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the Multilingual Empty Translation Aspect
|
||||||
|
* <p>
|
||||||
|
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||||
|
new JavaBehaviour(this, "onCopyNode"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onContentUpdate"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||||
|
new JavaBehaviour(this, "onContentUpdate"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||||
|
new JavaBehaviour(this, "onRemoveAspect"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent the policy component to register behaviour with
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService the Node Service to set
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a <b>cm:mlEmptyTranslation<b> is not permit.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.StoreRef, boolean, org.alfresco.repo.policy.PolicyScope)
|
||||||
|
*/
|
||||||
|
public void onCopyNode(QName classRef, NodeRef sourceNodeRef, StoreRef destinationStoreRef, boolean copyToNewNode, PolicyScope copyDetails)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("It's impossible to copy an empty translation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a content is added to a <b>cm:mlEmptyTranslation<b>, remove this aspect.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy#onContentUpdate(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||||
|
*/
|
||||||
|
public void onContentUpdate(NodeRef nodeRef, boolean newContent)
|
||||||
|
{
|
||||||
|
if(newContent)
|
||||||
|
{
|
||||||
|
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a <b>cm:mlEmptyTranslation<b> is deleted, it can't be archived.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// add TEMPORARY ASPECT to force the deleteNode
|
||||||
|
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the aspect <b>cm:mlEmptyTranslation<b> is removed <b>and the content url property is null</b>, the node can't be store much time.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) *
|
||||||
|
*/
|
||||||
|
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
// if the node is updated, the URL will not be null and the rome aspect don't delete
|
||||||
|
// the translation. It will be a simple mlDocument.
|
||||||
|
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)
|
||||||
|
&& ((ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT)).getContentUrl() == null)
|
||||||
|
{
|
||||||
|
// add TEMPORARY ASPECT to force the deleteNode
|
||||||
|
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||||
|
nodeService.deleteNode(nodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
172
source/java/org/alfresco/repo/model/ml/MLContainerType.java
Normal file
172
source/java/org/alfresco/repo/model/ml/MLContainerType.java
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing behaviour for the multilingual multilingual container type.
|
||||||
|
* A multilingual container type is fonctionally named '<b>Logical Document</b>'.
|
||||||
|
* It links each translation of a semantical message together
|
||||||
|
*
|
||||||
|
* {@link ContentModel#TYPE_MULTILINGUAL_CONTAINER multilingual container type}
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MLContainerType implements
|
||||||
|
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||||
|
NodeServicePolicies.OnUpdatePropertiesPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* set a property with this QName when the deletion process is running on the mlContainer. In this case
|
||||||
|
* the policies of the remove aspect of mlDocument don't delete one more time the mlContainer.
|
||||||
|
*/
|
||||||
|
/*package*/ static QName PROP_NAME_DELETION_RUNNING = QName.createQName("__MLContanier_", "Deletion_Running");
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
private MultilingualContentService multilingualContentService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the Multilingual Container Type
|
||||||
|
* <p>
|
||||||
|
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||||
|
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
|
||||||
|
new JavaBehaviour(this, "onUpdateProperties"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent the policy component to register behaviour with
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param multilingualContentService the Multilingual Content Service to set
|
||||||
|
*/
|
||||||
|
public void setMultilingualContentService(
|
||||||
|
MultilingualContentService multilingualContentService)
|
||||||
|
{
|
||||||
|
this.multilingualContentService = multilingualContentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService the Node Service to set
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a <b>cm:mlContainer<b> is deleted, it can't be archived.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(nodeRef);
|
||||||
|
|
||||||
|
// add the DELETION_RUNNING property
|
||||||
|
nodeService.setProperty(nodeRef, PROP_NAME_DELETION_RUNNING, new Boolean(true));
|
||||||
|
|
||||||
|
for(Map.Entry<Locale, NodeRef> entry : translations.entrySet())
|
||||||
|
{
|
||||||
|
nodeService.removeAspect(entry.getValue(), ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the DELETION_RUNNING property
|
||||||
|
Map<QName, Serializable> prop = nodeService.getProperties(nodeRef);
|
||||||
|
prop.remove(PROP_NAME_DELETION_RUNNING);
|
||||||
|
nodeService.setProperties(nodeRef, prop);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property <b>locale</b> of a <b>cm:mlContainer</b> represents the locale of the pivot translation.
|
||||||
|
*
|
||||||
|
* Since the pivot must be an existing translation and the pivot can t be empty, some tests must be performed when
|
||||||
|
* the locale of the mlContainer is updated.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map)
|
||||||
|
*/
|
||||||
|
public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||||
|
{
|
||||||
|
Locale localeAfter = (Locale) after.get(ContentModel.PROP_LOCALE);
|
||||||
|
Locale localeBefore = (Locale) before.get(ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
// The locale can be set as null if the container have no children.
|
||||||
|
// Normaly, it's ONLY the case at the creation of the container.
|
||||||
|
if(localeAfter == null && nodeService.getChildAssocs(nodeRef).size() != 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("A Locale property must be defined for a Multilingual Container and can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(localeAfter != null && !localeAfter.equals(localeBefore))
|
||||||
|
{
|
||||||
|
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(nodeRef);
|
||||||
|
|
||||||
|
//get the new pivot translation
|
||||||
|
NodeRef pivot = translations.get(localeAfter);
|
||||||
|
|
||||||
|
if(pivot == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("The pivot translation must be an existing translation");
|
||||||
|
}
|
||||||
|
else if(nodeService.hasAspect(pivot, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("The pivot translation can't be an empty translation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -24,6 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.model.ml;
|
package org.alfresco.repo.model.ml;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -33,8 +35,12 @@ import java.util.Set;
|
|||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.i18n.I18NUtil;
|
import org.alfresco.i18n.I18NUtil;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.version.VersionModel;
|
||||||
|
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
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.repository.StoreRef;
|
||||||
@@ -55,6 +61,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @author Philippe Dubois
|
* @author Philippe Dubois
|
||||||
|
* @author yanipig
|
||||||
*/
|
*/
|
||||||
public class MultilingualContentServiceImpl implements MultilingualContentService
|
public class MultilingualContentServiceImpl implements MultilingualContentService
|
||||||
{
|
{
|
||||||
@@ -64,6 +71,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
private SearchService searchService;
|
private SearchService searchService;
|
||||||
private VersionService versionService;
|
private VersionService versionService;
|
||||||
private SearchParameters searchParametersMLRoot;
|
private SearchParameters searchParametersMLRoot;
|
||||||
|
private ContentFilterLanguagesService contentFilterLanguagesService;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
|
||||||
public MultilingualContentServiceImpl()
|
public MultilingualContentServiceImpl()
|
||||||
{
|
{
|
||||||
@@ -74,26 +83,6 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
searchParametersMLRoot.setQuery("/cm:multilingualRoot");
|
searchParametersMLRoot.setQuery("/cm:multilingualRoot");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
|
||||||
{
|
|
||||||
this.nodeService = nodeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSearchService(SearchService searchService)
|
|
||||||
{
|
|
||||||
this.searchService = searchService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVersionService(VersionService versionService)
|
|
||||||
{
|
|
||||||
this.versionService = versionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renameWithMLExtension(NodeRef translationNodeRef)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns a reference to the node that will hold all the <b>cm:mlContainer</b> nodes.
|
* @return Returns a reference to the node that will hold all the <b>cm:mlContainer</b> nodes.
|
||||||
*/
|
*/
|
||||||
@@ -231,6 +220,9 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
{
|
{
|
||||||
// Make one
|
// Make one
|
||||||
mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef, true);
|
mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef, true);
|
||||||
|
|
||||||
|
// set the pivot language
|
||||||
|
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, locale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -248,6 +240,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||||
QNAME_ML_TRANSLATION);
|
QNAME_ML_TRANSLATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return mlContainerNodeRef;
|
return mlContainerNodeRef;
|
||||||
}
|
}
|
||||||
@@ -307,7 +300,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
public void createEdition( NodeRef translationNodeRef)
|
public void createEdition( NodeRef translationNodeRef)
|
||||||
{
|
{
|
||||||
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationNodeRef, false);
|
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationNodeRef, false);
|
||||||
// Ensure that the translation given is one of the children
|
// Ensure that the translation given is one of the children
|
||||||
getOrCreateMLContainer(translationNodeRef, false);
|
getOrCreateMLContainer(translationNodeRef, false);
|
||||||
// Get all the container's children
|
// Get all the container's children
|
||||||
@@ -315,8 +308,25 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
mlContainerNodeRef,
|
mlContainerNodeRef,
|
||||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||||
RegexQNamePattern.MATCH_ALL);
|
RegexQNamePattern.MATCH_ALL);
|
||||||
// Version the container and all its children
|
|
||||||
versionService.createVersion(mlContainerNodeRef, null, true);
|
|
||||||
|
// Get and store the translation verions associated to the mlContainer
|
||||||
|
List<Version> versions = new ArrayList<Version>(childAssocRefs.size());
|
||||||
|
|
||||||
|
for (ChildAssociationRef childAssoc : childAssocRefs)
|
||||||
|
{
|
||||||
|
versions.add(versionService.getCurrentVersion(childAssoc.getChildRef()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Serializable> editionProperties = new HashMap<String, Serializable>();
|
||||||
|
editionProperties.put(
|
||||||
|
VersionModel.PROP_QNAME_TRANSLATION_VERIONS.toString(),
|
||||||
|
(Serializable) versions
|
||||||
|
);
|
||||||
|
|
||||||
|
// Version the container and all its children
|
||||||
|
versionService.createVersion(mlContainerNodeRef, editionProperties, true);
|
||||||
|
|
||||||
// Remove all the child documents apart from the given node
|
// Remove all the child documents apart from the given node
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (ChildAssociationRef childAssoc : childAssocRefs)
|
for (ChildAssociationRef childAssoc : childAssocRefs)
|
||||||
@@ -416,4 +426,173 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
|||||||
}
|
}
|
||||||
return nearestNodeRef;
|
return nearestNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
public List<Locale> getMissingTranslations(NodeRef localizedNodeRef, boolean addThisNodeLocale)
|
||||||
|
{
|
||||||
|
List<Locale> foundLocales = new ArrayList<Locale>(getTranslations(localizedNodeRef).keySet());
|
||||||
|
List<String> foundLanguages = new ArrayList<String>();
|
||||||
|
|
||||||
|
|
||||||
|
// transform locales into languages codes
|
||||||
|
for(Locale locale : foundLocales)
|
||||||
|
{
|
||||||
|
foundLanguages.add(locale.getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the locale of the given node if required
|
||||||
|
if(addThisNodeLocale)
|
||||||
|
{
|
||||||
|
Locale localeNode = (Locale) nodeService.getProperty(localizedNodeRef, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
if(localeNode != null)
|
||||||
|
{
|
||||||
|
foundLanguages.remove(localeNode.toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("No locale found for the node " + localizedNodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> missingLanguages = null;
|
||||||
|
|
||||||
|
if(foundLanguages.size() == 0)
|
||||||
|
{
|
||||||
|
// The given node is the only one available translation and it must
|
||||||
|
// be return.
|
||||||
|
// MissingLanguages become the entire list pf languages.
|
||||||
|
missingLanguages = contentFilterLanguagesService.getFilterLanguages();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get the missing languages form the list of content filter languages
|
||||||
|
missingLanguages = contentFilterLanguagesService.getMissingLanguages(foundLanguages);
|
||||||
|
}
|
||||||
|
// construct a list of locales
|
||||||
|
List<Locale> missingLocales = new ArrayList<Locale>(missingLanguages.size() + 1);
|
||||||
|
|
||||||
|
for(String lang : missingLanguages)
|
||||||
|
{
|
||||||
|
missingLocales.add(I18NUtil.parseLocale(lang));
|
||||||
|
}
|
||||||
|
|
||||||
|
return missingLocales;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
public NodeRef getPivotTranslation(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
NodeRef container = getTranslationContainer(nodeRef);
|
||||||
|
Locale containerLocale = (Locale) nodeService.getProperty(container, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
return getTranslationForLocale(nodeRef, containerLocale);
|
||||||
|
}
|
||||||
|
else if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(nodeRef)))
|
||||||
|
{
|
||||||
|
Locale containerLocale = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
return getTranslationForLocale(getTranslations(nodeRef).get(containerLocale), containerLocale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("The node is not multilingual " + nodeRef);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc */
|
||||||
|
public NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale)
|
||||||
|
{
|
||||||
|
// any node used as reference
|
||||||
|
NodeRef anyTranslation;
|
||||||
|
// the empty document to create
|
||||||
|
NodeRef newTranslationNodeRef = null;
|
||||||
|
|
||||||
|
QName typeQName = nodeService.getType(translationOfNodeRef);
|
||||||
|
if (typeQName.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
|
||||||
|
{
|
||||||
|
// Set the ml container ans get the pivot
|
||||||
|
anyTranslation = getPivotTranslation(translationOfNodeRef);
|
||||||
|
}
|
||||||
|
else if(nodeService.hasAspect(translationOfNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
anyTranslation = translationOfNodeRef;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Node must have aspect " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " applied or be a " + ContentModel.TYPE_MULTILINGUAL_CONTAINER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the document in the space of the node of reference
|
||||||
|
NodeRef parentNodeRef = nodeService.getPrimaryParent(anyTranslation).getParentRef();
|
||||||
|
|
||||||
|
newTranslationNodeRef = fileFolderService.create(
|
||||||
|
parentNodeRef,
|
||||||
|
name,
|
||||||
|
ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
|
||||||
|
// add the translation to the container
|
||||||
|
addTranslation(newTranslationNodeRef, translationOfNodeRef, locale);
|
||||||
|
|
||||||
|
// set it empty
|
||||||
|
nodeService.addAspect(newTranslationNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION, null);
|
||||||
|
|
||||||
|
// get the extension and set the ContentData property with an null URL.
|
||||||
|
String extension = "";
|
||||||
|
int dotIdx;
|
||||||
|
if((dotIdx = name.lastIndexOf(".")) > -1 )
|
||||||
|
{
|
||||||
|
extension = name.substring(dotIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeService.setProperty(newTranslationNodeRef, ContentModel.PROP_CONTENT,
|
||||||
|
new ContentData(null, extension, 0, "UTF-8", locale));
|
||||||
|
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Added an empty translation: \n" +
|
||||||
|
" Translation of: " + translationOfNodeRef + " of type " + typeQName + "\n" +
|
||||||
|
" New translation: " + newTranslationNodeRef + "\n" +
|
||||||
|
" Locale: " + locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTranslationNodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchService(SearchService searchService)
|
||||||
|
{
|
||||||
|
this.searchService = searchService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersionService(VersionService versionService)
|
||||||
|
{
|
||||||
|
this.versionService = versionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
|
||||||
|
{
|
||||||
|
this.contentFilterLanguagesService = contentFilterLanguagesService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileFolderService(FileFolderService fileFolderService)
|
||||||
|
{
|
||||||
|
this.fileFolderService = fileFolderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renameWithMLExtension(NodeRef translationNodeRef)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.policy.PolicyScope;
|
||||||
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
|
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.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing behaviour for the multilingual document aspect.
|
||||||
|
*
|
||||||
|
* {@link ContentModel#ASPECT_MULTILINGUAL_DOCUMENT ml document aspect}
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MultilingualDocumentAspect implements
|
||||||
|
CopyServicePolicies.OnCopyNodePolicy,
|
||||||
|
CopyServicePolicies.OnCopyCompletePolicy,
|
||||||
|
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||||
|
NodeServicePolicies.BeforeRemoveAspectPolicy,
|
||||||
|
NodeServicePolicies.OnRemoveAspectPolicy,
|
||||||
|
NodeServicePolicies.OnUpdatePropertiesPolicy
|
||||||
|
{
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
|
||||||
|
private MultilingualContentService multilingualContentService;
|
||||||
|
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the Multilingual Aspect
|
||||||
|
*
|
||||||
|
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_DOCUMENT ml document aspect}
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "onCopyNode"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeRemoveAspect"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "beforeRemoveAspect"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "onUpdateProperties"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "onCopyComplete"));
|
||||||
|
|
||||||
|
this.policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"),
|
||||||
|
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||||
|
new JavaBehaviour(this, "onRemoveAspect"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent the policy component to register behaviour with
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param multilingualContentService the Multilingual Content Service to set
|
||||||
|
*/
|
||||||
|
public void setMultilingualContentService(
|
||||||
|
MultilingualContentService multilingualContentService)
|
||||||
|
{
|
||||||
|
this.multilingualContentService = multilingualContentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService the Node Service to set
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The copy of a <b>cm:mlDocument</b> can't keep the Multilingual aspect.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.StoreRef, boolean, org.alfresco.repo.policy.PolicyScope)
|
||||||
|
*/
|
||||||
|
public void onCopyNode(QName classRef, NodeRef sourceNodeRef, StoreRef destinationStoreRef, boolean copyToNewNode, PolicyScope copyDetails)
|
||||||
|
{
|
||||||
|
copyDetails.removeAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The copy of <b>mlDocument</b> don't keep the 'locale' property.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy#onCopyComplete(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, boolean, java.util.Map)
|
||||||
|
*/
|
||||||
|
public void onCopyComplete(QName classRef, NodeRef sourceNodeRef, NodeRef destinationRef, boolean copyToNewNode, Map<NodeRef, NodeRef> copyMap)
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> copiedProp = nodeService.getProperties(destinationRef);
|
||||||
|
copiedProp.remove(ContentModel.PROP_LOCALE);
|
||||||
|
nodeService.setProperties(destinationRef, copiedProp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A <b>cm:mlDocument</b> is pivot translation it is a multilingual document (non empty) if it's language matches the language
|
||||||
|
* of its <b>cm:mlDocument</b>. And a pivot translation can't be removed if it's not the last translation of the <b>cm:mlContainer</b>.
|
||||||
|
*
|
||||||
|
* If a translation is deleted, it's multilingual aspect is lost.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a pivot translation is deleted, it's <b>cm:mlContainer is deleted too.</b>
|
||||||
|
*
|
||||||
|
* <i>Note: When the pivot translation and the mlContainer are deleted, the mlDocument apsect is removed from
|
||||||
|
* the other translations. It will be better to don't allow the deletion of the pivot if other translation is
|
||||||
|
* available at the client side level.</i>
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeRemoveAspectPolicy#beforeRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||||
|
*/
|
||||||
|
public void beforeRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
NodeRef mlContainer = multilingualContentService.getTranslationContainer(nodeRef);
|
||||||
|
|
||||||
|
// nothing to do if the mlContainer is in a deletion process
|
||||||
|
Boolean inDeleteProcess = (Boolean) nodeService.getProperty(mlContainer, MLContainerType.PROP_NAME_DELETION_RUNNING);
|
||||||
|
if(inDeleteProcess != null && inDeleteProcess == true)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Locale mlContainerLocale = (Locale) nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE);
|
||||||
|
Locale nodeRefLocale = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
nodeService.removeChild(mlContainer, nodeRef);
|
||||||
|
|
||||||
|
// if last translation or if nodeRef is pivot translation
|
||||||
|
if(multilingualContentService.getTranslations(mlContainer).size() == 0
|
||||||
|
|| mlContainerLocale.equals(nodeRefLocale))
|
||||||
|
{
|
||||||
|
// delete the mlContainer
|
||||||
|
nodeService.deleteNode(mlContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After removing the <b>cm:mlDocument</b> aspect :
|
||||||
|
* - the node is removed is it's a <b>cm:mlEmptyTranslation</b>
|
||||||
|
* - if not, only the locale property is removed
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||||
|
*/
|
||||||
|
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||||
|
{
|
||||||
|
// note: if the node has the temporary aspect and the mlEmptyTranslation in a same
|
||||||
|
// time, it means that the node is being deleted by another process...
|
||||||
|
if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY))
|
||||||
|
{
|
||||||
|
nodeService.deleteNode(nodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||||
|
props.remove(ContentModel.PROP_LOCALE);
|
||||||
|
nodeService.setProperties(nodeRef, props);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the locale is unique inside the <b>mlContainer</b>.
|
||||||
|
*
|
||||||
|
* If the locale of a pivot translation is modified, the pivot locale reference of the mlContainer
|
||||||
|
* must be modified too.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map)
|
||||||
|
*/
|
||||||
|
public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||||
|
{
|
||||||
|
Locale localeBefore = (Locale) before.get(ContentModel.PROP_LOCALE);
|
||||||
|
Locale localeAfter;
|
||||||
|
|
||||||
|
// the after local property type can be either Locale or String
|
||||||
|
Serializable objLocaleAfter = after.get(ContentModel.PROP_LOCALE);
|
||||||
|
if (objLocaleAfter instanceof Locale )
|
||||||
|
{
|
||||||
|
localeAfter = (Locale) objLocaleAfter;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localeAfter = I18NUtil.parseLocale(objLocaleAfter.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the local has been modified
|
||||||
|
if(!localeBefore.equals(localeAfter))
|
||||||
|
{
|
||||||
|
NodeRef mlContainer = multilingualContentService.getTranslationContainer(nodeRef);
|
||||||
|
|
||||||
|
// Since the map returned by the getTranslations doesn't duplicate keys, the size of this map will be
|
||||||
|
// different of the size of the number of children of the mlContainer if a duplicate locale is found.
|
||||||
|
int transSize = multilingualContentService.getTranslations(mlContainer).size();
|
||||||
|
int childSize = nodeService.getChildAssocs(mlContainer, ContentModel.ASSOC_MULTILINGUAL_CHILD, RegexQNamePattern.MATCH_ALL).size();
|
||||||
|
|
||||||
|
// if duplicate locale found
|
||||||
|
if(transSize != childSize)
|
||||||
|
{
|
||||||
|
// throw an exception and the current transaction will be rolled back. The properties will not be
|
||||||
|
// longer in an illegal state.
|
||||||
|
throw new IllegalArgumentException("The locale " + localeAfter +
|
||||||
|
" can't be changed for the node " + nodeRef +
|
||||||
|
" because this locale is already in use in an other translation of the same " +
|
||||||
|
ContentModel.TYPE_MULTILINGUAL_CONTAINER + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the locale of ML Container
|
||||||
|
Locale localMlContainer = (Locale) nodeService.getProperty(
|
||||||
|
mlContainer,
|
||||||
|
ContentModel.PROP_LOCALE);
|
||||||
|
|
||||||
|
// if locale of the container is equals to the locale of
|
||||||
|
// the node (before update). The nodeRef is the pivot language
|
||||||
|
// and the locale of the mlContainer must be modified
|
||||||
|
if(localeBefore.equals(localMlContainer))
|
||||||
|
{
|
||||||
|
nodeService.setProperty(
|
||||||
|
mlContainer,
|
||||||
|
ContentModel.PROP_LOCALE,
|
||||||
|
localeAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// else no action to perform
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.alfresco.repo.model.filefolder.FolderTypeTest;
|
||||||
|
import org.alfresco.repo.model.ml.tools.ContentFilterLanguagesMapTest;
|
||||||
|
import org.alfresco.repo.model.ml.tools.EmptyTranslationAspectTest;
|
||||||
|
import org.alfresco.repo.model.ml.tools.MLContainerTypeTest;
|
||||||
|
import org.alfresco.repo.model.ml.tools.MultilingualContentServiceImplTest;
|
||||||
|
import org.alfresco.repo.model.ml.tools.MultilingualDocumentAspectTest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multilingual test suite
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MultilingualTestSuite extends TestSuite
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates the test suite
|
||||||
|
*
|
||||||
|
* @return the test suite
|
||||||
|
*/
|
||||||
|
public static Test suite()
|
||||||
|
{
|
||||||
|
TestSuite suite = new TestSuite();
|
||||||
|
|
||||||
|
suite.addTestSuite(EmptyTranslationAspectTest.class);
|
||||||
|
suite.addTestSuite(ContentFilterLanguagesMapTest.class);
|
||||||
|
suite.addTestSuite(MultilingualContentServiceImplTest.class);
|
||||||
|
suite.addTestSuite(MultilingualDocumentAspectTest.class);
|
||||||
|
suite.addTestSuite(MLContainerTypeTest.class);
|
||||||
|
suite.addTestSuite(FolderTypeTest.class);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml.tools;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
|
import org.alfresco.repo.transaction.TransactionUtil;
|
||||||
|
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||||
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
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.VersionService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base multilingual test cases
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMultilingualTestCases extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
protected static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||||
|
|
||||||
|
protected ServiceRegistry serviceRegistry;
|
||||||
|
protected AuthenticationComponent authenticationComponent;
|
||||||
|
protected TransactionService transactionService;
|
||||||
|
protected NodeService nodeService;
|
||||||
|
protected FileFolderService fileFolderService;
|
||||||
|
protected VersionService versionService;
|
||||||
|
protected MultilingualContentService multilingualContentService;
|
||||||
|
protected NodeRef folderNodeRef;
|
||||||
|
protected ContentFilterLanguagesService contentFilterLanguagesService;
|
||||||
|
protected NodeArchiveService nodeArchiveService;
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
nodeArchiveService = (NodeArchiveService) ctx.getBean("nodeArchiveService");
|
||||||
|
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
|
authenticationComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
|
||||||
|
transactionService = serviceRegistry.getTransactionService();
|
||||||
|
nodeService = serviceRegistry.getNodeService();
|
||||||
|
fileFolderService = serviceRegistry.getFileFolderService();
|
||||||
|
versionService = serviceRegistry.getVersionService();
|
||||||
|
multilingualContentService = (MultilingualContentService) ctx.getBean("MultilingualContentService");
|
||||||
|
contentFilterLanguagesService = (ContentFilterLanguagesService) ctx.getBean("ContentFilterLanguagesService");
|
||||||
|
|
||||||
|
// Run as admin
|
||||||
|
authenticationComponent.setCurrentUser("admin");
|
||||||
|
|
||||||
|
// Create a folder to work in
|
||||||
|
TransactionWork<NodeRef> createFolderWork = new TransactionWork<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef doWork() throws Exception
|
||||||
|
{
|
||||||
|
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||||
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
|
// Create the folder
|
||||||
|
NodeRef folderNodeRef = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "testFolder"),
|
||||||
|
ContentModel.TYPE_FOLDER).getChildRef();
|
||||||
|
// done
|
||||||
|
return folderNodeRef;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
folderNodeRef = TransactionUtil.executeInUserTransaction(transactionService, createFolderWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
// Clear authentication
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationComponent.clearCurrentSecurityContext();
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeRef createContent()
|
||||||
|
{
|
||||||
|
NodeRef contentNodeRef = fileFolderService.create(
|
||||||
|
folderNodeRef,
|
||||||
|
"" + System.currentTimeMillis(),
|
||||||
|
ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
// add some content
|
||||||
|
ContentWriter contentWriter = fileFolderService.getWriter(contentNodeRef);
|
||||||
|
contentWriter.putContent("ABC");
|
||||||
|
// done
|
||||||
|
return contentNodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetup() throws Exception
|
||||||
|
{
|
||||||
|
// Ensure that content can be created
|
||||||
|
createContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml.tools;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content filter language service test cases
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService
|
||||||
|
* @see org.alfresco.repo.model.ml.ContentFilterLanguagesMap
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class ContentFilterLanguagesMapTest extends AbstractMultilingualTestCases
|
||||||
|
{
|
||||||
|
|
||||||
|
public void testGetFilterLanguages() throws Exception
|
||||||
|
{
|
||||||
|
// get the list of content filter languages
|
||||||
|
List<String> lggs = contentFilterLanguagesService.getFilterLanguages();
|
||||||
|
|
||||||
|
// Ensure that the list is not null
|
||||||
|
assertNotNull("Language list is null", lggs);
|
||||||
|
|
||||||
|
// Ensure that the list is read-only
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lggs.add("NEW LOCALE");
|
||||||
|
assertTrue("Add a value to the content filter language list is not permit, this list would be read only", false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// test case ok
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lggs.remove(0);
|
||||||
|
assertTrue("Remove a value to the content filter language list is not permit, this list would be read only", false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// test case ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testGetMissingLanguages() throws Exception
|
||||||
|
{
|
||||||
|
List<String> lggs = contentFilterLanguagesService.getFilterLanguages();
|
||||||
|
|
||||||
|
// get missing languages with null parameter
|
||||||
|
List<String> missingLggsNull = contentFilterLanguagesService.getMissingLanguages(null);
|
||||||
|
|
||||||
|
// Ensure that the returned list is not null
|
||||||
|
assertNotNull("Language list returned with the null parameter is null", missingLggsNull);
|
||||||
|
// Ensure that the returned list is entire
|
||||||
|
assertEquals("Language list returned with the null parameter corrupted", missingLggsNull.size(), lggs.size());
|
||||||
|
|
||||||
|
// get missing languages with empty collection parameter
|
||||||
|
List<String> missingLggsEmpty = contentFilterLanguagesService.getMissingLanguages(Collections.EMPTY_LIST);
|
||||||
|
|
||||||
|
// Ensure that the returned list is not null
|
||||||
|
assertNotNull("Language list returned with the empty parameter is null", missingLggsEmpty);
|
||||||
|
// Ensure that the returned list is entire
|
||||||
|
assertEquals("Language list returned with the empty parameter corrupted", missingLggsEmpty.size(), lggs.size());
|
||||||
|
|
||||||
|
// get missing languages with a two locale list
|
||||||
|
List<String> param = new ArrayList<String>();
|
||||||
|
param.add(0, lggs.get(0));
|
||||||
|
param.add(1, lggs.get(1));
|
||||||
|
List<String> missingLggsOk = contentFilterLanguagesService.getMissingLanguages(param);
|
||||||
|
|
||||||
|
// Ensure that the returned list is not null
|
||||||
|
assertNotNull("Language list returned with the correct parameter is null", missingLggsOk);
|
||||||
|
// Ensure that the returned list size is correct
|
||||||
|
assertEquals("Language list size returned with the correct parameter is not correct", missingLggsOk.size(), (lggs.size() - 2));
|
||||||
|
// Ensure that the returned list don't content the preceding locales
|
||||||
|
assertFalse("Language found : " + param.get(0), missingLggsOk.contains(param.get(0)));
|
||||||
|
assertFalse("Language found : " + param.get(1), missingLggsOk.contains(param.get(1)));
|
||||||
|
// get missing languages with a not found locale
|
||||||
|
param.add(2, "WRONG LOCALE CODE");
|
||||||
|
List<String> missingLggsWrong = contentFilterLanguagesService.getMissingLanguages(param);
|
||||||
|
|
||||||
|
// Ensure that the returned list is not null
|
||||||
|
assertNotNull("Language list returned with the wrong parameter is null", missingLggsWrong);
|
||||||
|
// Ensure that the returned list size is correct
|
||||||
|
assertEquals("Language list size returned with the correct parameter is not correct", missingLggsWrong.size(), (lggs.size() - 2));
|
||||||
|
// Ensure that the returned list don't content the wrong locale
|
||||||
|
assertFalse("Language found : " + param.get(0), missingLggsWrong.contains(param.get(0)));
|
||||||
|
assertFalse("Language found : " + param.get(1), missingLggsWrong.contains(param.get(1)));
|
||||||
|
assertFalse("Language found : " + param.get(2), missingLggsWrong.contains(param.get(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testISOCodeConvertions() throws Exception
|
||||||
|
{
|
||||||
|
// New ISO code list
|
||||||
|
String[] newCode = {"he", "id", "yi"};
|
||||||
|
String[] oldCode = {"iw", "in", "ji"};
|
||||||
|
|
||||||
|
Locale loc0 = new Locale(newCode[0]);
|
||||||
|
Locale loc1 = new Locale(newCode[1]);
|
||||||
|
Locale loc2 = new Locale(newCode[2]);
|
||||||
|
|
||||||
|
// Ensure that java.util.Locale has converted the new ISO code into new iso code
|
||||||
|
assertEquals("java.util.Locale Convertion not correct for " + newCode[0], oldCode[0], loc0.getLanguage());
|
||||||
|
assertEquals("java.util.Locale Convertion not correct for " + newCode[1], oldCode[1], loc1.getLanguage());
|
||||||
|
assertEquals("java.util.Locale Convertion not correct for " + newCode[2], oldCode[2], loc2.getLanguage());
|
||||||
|
|
||||||
|
// Ensure that the convertion is correcte
|
||||||
|
assertEquals("Convertion of new ISO codes not correct for " + newCode[0], oldCode[0], contentFilterLanguagesService.convertToOldISOCode(newCode[0]));
|
||||||
|
assertEquals("Convertion of new ISO codes not correct for " + newCode[1], oldCode[1], contentFilterLanguagesService.convertToOldISOCode(newCode[1]));
|
||||||
|
assertEquals("Convertion of new ISO codes not correct for " + newCode[2], oldCode[2], contentFilterLanguagesService.convertToOldISOCode(newCode[2]));
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals("Convertion of old ISO codes not correct for " + oldCode[0], newCode[0], contentFilterLanguagesService.convertToNewISOCode(oldCode[0]));
|
||||||
|
assertEquals("Convertion of old ISO codes not correct for " + oldCode[1], newCode[1], contentFilterLanguagesService.convertToNewISOCode(oldCode[1]));
|
||||||
|
assertEquals("Convertion of old ISO codes not correct for " + oldCode[2], newCode[2], contentFilterLanguagesService.convertToNewISOCode(oldCode[2]));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml.tools;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty translations aspect test cases
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.ml.EmptyTranslationAspect
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class EmptyTranslationAspectTest extends AbstractMultilingualTestCases {
|
||||||
|
|
||||||
|
protected ContentService contentService;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
contentService = (ContentService) ctx.getBean("ContentService");
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopy() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
|
||||||
|
boolean exceptionCatched = false;
|
||||||
|
NodeRef copy = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
copy = fileFolderService.copy(
|
||||||
|
empty,
|
||||||
|
nodeService.getPrimaryParent(empty).getParentRef(),
|
||||||
|
"copyOfEmpty" + System.currentTimeMillis()).getNodeRef();
|
||||||
|
|
||||||
|
// test failed
|
||||||
|
}
|
||||||
|
catch (Exception ignore)
|
||||||
|
{
|
||||||
|
exceptionCatched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the copy of an empty translation throws an exception
|
||||||
|
assertTrue("The copy of a translation must throws an exception", exceptionCatched);
|
||||||
|
// Ensure that the copy node is null
|
||||||
|
assertNull("The copy must fail ", copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteNode() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
|
||||||
|
nodeService.deleteNode(empty);
|
||||||
|
|
||||||
|
// Ensure that the empty translation is removed from the workspace
|
||||||
|
assertFalse("The empty translation must be removed from the wokspace", nodeService.exists(empty));
|
||||||
|
// Ensure that the empty translation is not archived
|
||||||
|
assertFalse("The empty translation must be removed from the wokspace", nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetContent() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef otherTranslation = createContent();
|
||||||
|
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(otherTranslation, pivot, Locale.KOREAN);
|
||||||
|
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
|
||||||
|
// Modify the content of the pivot
|
||||||
|
String contentString = fileFolderService.getReader(pivot).getContentString();
|
||||||
|
contentString += "_TEST_";
|
||||||
|
|
||||||
|
fileFolderService.getWriter(pivot).putContent(contentString);
|
||||||
|
|
||||||
|
// Ensure that the URL property of the empty translation content is null
|
||||||
|
assertNull("The URL property of an empty translation must be null", ((ContentData) nodeService.getProperty(empty, ContentModel.PROP_CONTENT)).getContentUrl());
|
||||||
|
// Ensure that the content retourned by a get reader of the empty document is the same as the pivot
|
||||||
|
assertEquals("The content retourned of the empty translation must be the same that the content of the pivot",
|
||||||
|
fileFolderService.getReader(pivot).getContentString(),
|
||||||
|
fileFolderService.getReader(empty).getContentString());
|
||||||
|
// Ensure that the content retourned by a get reader of the empty document is different to the non-pivot translation
|
||||||
|
assertNotSame("The content retourned of the empty translation must be different that the content of a non-pivot translation",
|
||||||
|
fileFolderService.getReader(otherTranslation).getContentString(),
|
||||||
|
fileFolderService.getReader(empty).getContentString());
|
||||||
|
|
||||||
|
|
||||||
|
// modify the pivot
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties(mlContainer);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, Locale.KOREAN);
|
||||||
|
nodeService.setProperties(mlContainer, props);
|
||||||
|
|
||||||
|
// Ensure that the modicfication of the pivot is take in account
|
||||||
|
assertEquals("The modification of the pivot is not take in account",
|
||||||
|
fileFolderService.getReader(otherTranslation).getContentString(),
|
||||||
|
fileFolderService.getReader(empty).getContentString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateContent() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
|
||||||
|
// update the empty translation content
|
||||||
|
ContentWriter writer = contentService.getWriter(empty, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setMimetype("text/plain");
|
||||||
|
writer.putContent("ANY_CONTENT");
|
||||||
|
|
||||||
|
// Ensure that the URL property of the empty translation content is not null
|
||||||
|
assertNotNull("The url of an updated (ex)empty transation can't be null", ((ContentData) nodeService.getProperty(empty, ContentModel.PROP_CONTENT)).getContentUrl());
|
||||||
|
// Ensure that the mlEmptyTranslation aspect is removed
|
||||||
|
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " aspect of an updated (ex)empty translation must be removed", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||||
|
// Ensure that the mlDocument aspect is not removed
|
||||||
|
assertTrue("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect of an updated (ex)empty translation must be keeped", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
// Ensure that the content is written
|
||||||
|
assertEquals("The content of the (ex)empty translation is not correct",
|
||||||
|
fileFolderService.getReader(empty).getContentString(),
|
||||||
|
"ANY_CONTENT");
|
||||||
|
// Ensure that the content is different that the content of the pivot
|
||||||
|
assertNotSame("The content of the (ex)empty translation is not updated and is the same as the content of the pivot",
|
||||||
|
fileFolderService.getReader(empty).getContentString(),
|
||||||
|
fileFolderService.getReader(pivot).getContentString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveAspect() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
|
||||||
|
// 1. remove mlEmptyTranslation aspect with empty content
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||||
|
|
||||||
|
// Ensure that the empty translation is deleted
|
||||||
|
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with no content the node must be deleted",
|
||||||
|
nodeService.exists(empty));
|
||||||
|
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with no content the node must be deleted and can't be archived",
|
||||||
|
nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||||
|
|
||||||
|
// 2. remove mlDocument aspect with empty content
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||||
|
|
||||||
|
// Ensure that the empty translation is deleted
|
||||||
|
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " of an empty translation with no content the node must be deleted",
|
||||||
|
nodeService.exists(empty));
|
||||||
|
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " of an empty translation with no content the node must be deleted and can't be archived",
|
||||||
|
nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||||
|
|
||||||
|
// 3. remove mlEmptyTranslation aspect with not empty content
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||||
|
ContentWriter writer = contentService.getWriter(empty, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setMimetype("text/plain");
|
||||||
|
writer.putContent("ANY_CONTENT");
|
||||||
|
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||||
|
|
||||||
|
// Ensure that the empty translation is NOT deleted
|
||||||
|
assertTrue("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content the node must NOT be deleted",
|
||||||
|
nodeService.exists(empty));
|
||||||
|
// Ensure that the mlEmptyTranslation aspect is removed
|
||||||
|
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content this aspect must be removed",
|
||||||
|
nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||||
|
// Ensure that the mlEmptyDocument in NOT removed
|
||||||
|
assertTrue("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be keeped",
|
||||||
|
nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml.tools;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multilingual container type test cases
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.ml.MLContainerType
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MLContainerTypeTest extends AbstractMultilingualTestCases {
|
||||||
|
|
||||||
|
|
||||||
|
public void testDeleteNode() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef empty;
|
||||||
|
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(pivot, "Empty_" + System.currentTimeMillis(), Locale.ENGLISH);
|
||||||
|
|
||||||
|
nodeService.deleteNode(mlContainer);
|
||||||
|
|
||||||
|
// Ensure that the mlContainer is deleted
|
||||||
|
assertFalse("The mlContainer must be deleted", nodeService.exists(mlContainer));
|
||||||
|
// Ensure that the empty translation is deleted
|
||||||
|
assertFalse("The mlEmptyTranslation must be deleted", nodeService.exists(empty));
|
||||||
|
// Ensure that the non-empty document is not deleted
|
||||||
|
assertTrue("The mlDocument must not be deleted", nodeService.exists(pivot));
|
||||||
|
// Ensure that the mlDocument property of the non-empty document is removed
|
||||||
|
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect of the mlDocument must be removed",
|
||||||
|
nodeService.hasAspect(pivot, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testEditLocale() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef trans1 = createContent();
|
||||||
|
NodeRef trans2 = createContent();
|
||||||
|
NodeRef trans3 = createContent();
|
||||||
|
NodeRef empty = null;
|
||||||
|
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(trans1, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trans2, trans1, Locale.GERMAN);
|
||||||
|
multilingualContentService.addTranslation(trans3, trans1, Locale.ITALIAN);
|
||||||
|
empty = multilingualContentService.addEmptyTranslation(trans1, "EMPTY_" + System.currentTimeMillis(), Locale.JAPANESE);
|
||||||
|
|
||||||
|
// 1. Locale as null
|
||||||
|
|
||||||
|
// Ensure that the setting of the locale of the mlContainer as null throws an excpetion
|
||||||
|
assertTrue("The setting of the locale of a mlContainer must throws an exception",
|
||||||
|
setLocaleProp(mlContainer, null));
|
||||||
|
// Ensure that the locale of the mlContainer is not changed
|
||||||
|
assertEquals("The locale of the mlContainer would not be changed",
|
||||||
|
Locale.FRENCH,
|
||||||
|
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// 2. Set an non-existing locale
|
||||||
|
|
||||||
|
// Ensure that the setting of the locale of the mlContainer as a non-existing translation language throws an excpetion
|
||||||
|
assertTrue("The setting of the locale of a mlContainer as a non-existing translation language must throws an exception",
|
||||||
|
setLocaleProp(mlContainer, Locale.US));
|
||||||
|
// Ensure that the locale of the mlContainer is not changed
|
||||||
|
assertEquals("The locale of the mlContainer would not be changed",
|
||||||
|
Locale.FRENCH,
|
||||||
|
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// 3. Set the locale of a empty translation
|
||||||
|
|
||||||
|
// Ensure that the setting of the locale of the mlContainer as an empty translation language throws an excpetion
|
||||||
|
assertTrue("The setting of the locale of a mlContainer as an empty translation language must throws an exception",
|
||||||
|
setLocaleProp(mlContainer, Locale.JAPANESE));
|
||||||
|
// Ensure that the locale of the mlContainer is not changed
|
||||||
|
assertEquals("The locale of the mlContainer would not be changed",
|
||||||
|
Locale.FRENCH,
|
||||||
|
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// 4. Set an existing and valid locale
|
||||||
|
|
||||||
|
// Ensure that the setting of the locale of the mlContainer as an existing and a non-empty translation DOESN'T throw an excpetion
|
||||||
|
assertFalse("The setting of the locale of a mlContainer as an existing and a non-empty translation DOESN'T throw an excpetion",
|
||||||
|
setLocaleProp(mlContainer, Locale.ITALIAN));
|
||||||
|
// Ensure that the locale of the mlContainer is not changed
|
||||||
|
assertEquals("The locale of the mlContainer would be changed",
|
||||||
|
Locale.ITALIAN,
|
||||||
|
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private boolean setLocaleProp(NodeRef node, Locale locale) throws Exception
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties(node);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, locale);
|
||||||
|
|
||||||
|
boolean exceptionCatched = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nodeService.setProperties(node, props);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException ignore)
|
||||||
|
{
|
||||||
|
exceptionCatched = true;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return exceptionCatched;
|
||||||
|
}
|
||||||
|
}
|
@@ -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.model.ml.tools;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.version.Version;
|
||||||
|
import org.alfresco.service.cmr.version.VersionHistory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @author Philippe Dubois
|
||||||
|
*/
|
||||||
|
public class MultilingualContentServiceImplTest extends AbstractMultilingualTestCases
|
||||||
|
{
|
||||||
|
|
||||||
|
public void testMakeTranslation() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef contentNodeRef = createContent();
|
||||||
|
// Turn the content into a translation with the appropriate structures
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(contentNodeRef, Locale.CHINESE);
|
||||||
|
// Check it
|
||||||
|
assertNotNull("Container not created", mlContainerNodeRef);
|
||||||
|
// Check the container child count
|
||||||
|
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddTranslationUsingContainer() throws Exception
|
||||||
|
{
|
||||||
|
// Make a container with a single translation
|
||||||
|
NodeRef chineseContentNodeRef = createContent();
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||||
|
// Create some more content
|
||||||
|
NodeRef frenchContentNodeRef = createContent();
|
||||||
|
// Make this a translation of the Chinese
|
||||||
|
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
|
||||||
|
frenchContentNodeRef,
|
||||||
|
mlContainerNodeRef,
|
||||||
|
Locale.FRENCH);
|
||||||
|
// Make sure that the original container was used
|
||||||
|
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
|
||||||
|
// Check the container child count
|
||||||
|
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddTranslationUsingContent() throws Exception
|
||||||
|
{
|
||||||
|
// Make a container with a single translation
|
||||||
|
NodeRef chineseContentNodeRef = createContent();
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||||
|
// Create some more content
|
||||||
|
NodeRef frenchContentNodeRef = createContent();
|
||||||
|
// Make this a translation of the Chinese
|
||||||
|
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
|
||||||
|
frenchContentNodeRef,
|
||||||
|
chineseContentNodeRef,
|
||||||
|
Locale.FRENCH);
|
||||||
|
// Make sure that the original container was used
|
||||||
|
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
|
||||||
|
// Check the container child count
|
||||||
|
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testGetMissingTranslation() throws Exception
|
||||||
|
{
|
||||||
|
List<String> langList = contentFilterLanguagesService.getFilterLanguages();
|
||||||
|
int langListSize = langList.size();
|
||||||
|
|
||||||
|
// make sure that it exists at least tree language filter
|
||||||
|
assertFalse("The testGetMissingTranslation test case needs at least three language", langListSize < 3);
|
||||||
|
|
||||||
|
// get the first tree locale of the content filter language list
|
||||||
|
Locale loc1 = I18NUtil.parseLocale(langList.get(0));
|
||||||
|
Locale loc2 = I18NUtil.parseLocale(langList.get(1));
|
||||||
|
Locale loc3 = I18NUtil.parseLocale(langList.get(2));
|
||||||
|
|
||||||
|
// create three content
|
||||||
|
NodeRef nodeRef1 = createContent();
|
||||||
|
NodeRef nodeRef2 = createContent();
|
||||||
|
NodeRef nodeRef3 = createContent();
|
||||||
|
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(nodeRef1, loc1);
|
||||||
|
|
||||||
|
List<Locale> missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
|
||||||
|
|
||||||
|
// make sure that the missing language list size is correct
|
||||||
|
assertFalse("Missing Translation Size false. " +
|
||||||
|
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 1), missing.size() != (langListSize - 1));
|
||||||
|
|
||||||
|
// make sure that the missing language list is correct
|
||||||
|
assertFalse("Missing Translation List false. Locale " + loc1 + " found", missing.contains(loc1.toString()));
|
||||||
|
|
||||||
|
multilingualContentService.addTranslation(nodeRef2, mlContainerNodeRef, loc2);
|
||||||
|
multilingualContentService.addTranslation(nodeRef3, mlContainerNodeRef, loc3);
|
||||||
|
|
||||||
|
|
||||||
|
missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
|
||||||
|
|
||||||
|
// make sure that the missing language list size is correct
|
||||||
|
assertFalse("Missing Translation Size false. " +
|
||||||
|
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 3), missing.size() != (langListSize - 3));
|
||||||
|
|
||||||
|
// make sure that the missing language list is correct
|
||||||
|
assertFalse("Missing Translation List false. Locale " + loc2 + " or " + loc3 + " found", missing.contains(loc2.toString()) || missing.contains(loc3.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testPivotTranslation() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef chineseContentNodeRef = createContent();
|
||||||
|
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||||
|
|
||||||
|
// make sure that the pivot language is set
|
||||||
|
assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// make sure that the pivot language is correctly set
|
||||||
|
assertTrue("Pivot language not correctly set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE).equals(Locale.CHINESE));
|
||||||
|
|
||||||
|
NodeRef frenchContentNodeRef = createContent();
|
||||||
|
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||||
|
|
||||||
|
// make sure that the pivot noderef is correct
|
||||||
|
assertTrue("Pivot node ref not correct", multilingualContentService.getPivotTranslation(mlContainerNodeRef).equals(chineseContentNodeRef));
|
||||||
|
|
||||||
|
// modify the pivot language
|
||||||
|
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, Locale.FRENCH);
|
||||||
|
|
||||||
|
// make sure that the modified pivot noderef is correct
|
||||||
|
assertTrue("Pivot node ref not correct", multilingualContentService.getPivotTranslation(mlContainerNodeRef).equals(frenchContentNodeRef));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testCreateEmptyTranslation() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef chineseContentNodeRef = createContent();
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||||
|
|
||||||
|
NodeRef empty = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "" + System.currentTimeMillis(), Locale.CANADA);
|
||||||
|
|
||||||
|
// Ensure that the empty translation is not null
|
||||||
|
assertNotNull("The creation of the empty document failed ", empty);
|
||||||
|
// Ensure that the empty translation has the mlDocument aspect
|
||||||
|
assertTrue("The empty document must have the mlDocument aspect", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
// Ensure that the empty translation has the mlEmptyTranslation aspect
|
||||||
|
assertTrue("The empty document must have the mlEmptyTranslation aspect", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public void testCreateEdition() throws Exception
|
||||||
|
{
|
||||||
|
// Make some content
|
||||||
|
NodeRef chineseContentNodeRef = createContent();
|
||||||
|
NodeRef frenchContentNodeRef = createContent();
|
||||||
|
NodeRef japaneseContentNodeRef = createContent();
|
||||||
|
// Add to container
|
||||||
|
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||||
|
multilingualContentService.addTranslation(frenchContentNodeRef, mlContainerNodeRef, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(japaneseContentNodeRef, mlContainerNodeRef, Locale.JAPANESE);
|
||||||
|
// Check the container child count
|
||||||
|
assertEquals("Incorrect number of child nodes", 3, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||||
|
|
||||||
|
// Version each of the documents
|
||||||
|
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(3);
|
||||||
|
nodeRefs.add(chineseContentNodeRef);
|
||||||
|
nodeRefs.add(frenchContentNodeRef);
|
||||||
|
nodeRefs.add(japaneseContentNodeRef);
|
||||||
|
versionService.createVersion(nodeRefs, null);
|
||||||
|
// Get the current versions of each of the documents
|
||||||
|
Version chineseVersionPreEdition = versionService.getCurrentVersion(chineseContentNodeRef);
|
||||||
|
Version frenchVersionPreEdition = versionService.getCurrentVersion(frenchContentNodeRef);
|
||||||
|
Version japaneseVersionPreEdition = versionService.getCurrentVersion(japaneseContentNodeRef);
|
||||||
|
|
||||||
|
// Create the edition, keeping the Chinese translation as the basis
|
||||||
|
multilingualContentService.createEdition(chineseContentNodeRef);
|
||||||
|
// Check the container child count
|
||||||
|
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||||
|
|
||||||
|
// Get the document versions now
|
||||||
|
Version chineseVersionPostEdition = versionService.getCurrentVersion(chineseContentNodeRef);
|
||||||
|
assertFalse("Expected document to be gone", nodeService.exists(frenchContentNodeRef));
|
||||||
|
assertFalse("Expected document to be gone", nodeService.exists(japaneseContentNodeRef));
|
||||||
|
|
||||||
|
// Now be sure that we can get the required information using the version service
|
||||||
|
VersionHistory mlContainerVersionHistory = versionService.getVersionHistory(mlContainerNodeRef);
|
||||||
|
Collection<Version> mlContainerVersions = mlContainerVersionHistory.getAllVersions();
|
||||||
|
// Loop through and get all the children of each version
|
||||||
|
for (Version mlContainerVersion : mlContainerVersions)
|
||||||
|
{
|
||||||
|
NodeRef versionedMLContainerNodeRef = mlContainerVersion.getFrozenStateNodeRef();
|
||||||
|
// Get all the children
|
||||||
|
Map<Locale, NodeRef> translationsByLocale = multilingualContentService.getTranslations(
|
||||||
|
versionedMLContainerNodeRef);
|
||||||
|
// Count the children
|
||||||
|
int count = translationsByLocale.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* 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.model.ml.tools;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multilingual document aspect test cases
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases
|
||||||
|
{
|
||||||
|
public void testCopy() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef original = createContent();
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(original, Locale.FRENCH);
|
||||||
|
|
||||||
|
NodeRef copy =
|
||||||
|
fileFolderService.copy(original, nodeService.getPrimaryParent(original).getParentRef(), "COPY" + System.currentTimeMillis()).getNodeRef();
|
||||||
|
|
||||||
|
// Ensure that the copy removes the mlDocument aspect
|
||||||
|
assertFalse("The copy of a mlDocument can't have the multilingual aspect", nodeService.hasAspect(copy, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
|
||||||
|
// Ensure that the copy removes the association between the mlConatiner and the new node
|
||||||
|
assertEquals("The copy of a mlDocument can't be a children of the mlContainer", 1, multilingualContentService.getTranslations(mlContainer).size());
|
||||||
|
|
||||||
|
// Ensure that the copy removes the Locale property of the new node
|
||||||
|
assertNull("The copy of a mlDocument can't keep the locale property", nodeService.getProperty(copy, ContentModel.PROP_LOCALE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteNode() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef trad1 = createContent();
|
||||||
|
NodeRef trad2 = createContent();
|
||||||
|
NodeRef trad3 = createContent();
|
||||||
|
|
||||||
|
NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef();
|
||||||
|
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(trad1, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trad2, trad1, Locale.GERMAN);
|
||||||
|
multilingualContentService.addTranslation(trad3, trad1, Locale.ITALIAN);
|
||||||
|
|
||||||
|
nodeService.deleteNode(trad3);
|
||||||
|
|
||||||
|
// Ensure that the deleted node is romoved from its space
|
||||||
|
assertEquals("The deleted node must be removed to the space", 2, nodeService.getChildAssocs(parent).size());
|
||||||
|
// Ensure that the mlContainer doesn't keep an association to the deleted node
|
||||||
|
assertEquals("The deleted node must be removed to the child associations of the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
|
||||||
|
|
||||||
|
// retore the deleted node
|
||||||
|
NodeRef restoredNode = nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(trad3)).getRestoredNodeRef();
|
||||||
|
|
||||||
|
// Ensure that the restored node is restored to it s original space
|
||||||
|
assertEquals("The restaured node must be restaured to the the space", 3, nodeService.getChildAssocs(parent).size());
|
||||||
|
// Ensure that the restored node is not linked to the mlContainer
|
||||||
|
assertEquals("The restaured node would not be restaured to the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
|
||||||
|
// Ensure that the restored node doesn't keep the mlDocument aspect
|
||||||
|
assertFalse("The restaured node can't keep the multilingual aspect", nodeService.hasAspect(restoredNode, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
// Ensure that the restored node doesn't keep the locale property
|
||||||
|
assertNull("The restaured node can't keep the locale property", nodeService.getProperty(restoredNode, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeletePivot() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef trans1 = createContent();
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||||
|
|
||||||
|
//nodeService.deleteNode(trans1);
|
||||||
|
nodeService.deleteNode(pivot);
|
||||||
|
|
||||||
|
// Ensure that pivot is removed
|
||||||
|
assertFalse("The pivot would be removed", nodeService.exists(pivot));
|
||||||
|
// Ensure that the mlContainer is removed
|
||||||
|
assertFalse("The mlContainer must be removed if the pivot is removed", nodeService.exists(mlContainer));
|
||||||
|
// Ensure that trans1 is NOT removed
|
||||||
|
assertTrue("The last translation would not be removed", nodeService.exists(trans1));
|
||||||
|
// Ensure that trans1 has no mlDocument aspect
|
||||||
|
assertFalse("The last translation can't keep the multilingual aspect", nodeService.hasAspect(trans1, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||||
|
// Ensure that trans1 has no locale propety
|
||||||
|
assertNull("The last translation can't keep the locale property", nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteLastNode() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
|
||||||
|
nodeService.deleteNode(pivot);
|
||||||
|
|
||||||
|
// Ensure that the mlContainer is removed too
|
||||||
|
assertFalse("The mlContainer must be removed if the last translation is removed", nodeService.exists(mlContainer));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveAspect() throws Exception
|
||||||
|
{
|
||||||
|
// entierly covered by the delete tests
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateLocale() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef trans1 = createContent();
|
||||||
|
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||||
|
|
||||||
|
// modify the locale for the translation
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties(trans1);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, Locale.GERMAN);
|
||||||
|
nodeService.setProperties(trans1, props);
|
||||||
|
|
||||||
|
// Ensure that the pivot reference is not changed for the mlContainer and the locale is changed for the translation
|
||||||
|
assertEquals("The locale for the pivot would be changed ",Locale.GERMAN, nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
|
||||||
|
assertEquals("The pivot reference would not be changed in the mlContainer", Locale.FRENCH, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// modify the locale for the pivot
|
||||||
|
props = nodeService.getProperties(pivot);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, Locale.US);
|
||||||
|
nodeService.setProperties(pivot, props);
|
||||||
|
|
||||||
|
// Ensure that the pivot reference is changed (in the pivot and in the mlContainer)
|
||||||
|
assertEquals("The locale for the pivot would be changed ", Locale.US, nodeService.getProperty(pivot, ContentModel.PROP_LOCALE));
|
||||||
|
assertEquals("The pivot reference would be changes in the mlContainer", Locale.US, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateRedundantLocale() throws Exception
|
||||||
|
{
|
||||||
|
NodeRef pivot = createContent();
|
||||||
|
NodeRef trans1 = createContent();
|
||||||
|
NodeRef trans2 = createContent();
|
||||||
|
|
||||||
|
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||||
|
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||||
|
multilingualContentService.addTranslation(trans2, pivot, Locale.JAPANESE);
|
||||||
|
|
||||||
|
// 1. Try with redundant locale
|
||||||
|
|
||||||
|
// modify the locale for the translation 2
|
||||||
|
Map<QName, Serializable> props = nodeService.getProperties(trans2);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, Locale.KOREAN);
|
||||||
|
|
||||||
|
boolean exceptionCatched = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nodeService.setProperties(trans2, props);
|
||||||
|
// test failed
|
||||||
|
} catch (Exception ignore)
|
||||||
|
{
|
||||||
|
exceptionCatched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the the exception was catched.
|
||||||
|
assertTrue("The modification of this locale must catch an exception because it is already in use in another translation", exceptionCatched);
|
||||||
|
// Ensure that the locale of the trans2 is unchanged
|
||||||
|
assertEquals("The locale must not be changed",
|
||||||
|
Locale.JAPANESE,
|
||||||
|
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
|
||||||
|
|
||||||
|
// 2. Try with a non-redundant locale
|
||||||
|
|
||||||
|
props = nodeService.getProperties(trans2);
|
||||||
|
props.put(ContentModel.PROP_LOCALE, Locale.ITALIAN);
|
||||||
|
|
||||||
|
exceptionCatched = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nodeService.setProperties(trans2, props);
|
||||||
|
|
||||||
|
} catch (Exception ignore)
|
||||||
|
{
|
||||||
|
// test failed
|
||||||
|
exceptionCatched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the exception was not catched
|
||||||
|
assertFalse("The modification of the locale would not throws an exception", exceptionCatched);
|
||||||
|
// Ensure that the locale is modified
|
||||||
|
assertEquals("The locale must be changed",
|
||||||
|
Locale.ITALIAN,
|
||||||
|
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
181
source/java/org/alfresco/repo/node/MLTranslationInterceptor.java
Normal file
181
source/java/org/alfresco/repo/node/MLTranslationInterceptor.java
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* 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.node;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||||
|
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.namespace.QName;
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interceptor to
|
||||||
|
* - filter the multilingual nodes to display the documents in the prefered language of teh user
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*/
|
||||||
|
public class MLTranslationInterceptor implements MethodInterceptor
|
||||||
|
{
|
||||||
|
private static Log logger = LogFactory
|
||||||
|
.getLog(MLTranslationInterceptor.class);
|
||||||
|
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
private MultilingualContentService multilingualContentService;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||||
|
{
|
||||||
|
Object ret = null;
|
||||||
|
String methodName = invocation.getMethod().getName();
|
||||||
|
|
||||||
|
// intercept the methods getChildAssocs and getChildByNames to apply filter.
|
||||||
|
if (methodName.equals("getChildAssocs") || methodName.equals("getChildByName"))
|
||||||
|
{
|
||||||
|
ret = invocation.proceed();
|
||||||
|
|
||||||
|
NodeRef parent = (NodeRef) invocation.getArguments()[0];
|
||||||
|
|
||||||
|
// all the association returned by the method
|
||||||
|
List<ChildAssociationRef> allChildAssoc = (List<ChildAssociationRef>) ret;
|
||||||
|
|
||||||
|
// get the user content filter language
|
||||||
|
Locale filterLocale = I18NUtil.getContentLocaleOrNull();
|
||||||
|
|
||||||
|
if(filterLocale != null
|
||||||
|
&& nodeService.getType(parent).equals(ContentModel.TYPE_FOLDER)
|
||||||
|
&& ret != null
|
||||||
|
&& !allChildAssoc.isEmpty()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
// the list of Association to return
|
||||||
|
List<ChildAssociationRef> toReturn = new ArrayList();
|
||||||
|
// the ml containers found in the folder
|
||||||
|
List<NodeRef> mlContainers = new ArrayList();
|
||||||
|
|
||||||
|
// construct the list of ML Container
|
||||||
|
for (ChildAssociationRef assoc : allChildAssoc)
|
||||||
|
{
|
||||||
|
NodeRef child = assoc.getChildRef();
|
||||||
|
|
||||||
|
QName type = nodeService.getType(child);
|
||||||
|
|
||||||
|
if(type.equals(ContentModel.TYPE_CONTENT) &&
|
||||||
|
nodeService.hasAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||||
|
{
|
||||||
|
NodeRef container = multilingualContentService.getTranslationContainer(child);
|
||||||
|
|
||||||
|
if (!mlContainers.contains(container))
|
||||||
|
{
|
||||||
|
mlContainers.add(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no specific treatment for folder and non-multilingual document
|
||||||
|
toReturn.add(assoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each mlContainer found, choose the unique document to return
|
||||||
|
for(NodeRef container : mlContainers)
|
||||||
|
{
|
||||||
|
// get each translation language
|
||||||
|
Set<Locale> locales = multilingualContentService.getTranslations(container).keySet();
|
||||||
|
|
||||||
|
if(locales != null && locales.size() > 0)
|
||||||
|
{
|
||||||
|
Locale matchedLocal = I18NUtil.getNearestLocale(filterLocale, locales);
|
||||||
|
|
||||||
|
NodeRef matchedTranslation = null;
|
||||||
|
|
||||||
|
// if the filter language is not found
|
||||||
|
if(matchedLocal == null)
|
||||||
|
{
|
||||||
|
// get the pivot translation
|
||||||
|
matchedTranslation = multilingualContentService.getPivotTranslation(container);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get the matched translation
|
||||||
|
matchedTranslation = multilingualContentService.getTranslations(container).get(matchedLocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
toReturn.add(new ChildAssociationRef(null, null, null, matchedTranslation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = toReturn;
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Filter has found " +
|
||||||
|
allChildAssoc.size() + " entries, " +
|
||||||
|
mlContainers.size() + " different ML Container " +
|
||||||
|
"and returns " + toReturn.size() + " nodes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
ret = invocation.proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultilingualContentService getMultilingualContentService()
|
||||||
|
{
|
||||||
|
return multilingualContentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMultilingualContentService(
|
||||||
|
MultilingualContentService multilingualContentService)
|
||||||
|
{
|
||||||
|
this.multilingualContentService = multilingualContentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeService getNodeService()
|
||||||
|
{
|
||||||
|
return nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
}
|
@@ -37,6 +37,7 @@ import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
|||||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
import org.alfresco.service.cmr.lock.LockService;
|
||||||
|
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.CopyService;
|
import org.alfresco.service.cmr.repository.CopyService;
|
||||||
@@ -255,7 +256,7 @@ public class ServiceDescriptorRegistry
|
|||||||
*/
|
*/
|
||||||
public ActionService getActionService()
|
public ActionService getActionService()
|
||||||
{
|
{
|
||||||
return (ActionService)getService(ACTION_SERVICE);
|
return (ActionService)getService(ACTION_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@@ -364,6 +365,14 @@ public class ServiceDescriptorRegistry
|
|||||||
return (AttributeService)getService(ATTRIBUTE_SERVICE);
|
return (AttributeService)getService(ATTRIBUTE_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService()
|
||||||
|
*/
|
||||||
|
public ContentFilterLanguagesService getContentFilterLanguagesService()
|
||||||
|
{
|
||||||
|
return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.alfresco.service.ServiceRegistry#getAVMLockingService()
|
* @see org.alfresco.service.ServiceRegistry#getAVMLockingService()
|
||||||
*/
|
*/
|
||||||
|
@@ -41,7 +41,7 @@ public interface VersionModel
|
|||||||
*/
|
*/
|
||||||
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
|
* The store protocol
|
||||||
*/
|
*/
|
||||||
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
|
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
|
||||||
@@ -169,4 +169,11 @@ public interface VersionModel
|
|||||||
public static final QName CHILD_QNAME_VERSIONED_CHILD_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_CHILD_ASSOCS);
|
public static final QName CHILD_QNAME_VERSIONED_CHILD_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_CHILD_ASSOCS);
|
||||||
public static final QName CHILD_QNAME_VERSIONED_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ASSOCS);
|
public static final QName CHILD_QNAME_VERSIONED_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ASSOCS);
|
||||||
public static final QName CHILD_QNAME_VERSION_META_DATA = QName.createQName(NAMESPACE_URI, CHILD_VERSION_META_DATA);
|
public static final QName CHILD_QNAME_VERSION_META_DATA = QName.createQName(NAMESPACE_URI, CHILD_VERSION_META_DATA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created version associated to the deleted translations of an mlContainer
|
||||||
|
*/
|
||||||
|
public static final String PROP_TRANSLATION_VERIONS = "translationVersions";
|
||||||
|
public static final QName PROP_QNAME_TRANSLATION_VERIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERIONS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
|||||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.lock.LockService;
|
import org.alfresco.service.cmr.lock.LockService;
|
||||||
|
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||||
import org.alfresco.service.cmr.model.FileFolderService;
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.CopyService;
|
import org.alfresco.service.cmr.repository.CopyService;
|
||||||
@@ -85,6 +86,7 @@ public interface ServiceRegistry
|
|||||||
static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService");
|
static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService");
|
||||||
static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService");
|
static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService");
|
||||||
static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService");
|
static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService");
|
||||||
|
static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService");
|
||||||
static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService");
|
static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService");
|
||||||
static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService");
|
static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService");
|
||||||
static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService");
|
static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService");
|
||||||
@@ -179,6 +181,12 @@ public interface ServiceRegistry
|
|||||||
@NotAuditable
|
@NotAuditable
|
||||||
MimetypeService getMimetypeService();
|
MimetypeService getMimetypeService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the content filter languages service (or null, if one is not provided)
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
ContentFilterLanguagesService getContentFilterLanguagesService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the search service (or null, if one is not provided)
|
* @return the search service (or null, if one is not provided)
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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.service.cmr.ml;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.service.Auditable;
|
||||||
|
import org.alfresco.service.NotAuditable;
|
||||||
|
import org.alfresco.service.PublicService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This service interface provides support for content filter languages .
|
||||||
|
*
|
||||||
|
* @author yanipig
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@PublicService
|
||||||
|
public interface ContentFilterLanguagesService
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I18N message prefix to found the translation of a language label with a
|
||||||
|
* given lang code.
|
||||||
|
*/
|
||||||
|
public static final String MESSAGE_PREFIX = "content_filter_lang.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the order of the specified language code
|
||||||
|
*
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
* @throws AlfrescoRuntimeException if the code doesn't exist
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
public int getOrderByCode(String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the language of the specified language code
|
||||||
|
*
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
* @throws AlfrescoRuntimeException if the code doesn't exist
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
public String getLabelByCode(String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ordered list of languages code
|
||||||
|
*
|
||||||
|
* @return the map of displays indexed by extension
|
||||||
|
*/
|
||||||
|
@Auditable
|
||||||
|
public List<String> getFilterLanguages();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the the odered filter which results form an extract of availableLanguages on the filterLanguages
|
||||||
|
*
|
||||||
|
* @param availableLanguages the languages list whose will be removed from the filterLanguages
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Auditable
|
||||||
|
public List<String> getMissingLanguages(List<String> availableLanguages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default content filter language, null if it's not set.
|
||||||
|
*/
|
||||||
|
@Auditable
|
||||||
|
public String getDefaultLanguage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since <code>java.util.Locale</code> uses and returns <b>old</b> ISO code and the content-filter-lang.xml
|
||||||
|
* respects the <b>new ones</b>. This method convert new codes into old codes:
|
||||||
|
* <p>(he, yi, and id) new codes to (iw, ji, and in) old codes </p>
|
||||||
|
*
|
||||||
|
* @param code the ISO language code to convert
|
||||||
|
* @return the convertion of the codes he, yi, and id or the given code
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
public String convertToOldISOCode(String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since <code>java.util.Locale</code> uses and returns <b>old</b> ISO code and the content-filter-lang.xml
|
||||||
|
* respects the <b>new ones</b>. This method convert old codes into new codes:
|
||||||
|
* <p>(iw, ji, and in) old codes to (he, yi, and id) new codes </p>
|
||||||
|
*
|
||||||
|
* @param code the ISO language code to convert
|
||||||
|
* @return the convertion of the codes iw, ji, and in or the given code
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
public String convertToNewISOCode(String code);
|
||||||
|
}
|
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.service.cmr.ml;
|
package org.alfresco.service.cmr.ml;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -117,4 +118,38 @@ public interface MultilingualContentService
|
|||||||
*/
|
*/
|
||||||
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "locale"})
|
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "locale"})
|
||||||
NodeRef getTranslationForLocale(NodeRef translationNodeRef, Locale locale);
|
NodeRef getTranslationForLocale(NodeRef translationNodeRef, Locale locale);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given <b>cm:mlDocument</b> or a <b>cm:mlContainer</b>, this node returns each
|
||||||
|
* locale that the node hasn't a translation yet.
|
||||||
|
*
|
||||||
|
* @param localizedNodeRef the <b>cm:mlDocument</b> or the <b>cm:mlContainer</b>
|
||||||
|
* @param addThisNodeLocale if true, add the locale of the given <b>cm:mlDocument</b> in the list.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Auditable(key = Auditable.Key.ARG_0, parameters = {"localizedNodeRef", "addThisNodeLocale"})
|
||||||
|
List<Locale> getMissingTranslations(NodeRef localizedNodeRef, boolean addThisNodeLocale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given any node, this returns the pivot translation. The pivot translation is the translation
|
||||||
|
* that its locale is referenced by the locale of the MLContainer. The translation can't be an
|
||||||
|
* empty translation.
|
||||||
|
*
|
||||||
|
* @param nodeRef the node to test
|
||||||
|
* @return the pivot translation
|
||||||
|
*/
|
||||||
|
@Auditable(key = Auditable.Key.ARG_0, parameters = {"nodeRef"})
|
||||||
|
NodeRef getPivotTranslation(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a empty translation out of an existing document. The necessary translation structures will be created
|
||||||
|
* as necessary.
|
||||||
|
*
|
||||||
|
* @param translationOfNodeRef An existing <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
|
||||||
|
* @param name The name of the translation to create
|
||||||
|
* @return Returns the new created <b>cm:mlEmptyTranslation</b>
|
||||||
|
*/
|
||||||
|
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationOfNodeRef", "name", "locale"})
|
||||||
|
NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user