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:
Derek Hulley
2007-05-22 04:47:14 +00:00
parent 2f68bf73da
commit 2e79d2e6d2
33 changed files with 3885 additions and 197 deletions

View File

@@ -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"/>

View File

@@ -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>

View File

@@ -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">

View File

@@ -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">

View 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

View File

@@ -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

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 -->
<!-- ============================== --> <!-- ============================== -->

View File

@@ -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

View File

@@ -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();

View 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);
}
}
}
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View 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");
}
}
}
}

View File

@@ -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();
}
} }

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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]));
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,232 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.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();
}
}
}

View File

@@ -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));
}
}

View 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;
}
}

View File

@@ -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()
*/ */

View File

@@ -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);
} }

View File

@@ -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)
*/ */

View File

@@ -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);
}

View File

@@ -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);
} }