Merged V2.1 to HEAD

6383: ML contributions
   6400: AR-1625 Empty translations track pivot translation


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6406 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-08-02 23:57:38 +00:00
parent 7c4ddd4fdd
commit 4ffc28f0bf
28 changed files with 2461 additions and 848 deletions

View File

@@ -15,11 +15,11 @@
* 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:
* 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.web.action.evaluator;
@@ -31,36 +31,58 @@ import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.UserPreferencesBean;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* Evaluates whether the Add Translation (with or without content) action should be visible.
*
* If the node is not already Multilingual, locked, or if a translation exists for each available
* Evaluates whether the Add Translation (with or without content) action should be visible.
*
* If the node is not already Multilingual, locked, or if a translation exists for each available
* filter language, don't allow the action.
*
*
* The current user can add a translation to a translation set only if he has enough right to add
* a content to the space where the pivot translation is located in.
*
* @author Yannick Pignot
*/
public class AddTranslationEvaluator implements ActionEvaluator
{
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
boolean isNodeMultililingal = node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
boolean isMLContainer = node.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER);
MultilingualContentService mlservice =
(MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
// the node must be multiligual (translation or ml container)
if(isNodeMultililingal || isMLContainer)
{
FacesContext fc = FacesContext.getCurrentInstance();
UserPreferencesBean userprefs =
(UserPreferencesBean) FacesHelper.getManagedBean(fc, "UserPreferencesBean");
// the current user must have enough right to add a content to the space
// where the pivot translation is located in
if(MultilingualUtils.canAddChildrenToPivotSpace(node, fc))
{
MultilingualContentService mlservice =
(MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
// the number of translation of this document
int availableTranslationCount = mlservice.getTranslations(node.getNodeRef()).size();
// the total number of available languages for the translation
int contentFilterLanguagesCount = userprefs.getContentFilterLanguages(false).length;
UserPreferencesBean userprefs =
(UserPreferencesBean) FacesHelper.getManagedBean(fc, "UserPreferencesBean");
return (node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false &&
node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT) == true &&
availableTranslationCount < contentFilterLanguagesCount);
// the number of translation of this document
int availableTranslationCount = mlservice.getTranslations(node.getNodeRef()).size();
// the total number of available languages for the translation
int contentFilterLanguagesCount = userprefs.getContentFilterLanguages(false).length;
// the number of translation must be < to the total number of available language for the content filter
return (availableTranslationCount < contentFilterLanguagesCount);
}
else
{
return false;
}
}
else
{
return false;
}
}
}

View File

@@ -15,35 +15,50 @@
* 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:
* 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.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* Evaluates whether the Cut Node action should be visible.
*
* Among all available operations over non-multilingual documents (i.e. copy,
* delete, start discussion, etc), there is a missing one: <b>Move</b>.
* Translations cannot be moved due to the exiting link it has with the logical
* document. Despite it is technically achievable, it could be functionally
* troublesome. Spreading translations of the same semantic message among several
* Evaluates whether the Cut Node action should be visible.
*
* Among all available operations over non-multilingual documents (i.e. copy,
* delete, start discussion, etc), there is a missing one: <b>Move</b>.
* Translations cannot be moved due to the exiting link it has with the logical
* document. Despite it is technically achievable, it could be functionally
* troublesome. Spreading translations of the same semantic message among several
* spaces could lead to confusion and problems.
*
*
* If the node to move is a mlContainer, the user must have enough right to delete each translation
*
* @author Yannick Pignot
*/
public class CutNodeEvaluator implements ActionEvaluator
{
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
// the node to delete is a ml container, test if the user has enought right on each translation
if(node.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
return MultilingualUtils.canMoveEachTranslation(node, fc);
}
boolean eval = true;
// impossible to cut/copy a translation without content.
@@ -53,9 +68,9 @@ public class CutNodeEvaluator implements ActionEvaluator
}
else
{
eval = !node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
eval = !node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
}
return eval;
return eval;
}
}

View File

@@ -15,11 +15,11 @@
* 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:
* 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.web.action.evaluator;
@@ -30,11 +30,12 @@ import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Delete document.
*
*
* @author Kevin Roast
*/
public class DeleteDocEvaluator implements ActionEvaluator
@@ -44,14 +45,20 @@ public class DeleteDocEvaluator implements ActionEvaluator
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
// the node to delete is a ml container, test if the user has enought right on each translation
if(node.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
return MultilingualUtils.canDeleteEachTranslation(node, fc);
}
boolean isPivot = false;
// special case for multilingual documents
if (node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
FacesContext fc = FacesContext.getCurrentInstance();
MultilingualContentService mlservice =
MultilingualContentService mlservice =
(MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
// if the translation is the last translation, user can delete it
@@ -67,7 +74,7 @@ public class DeleteDocEvaluator implements ActionEvaluator
}
// finally, the node is not the pivot translation, user can delete it
}
return (node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false &&
isPivot == false);

View File

@@ -0,0 +1,48 @@
/*
* 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.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.web.action.ActionEvaluator;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* Evaluates whether the new edition wizard action should be visible.
*
* The creation of a new edtion implies the deletion of each translation and the creation
* of new content in the space
*
* @author Yanick Pignot
*/
public class NewEditionEvaluator implements ActionEvaluator
{
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
return MultilingualUtils.canStartNewEditon(node, fc);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -44,6 +43,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.version.common.VersionLabelComparator;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
@@ -59,6 +59,7 @@ import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.MapNode;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
@@ -95,6 +96,8 @@ public class DocumentDetailsBean extends BaseDetailsBean
private NodeRef addedCategory;
private List categories;
private Node translationDocument;
// ------------------------------------------------------------------------------
// Construction
@@ -213,7 +216,7 @@ public class DocumentDetailsBean extends BaseDetailsBean
{
this.navigator.setupDispatchContext(getDocument());
}
/**
* Save the state of the panel that was expanded/collapsed
*/
@@ -252,8 +255,17 @@ public class DocumentDetailsBean extends BaseDetailsBean
clientVersion.put("notes", version.getDescription());
clientVersion.put("author", version.getCreator());
clientVersion.put("versionDate", version.getCreatedDate());
clientVersion.put("url", DownloadContentServlet.generateBrowserURL(version.getFrozenStateNodeRef(),
clientVersion.getName()));
if(getDocument().hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
clientVersion.put("url", null);
}
else
{
clientVersion.put("url", DownloadContentServlet.generateBrowserURL(version.getFrozenStateNodeRef(),
clientVersion.getName()));
}
// add the client side version to the list
versions.add(clientVersion);
@@ -264,23 +276,6 @@ public class DocumentDetailsBean extends BaseDetailsBean
return versions;
}
/**
* The comparator to sort a version list according their version label ascending
*
* TODO add this code in the repository as Version Util class ?
*/
private Comparator versionComparator = new Comparator()
{
public int compare(Object o1, Object o2)
{
String label01 = ((Version) o1).getVersionLabel();
String label02 = ((Version) o2).getVersionLabel();
// sort the list ascending
return label02.compareTo(label01);
}
};
/** List of client light weight edition histories */
private List<SingleEditionBean> editionHistory = null;
@@ -366,102 +361,115 @@ public class DocumentDetailsBean extends BaseDetailsBean
private List<SingleEditionBean> initEditionHistory()
{
// get the mlContainer
NodeRef mlContainer = getDocumentMlContainer().getNodeRef();
NodeRef mlContainer = getDocumentMlContainer().getNodeRef();
// get all editions and sort them ascending according their version label
List<Version> orderedEditionList = new ArrayList<Version>(editionService.getEditions(mlContainer).getAllVersions());
Collections.sort(orderedEditionList, versionComparator);
// get all editions and sort them ascending according their version label
List<Version> orderedEditionList = new ArrayList<Version>(editionService.getEditions(mlContainer).getAllVersions());
Collections.sort(orderedEditionList, new VersionLabelComparator());
// the list of Single Edition Bean to return
editionHistory = new ArrayList<SingleEditionBean>(orderedEditionList.size());
// the list of Single Edition Bean to return
editionHistory = new ArrayList<SingleEditionBean>(orderedEditionList.size());
boolean firstEdition = true;
boolean firstEdition = true;
// for each edition, init a SingleEditionBean
for (Version edition : orderedEditionList)
{
SingleEditionBean editionBean = new SingleEditionBean();
// for each edition, init a SingleEditionBean
for (Version edition : orderedEditionList)
{
SingleEditionBean editionBean = new SingleEditionBean();
MapNode clientEdition = new MapNode(edition.getFrozenStateNodeRef());
MapNode clientEdition = new MapNode(edition.getFrozenStateNodeRef());
String editionLabel = edition.getVersionLabel();
if (firstEdition)
{
editionLabel += " (" + Application.getMessage(FacesContext.getCurrentInstance(), MSG_CURRENT) + ")";
}
String editionLabel = edition.getVersionLabel();
if (firstEdition)
{
editionLabel += " (" + Application.getMessage(FacesContext.getCurrentInstance(), MSG_CURRENT) + ")";
}
clientEdition.put("editionLabel", editionLabel);
clientEdition.put("editionNotes", edition.getDescription());
clientEdition.put("editionAuthor", edition.getCreator());
clientEdition.put("editionDate", edition.getCreatedDate());
clientEdition.put("editionLabel", editionLabel);
clientEdition.put("editionNotes", edition.getDescription());
clientEdition.put("editionAuthor", edition.getCreator());
clientEdition.put("editionDate", edition.getCreatedDate());
// Set the edition of the edition bean
editionBean.setEdition(clientEdition);
// Set the edition of the edition bean
editionBean.setEdition(clientEdition);
// get translations
List<VersionHistory> translationHistories = null;
// get translations
List<VersionHistory> translationHistories = null;
if (firstEdition)
{
// Get the translations because the current edition doesn't content link with its
// translation in the version store.
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainer);
translationHistories = new ArrayList<VersionHistory>(translations.size());
for (NodeRef translation : translations.values())
{
translationHistories.add(versionService.getVersionHistory(translation));
}
}
else
{
if (firstEdition)
{
// Get the translations because the current edition doesn't content link with its
// translation in the version store.
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainer);
translationHistories = new ArrayList<VersionHistory>(translations.size());
for (NodeRef translation : translations.values())
{
translationHistories.add(versionService.getVersionHistory(translation));
}
}
else
{
translationHistories = editionService.getVersionedTranslations(edition);
}
}
// add each translation in the SingleEditionBean
for (VersionHistory versionHistory : translationHistories)
{
// get the list of versions and sort them ascending according their version label
List<Version> orderedVersions = new ArrayList<Version>(versionHistory.getAllVersions());
Collections.sort(orderedVersions, versionComparator);
// add each translation in the SingleEditionBean
for (VersionHistory versionHistory : translationHistories)
{
// get the list of versions and sort them ascending according their version label
List<Version> orderedVersions = new ArrayList<Version>(versionHistory.getAllVersions());
Collections.sort(orderedVersions, new VersionLabelComparator());
// the last version is the first version of the list
Version lastVersion = orderedVersions.get(0);
// the last version is the first version of the list
Version lastVersion = orderedVersions.get(0);
// get the properties of the lastVersion
Map<QName, Serializable> lastVersionProperties = editionService.getVersionedMetadatas(lastVersion);
Locale language = (Locale) lastVersionProperties.get(ContentModel.PROP_LOCALE);
// get the properties of the lastVersion
Map<QName, Serializable> lastVersionProperties = editionService.getVersionedMetadatas(lastVersion);
Locale language = (Locale) lastVersionProperties.get(ContentModel.PROP_LOCALE);
// create a map node representation of the last version
MapNode clientLastVersion = new MapNode(lastVersion.getFrozenStateNodeRef());
// create a map node representation of the last version
MapNode clientLastVersion = new MapNode(lastVersion.getFrozenStateNodeRef());
clientLastVersion.put("versionName", lastVersionProperties.get(ContentModel.PROP_NAME));
clientLastVersion.put("versionDescription", lastVersionProperties.get(ContentModel.PROP_DESCRIPTION));
clientLastVersion.put("versionAuthor", lastVersionProperties.get(ContentModel.PROP_AUTHOR));
clientLastVersion.put("versionCreatedDate", lastVersionProperties.get(ContentModel.PROP_CREATED));
clientLastVersion.put("versionModifiedDate", lastVersionProperties.get(ContentModel.PROP_MODIFIED));
clientLastVersion.put("versionLanguage", this.contentFilterLanguagesService.convertToNewISOCode(language.getLanguage()).toUpperCase());
clientLastVersion.put("versionUrl", DownloadContentServlet.generateBrowserURL(lastVersion.getFrozenStateNodeRef(), clientLastVersion.getName()));
clientLastVersion.put("versionName", lastVersionProperties.get(ContentModel.PROP_NAME));
// use the node service for the description to ensure that the returned value is a text and not a MLText
clientLastVersion.put("versionDescription", nodeService.getProperty(lastVersion.getFrozenStateNodeRef(), ContentModel.PROP_DESCRIPTION));
clientLastVersion.put("versionAuthor", lastVersionProperties.get(ContentModel.PROP_AUTHOR));
clientLastVersion.put("versionCreatedDate", lastVersionProperties.get(ContentModel.PROP_CREATED));
clientLastVersion.put("versionModifiedDate", lastVersionProperties.get(ContentModel.PROP_MODIFIED));
clientLastVersion.put("versionLanguage", this.contentFilterLanguagesService.convertToNewISOCode(language.getLanguage()).toUpperCase());
// add a translation of the editionBean
editionBean.addTranslations(clientLastVersion);
}
editionHistory.add(editionBean);
firstEdition = false;
}
if(nodeService.hasAspect(lastVersion.getFrozenStateNodeRef(), ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
clientLastVersion.put("versionUrl", null);
}
else
{
clientLastVersion.put("versionUrl", DownloadContentServlet.generateBrowserURL(lastVersion.getFrozenStateNodeRef(), clientLastVersion.getName()));
}
return editionHistory;
// add a translation of the editionBean
editionBean.addTranslations(clientLastVersion);
}
editionHistory.add(editionBean);
firstEdition = false;
}
return editionHistory;
}
/**
* Returns a list of objects representing the translations of the current document
*
* Returns a list of objects representing the translations of the current document
*
* @return List of translations
*/
public List getTranslations()
{
List<MapNode> translations = new ArrayList<MapNode>();
if (getDocument().hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
Node document = getDocument();
boolean canNewEdtion = MultilingualUtils.canStartNewEditon(document, FacesContext.getCurrentInstance());
if (document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT) || ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(document.getType()))
{
Map<Locale, NodeRef> translationsMap = this.multilingualContentService.getTranslations(getDocument().getNodeRef());
@@ -485,6 +493,8 @@ public class DocumentDetailsBean extends BaseDetailsBean
mapNode.put("language", lgge);
mapNode.put("url", DownloadContentServlet.generateBrowserURL(nodeRef, mapNode.getName()));
mapNode.put("notEmpty", new Boolean(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)));
mapNode.put("userHasRight", new Boolean(canNewEdtion));
// add the client side version to the list
translations.add(mapNode);
}
@@ -593,23 +603,23 @@ public class DocumentDetailsBean extends BaseDetailsBean
/**
* Sets the category added from the multi value editor
*
*
* @param addedCategory The added category
*/
public void setAddedCategory(NodeRef addedCategory)
{
this.addedCategory = addedCategory;
}
/**
* Updates the categories for the current document
*
*
* @return The outcome
*/
public String saveCategories()
{
String outcome = "cancel";
try
{
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
@@ -617,22 +627,22 @@ public class DocumentDetailsBean extends BaseDetailsBean
{
public Object execute() throws Throwable
{
// firstly retrieve all the properties for the current node
// firstly retrieve all the properties for the current node
Map<QName, Serializable> updateProps = nodeService.getProperties(getDocument().getNodeRef());
// create a node ref representation of the selected id and set the new properties
// create a node ref representation of the selected id and set the new properties
updateProps.put(ContentModel.PROP_CATEGORIES, (Serializable) categories);
// set the properties on the node
// set the properties on the node
nodeService.setProperties(getDocument().getNodeRef(), updateProps);
return null;
}
};
txnHelper.doInTransaction(callback);
// reset the state of the current document so it reflects the changes just made
getDocument().reset();
outcome = "finish";
}
catch (Throwable e)
@@ -640,10 +650,10 @@ public class DocumentDetailsBean extends BaseDetailsBean
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE_CATEGORY), e.getMessage()), e);
}
return outcome;
}
/**
* Applies the classifiable aspect to the current document
*/
@@ -656,13 +666,13 @@ public class DocumentDetailsBean extends BaseDetailsBean
{
public Object execute() throws Throwable
{
// add the general classifiable aspect to the node
// add the general classifiable aspect to the node
nodeService.addAspect(getDocument().getNodeRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, null);
return null;
}
};
txnHelper.doInTransaction(callback);
// reset the state of the current document
getDocument().reset();
}
@@ -672,7 +682,7 @@ public class DocumentDetailsBean extends BaseDetailsBean
FacesContext.getCurrentInstance(), MSG_ERROR_ASPECT_CLASSIFY), e.getMessage()), e);
}
}
/**
* Applies the versionable aspect to the current document
*/
@@ -685,13 +695,13 @@ public class DocumentDetailsBean extends BaseDetailsBean
{
public Object execute() throws Throwable
{
// add the versionable aspect to the node
// add the versionable aspect to the node
nodeService.addAspect(getDocument().getNodeRef(), ContentModel.ASPECT_VERSIONABLE, null);
return null;
}
};
txnHelper.doInTransaction(callback);
// reset the state of the current document
getDocument().reset();
}
@@ -701,14 +711,14 @@ public class DocumentDetailsBean extends BaseDetailsBean
FacesContext.getCurrentInstance(), MSG_ERROR_ASPECT_VERSIONING), e.getMessage()), e);
}
}
/**
* Action Handler to unlock a locked document
*/
public void unlock(final ActionEvent event)
{
final FacesContext fc = FacesContext.getCurrentInstance();
try
{
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
@@ -717,13 +727,13 @@ public class DocumentDetailsBean extends BaseDetailsBean
public Object execute() throws Throwable
{
lockService.unlock(getNode().getNodeRef());
String msg = Application.getMessage(fc, MSG_SUCCESS_UNLOCK);
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
String formId = Utils.getParentForm(fc, event.getComponent()).getClientId(fc);
fc.addMessage(formId + ':' + getPropertiesPanelId(), facesMsg);
getNode().reset();
String msg = Application.getMessage(fc, MSG_SUCCESS_UNLOCK);
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
String formId = Utils.getParentForm(fc, event.getComponent()).getClientId(fc);
fc.addMessage(formId + ':' + getPropertiesPanelId(), facesMsg);
getNode().reset();
return null;
}
};
@@ -735,7 +745,7 @@ public class DocumentDetailsBean extends BaseDetailsBean
fc, Repository.ERROR_GENERIC), e.getMessage()), e);
}
}
/**
* Applies the inlineeditable aspect to the current document
*/
@@ -748,33 +758,33 @@ public class DocumentDetailsBean extends BaseDetailsBean
{
public Object execute() throws Throwable
{
// add the inlineeditable aspect to the node
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
String contentType = null;
ContentData contentData = (ContentData)getDocument().getProperties().get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentType = contentData.getMimetype();
}
if (contentType != null)
{
// set the property to true by default if the filetype is a known content type
if (MimetypeMap.MIMETYPE_HTML.equals(contentType) ||
MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(contentType) ||
MimetypeMap.MIMETYPE_XML.equals(contentType) ||
MimetypeMap.MIMETYPE_TEXT_CSS.equals(contentType) ||
MimetypeMap.MIMETYPE_JAVASCRIPT.equals(contentType))
{
props.put(ApplicationModel.PROP_EDITINLINE, true);
}
}
// add the inlineeditable aspect to the node
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
String contentType = null;
ContentData contentData = (ContentData)getDocument().getProperties().get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentType = contentData.getMimetype();
}
if (contentType != null)
{
// set the property to true by default if the filetype is a known content type
if (MimetypeMap.MIMETYPE_HTML.equals(contentType) ||
MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(contentType) ||
MimetypeMap.MIMETYPE_XML.equals(contentType) ||
MimetypeMap.MIMETYPE_TEXT_CSS.equals(contentType) ||
MimetypeMap.MIMETYPE_JAVASCRIPT.equals(contentType))
{
props.put(ApplicationModel.PROP_EDITINLINE, true);
}
}
nodeService.addAspect(getDocument().getNodeRef(), ApplicationModel.ASPECT_INLINEEDITABLE, props);
return null;
}
};
txnHelper.doInTransaction(callback);
// reset the state of the current document
getDocument().reset();
}
@@ -970,6 +980,27 @@ public class DocumentDetailsBean extends BaseDetailsBean
return this.getNode();
}
/**
* Before opening the ml container details, remeber the translation
* from which the action comes.
*
* @param node
*/
public void setTranslationDocument(Node node)
{
this.translationDocument = node;
}
/**
* Restore the translationf from which the ml container
* details dialog comes.
*/
public void resetMLDocument(ActionEvent event)
{
this.browseBean.setupCommonBindingProperties(this.translationDocument);
this.browseBean.setDocument(this.translationDocument);
}
/**
* Returns the ml container of the document this bean is currently representing
*
@@ -977,11 +1008,19 @@ public class DocumentDetailsBean extends BaseDetailsBean
*/
public Node getDocumentMlContainer()
{
NodeRef nodeRef = getNode().getNodeRef();
Node currentNode = getNode();
return new Node(multilingualContentService.getTranslationContainer(nodeRef));
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(currentNode.getType()))
{
return currentNode;
}
else
{
NodeRef nodeRef = getNode().getNodeRef();
return new Node(multilingualContentService.getTranslationContainer(nodeRef));
}
}
/**
* Sets the lock service instance the bean should use
*

View File

@@ -0,0 +1,530 @@
/*--+
| Copyright European Community 2006 - Licensed under the EUPL V.1.0
|
| http://ec.europa.eu/idabc/en/document/6523
|
+--*/
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.common.VersionLabelComparator;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.EditionService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.repository.MapNode;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
/**
* Bean with generic function helping the rendering of the versioned properties
*
* @author Yanick Pignot
*/
public class VersionedDocumentDetailsBean
{
/** Dependencies */
protected VersionService versionService;
protected EditionService editionService;
protected NodeService nodeService;
protected MultilingualContentService multilingualContentService;
protected ContentFilterLanguagesService contentFilterLanguagesService;
private static final Comparator VERSION_LABEL_COMPARATOR = new VersionLabelComparator();
/** Determine if the version is a translation of a old edition */
private boolean fromPreviousEditon;
/** The version selected by the user */
private Version documentVersion;
private VersionHistory versionHistory;
/** The multilingual information of the selected version selected by the user */
private Version documentEdition;
private VersionHistory editionHistory;
public void init()
{
fromPreviousEditon = false;
documentVersion = null;
versionHistory = null;
documentEdition = null;
editionHistory = null;
}
/**
* Set which version of the current node that the user want to display the properties
*/
public void setBrowsingVersion(ActionEvent event)
{
init();
// Get the properties of the action event
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String versionLabel = params.get("versionLabel");
String id = params.get("id");
String lang = params.get("lang");
setBrowsingVersion(id, versionLabel, lang);
}
/**
* Implementation of setBrowsingVersion action event to be use with the needed parameters.
*/
private void setBrowsingVersion(String id, String versionLabel, String lang)
{
// test if the mandatories parameter are valid
ParameterCheck.mandatoryString("The id of the node", id);
ParameterCheck.mandatoryString("The version of the node", versionLabel);
try
{
// try to get the nodeRef with the given ID. This node is not a versioned node.
NodeRef currentNodeRef = new NodeRef(Repository.getStoreRef(), id);
// the threatment is different if the node is a translation or a mlContainer
if(nodeService.getType(currentNodeRef).equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// test if the lang parameter is valid
ParameterCheck.mandatoryString("The lang of the node", lang);
fromPreviousEditon = true;
versionLabel = cleanVersionLabel(versionLabel);
// set the edition information of the mlContainer of the selected translation version
this.editionHistory = editionService.getEditions(currentNodeRef);
this.documentEdition = editionHistory.getVersion(versionLabel);
// set the version to display
this.documentVersion = getBrowsingVersionForMLContainer(currentNodeRef, versionLabel, lang);
}
else
{
fromPreviousEditon = false;
// set the version history
this.versionHistory = versionService.getVersionHistory(currentNodeRef);
// set the version to display
this.documentVersion = getBrowsingVersionForDocument(currentNodeRef, versionLabel);
}
}
catch (InvalidNodeRefException refErr)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
}
}
/**
* Navigates to next item in the list of versioned content for the current VersionHistory
*/
@SuppressWarnings("unchecked")
public void nextItem(ActionEvent event)
{
// Get the properties of the action event
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String versionLabel = params.get("versionLabel");
// if the version is not specified, get the next version
if(versionLabel == null)
{
List<Version> nextVersions = new ArrayList<Version>(this.versionHistory.getSuccessors(this.documentVersion));
// if the version history doesn't contains successor, get the root version (the first one)
if(nextVersions == null || nextVersions.size() < 1)
{
this.documentVersion = versionHistory.getRootVersion();
}
else
{
Collections.sort(nextVersions, VERSION_LABEL_COMPARATOR);
this.documentVersion = nextVersions.get(0);
}
}
else
{
this.documentVersion = this.versionHistory.getVersion(versionLabel);
}
}
/**
* Navigates to previous item in the list of versioned content for the current VersionHistory
*/
@SuppressWarnings("unchecked")
public void previousItem(ActionEvent event)
{
// Get the properties of the action event
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String versionLabel = params.get("versionLabel");
// if the version is not specified, get the next version
if(versionLabel == null)
{
Version prevVersion = this.versionHistory.getPredecessor(this.documentVersion);
// if the version history doesn't contains predecessor, get the last version
if(prevVersion == null)
{
List<Version> allVersions = new ArrayList<Version>(this.versionHistory.getAllVersions());
Collections.sort(allVersions, VERSION_LABEL_COMPARATOR);
this.documentVersion = allVersions.get(0);
}
else
{
this.documentVersion = prevVersion;
}
}
else
{
this.documentVersion = this.versionHistory.getVersion(versionLabel);
}
}
/**
* Returns a list of objects representing the translations of the given version of the mlContainer
*
* @return List of translations
*/
@SuppressWarnings("unchecked")
public List getTranslations()
{
// get the version of the mlContainer and its translations
List<VersionHistory> translationsList = editionService.getVersionedTranslations(this.documentEdition);
Map<Locale, NodeRef> translationNodeRef;
// if translation size == 0, the edition is the current edition and the translations are not yet attached.
if(translationsList.size() == 0)
{
// the selection edition is the current: use the multilingual content service
translationNodeRef = multilingualContentService.getTranslations(this.documentEdition.getVersionedNodeRef());
}
else
{
translationNodeRef = new HashMap<Locale, NodeRef>(translationsList.size());
// get the last version of the translation in the given lang of the edition
for (VersionHistory history : translationsList)
{
// get the list of versions and sort them ascending according their version label
List<Version> orderedVersions = new ArrayList<Version>(history.getAllVersions());
Collections.sort(orderedVersions, VERSION_LABEL_COMPARATOR);
// the last version is the first version of the list
Version lastVersion = orderedVersions.get(0);
// fill the list of translation
if(lastVersion != null)
{
NodeRef versionNodeRef = lastVersion.getFrozenStateNodeRef();
Locale locale = (Locale) nodeService.getProperty(versionNodeRef, ContentModel.PROP_LOCALE);
translationNodeRef.put(locale, versionNodeRef);
}
}
}
// the list of client-side translation to return
List<MapNode> translations = new ArrayList<MapNode>(translationNodeRef.size());
for (Map.Entry<Locale, NodeRef> entry : translationNodeRef.entrySet())
{
Locale locale = entry.getKey();
NodeRef nodeRef = entry.getValue();
// create a map node representation of the translation
MapNode mapNode = new MapNode(nodeRef);
String lgge = (locale != null) ?
// convert the locale into new ISO codes
contentFilterLanguagesService.convertToNewISOCode(locale.getLanguage()).toUpperCase()
: null;
mapNode.put("name", nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
mapNode.put("language", lgge);
mapNode.put("url", DownloadContentServlet.generateBrowserURL(nodeRef, mapNode.getName()));
mapNode.put("notEmpty", new Boolean(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)));
// add the client side version to the list
translations.add(mapNode);
}
return translations;
}
/**
* Returns a list of objects representing the versions of the
* current document
*
* @return List of previous versions
*/
public List getVersionHistory()
{
List<MapNode> versions = new ArrayList<MapNode>();
for (Version version : this.versionHistory.getAllVersions())
{
// create a map node representation of the version
MapNode clientVersion = new MapNode(version.getFrozenStateNodeRef());
clientVersion.put("versionLabel", version.getVersionLabel());
clientVersion.put("notes", version.getDescription());
clientVersion.put("author", version.getCreator());
clientVersion.put("versionDate", version.getCreatedDate());
if(getFrozenStateDocument().hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
clientVersion.put("url", null);
}
else
{
clientVersion.put("url", DownloadContentServlet.generateBrowserURL(version.getFrozenStateNodeRef(),
clientVersion.getName()));
}
// add the client side version to the list
versions.add(clientVersion);
}
return versions;
}
/**
* @return true if the version is a translation of a previous edition
*/
public boolean isFromPreviousEditon()
{
return fromPreviousEditon;
}
/**
* Returns the URL to download content for the current document
*
* @return Content url to download the current document
*/
public String getUrl()
{
return DownloadContentServlet.generateBrowserURL(getFrozenStateNodeRef(), getName());
}
/**
* @return the versioned node selected by the user
*/
public Node getFrozenStateDocument()
{
return new Node(getFrozenStateNodeRef());
}
/**
* @return the versioned node ref selected by the user
*/
public NodeRef getFrozenStateNodeRef()
{
return documentVersion.getFrozenStateNodeRef();
}
/**
* @return the edition of the mlContainer of the selected verion of the translation
*/
public Node getMultilingualContainerDocument()
{
return new Node(documentEdition.getFrozenStateNodeRef());
}
/**
* @return the name of selected version
*/
public String getName()
{
String name = (String) nodeService.getProperty(getFrozenStateNodeRef(), ContentModel.PROP_NAME);
return name;
}
/**
* @return the file type image URL of the version
*/
public String getFileType32()
{
String fileType = Utils.getFileTypeImage(getName(), false);
return fileType;
}
public boolean isEmptyTranslation()
{
return nodeService.hasAspect(getFrozenStateNodeRef(), ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
}
/**
* @return the version to display of the document selected by the user
*/
public Version getVersion()
{
return this.documentVersion;
}
/**
* @return the next page to display according to which page the dialog is coming from
*/
public String getOutcome()
{
return (this.fromPreviousEditon) ? "showMLContainerDetails" : "showDocDetails";
}
/**
* Util method which remove the eventual '(actual)' label from the version label.
*/
private String cleanVersionLabel(String versionLabel)
{
// remove the (actual vesrion) label if needed
int idx = versionLabel.indexOf(' ');
if(idx > -1)
{
versionLabel = versionLabel.substring(0, idx);
}
return versionLabel;
}
/**
* Util method which returns the given version of a node
*/
private Version getBrowsingVersionForDocument(NodeRef document, String versionLabel)
{
return this.versionService.getVersionHistory(document).getVersion(versionLabel);
}
/**
* Util method which returns the current version of a node
*/
private Version getBrowsingCurrentVersionForMLContainer(NodeRef document, String lang)
{
NodeRef translation = multilingualContentService.getTranslationForLocale(document, I18NUtil.parseLocale(lang));
this.versionHistory = versionService.getVersionHistory(translation);
return versionService.getCurrentVersion(translation);
}
/**
* Util method which return the last version of a translation of a given edition of a mlContainer according its language
*/
@SuppressWarnings("unchecked")
private Version getBrowsingVersionForMLContainer(NodeRef document, String editionLabel, String lang)
{
// get the list of translations of the given edition of the mlContainer
List<VersionHistory> translations = editionService.getVersionedTranslations(this.documentEdition);
// if translation size == 0, the edition is the current edition and the translations are not yet attached.
if(translations.size() == 0)
{
// the selection edition is the current.
return getBrowsingCurrentVersionForMLContainer(document, lang);
}
else
{
Version versionToReturn = null;
// get the last version of the translation in the given lang of the edition
for (VersionHistory history : translations)
{
// get the list of versions and sort them ascending according their version label
List<Version> orderedVersions = new ArrayList<Version>(history.getAllVersions());
Collections.sort(orderedVersions, VERSION_LABEL_COMPARATOR);
// the last version is the first version of the list
Version lastVersion = orderedVersions.get(0);
if(lastVersion != null)
{
Map<QName, Serializable> properties = editionService.getVersionedMetadatas(lastVersion);
Locale locale = (Locale) properties.get(ContentModel.PROP_LOCALE);
if(locale.getLanguage().equalsIgnoreCase(lang))
{
versionToReturn = lastVersion;
this.versionHistory = history;
break;
}
}
}
return versionToReturn;
}
}
/**
* @param versionService the Version Service to set
*/
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
/**
* @param editionService the Edition Service to set
*/
public void setEditionService(EditionService editionService)
{
this.editionService = editionService;
}
/**
* @param nodeService the Node Service to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param contentFilterLanguagesService the Content Filter Languages Service to set
*/
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
{
this.contentFilterLanguagesService = contentFilterLanguagesService;
}
/**
* @param Multilingual Content Service the Multilingual Content Service to set
*/
public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
}

View File

@@ -15,11 +15,11 @@
* 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:
* 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.web.bean.clipboard;
@@ -35,6 +35,7 @@ import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -52,20 +53,20 @@ import org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem;
/**
* Class representing a 'workspace' store protocol clipboard item
*
*
* @author Kevin Roast
*/
public class WorkspaceClipboardItem extends AbstractClipboardItem
{
private static final String WORKSPACE_PASTE_VIEW_ID = "/jsp/browse/browse.jsp";
private static final String AVM_PASTE_VIEW_ID = "/jsp/wcm/browse-sandbox.jsp";
private static final String MSG_LINK_TO = "link_to";
// File extension to use for link nodes
private static final String LINK_NODE_EXTENSION = ".url";
/**
* @param ref
* @param mode
@@ -74,7 +75,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
{
super(ref, mode);
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#supportsLink()
*/
@@ -82,7 +83,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
{
return true;
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#canCopyToViewId(java.lang.String)
*/
@@ -109,28 +110,31 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
{
NavigationBean navigator = (NavigationBean)FacesHelper.getManagedBean(fc, NavigationBean.BEAN_NAME);
NodeRef destRef = new NodeRef(Repository.getStoreRef(), navigator.getCurrentNodeId());
DictionaryService dd = getServiceRegistry().getDictionaryService();
NodeService nodeService = getServiceRegistry().getNodeService();
FileFolderService fileFolderService = getServiceRegistry().getFileFolderService();
CopyService copyService = getServiceRegistry().getCopyService();
MultilingualContentService multilingualContentService = getServiceRegistry().getMultilingualContentService();
// TODO: Should we be using primary parent here?
// We are assuming that the item exists in only a single parent and that the source for
// the clipboard operation (e.g. the source folder) is specifically that parent node.
// So does not allow for more than one possible parent node - or for linked objects!
// This code should be refactored to use a parent ID when appropriate.
// This code should be refactored to use a parent ID when appropriate.
ChildAssociationRef assocRef = nodeService.getPrimaryParent(getNodeRef());
// initial name to attempt the copy of the item with
String name = getName();
String translationPrefix = "";
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
{
// copy as link was specifically requested by the user
String linkTo = Application.getMessage(fc, MSG_LINK_TO);
String linkTo = Application.getMessage(fc, MSG_LINK_TO);
name = linkTo + ' ' + name;
}
boolean operationComplete = false;
while (operationComplete == false)
{
@@ -147,7 +151,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
// LINK operation
if (logger.isDebugEnabled())
logger.debug("Attempting to link node ID: " + getNodeRef() + " into node: " + destRef.toString());
// we create a special Link Object node that has a property to reference the original
// create the node using the nodeService (can only use FileFolderService for content)
if (checkExists(name + LINK_NODE_EXTENSION, destRef) == false)
@@ -164,7 +168,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
assocRef.getQName(),
ApplicationModel.TYPE_FILELINK,
props);
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(2, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, name);
@@ -180,7 +184,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
assocRef.getQName(),
ApplicationModel.TYPE_FOLDERLINK,
props);
// apply the uifacets aspect - icon, title and description props
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4, 1.0f);
uiFacetsProps.put(ApplicationModel.PROP_ICON, "space-icon-link");
@@ -188,7 +192,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, name);
nodeService.addAspect(childRef.getChildRef(), ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
}
// if we get here without an exception, the clipboard link operation was successful
operationComplete = true;
}
@@ -198,7 +202,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
// COPY operation
if (logger.isDebugEnabled())
logger.debug("Attempting to copy node: " + getNodeRef() + " into node ID: " + destRef.toString());
// first check that we are not attempting to copy a duplicate into the same parent
if (destRef.equals(assocRef.getParentRef()) && name.equals(getName()))
{
@@ -206,7 +210,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
String copyOf = Application.getMessage(fc, MSG_COPY_OF);
name = copyOf + ' ' + name;
}
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
@@ -216,6 +220,11 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
destRef,
name);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.copyTranslationContainer(getNodeRef(), destRef, translationPrefix);
}
else
{
// copy the node
@@ -229,7 +238,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
true);
}
}
// if we get here without an exception, the clipboard copy operation was successful
operationComplete = true;
}
@@ -239,7 +248,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
// MOVE operation
if (logger.isDebugEnabled())
logger.debug("Attempting to move node: " + getNodeRef() + " into node ID: " + destRef.toString());
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
@@ -249,6 +258,11 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
destRef,
name);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.moveTranslationContainer(getNodeRef(), destRef);
}
else
{
// move the node
@@ -258,7 +272,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
ContentModel.ASSOC_CONTAINS,
assocRef.getQName());
}
// if we get here without an exception, the clipboard move operation was successful
operationComplete = true;
}
@@ -266,7 +280,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
catch (FileExistsException fileExistsErr)
{
if (getMode() != ClipboardStatus.COPY)
{
{
// we should not rename an item when it is being moved - so exit
throw fileExistsErr;
}
@@ -284,6 +298,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
String copyOf = Application.getMessage(fc, MSG_COPY_OF);
name = copyOf + ' ' + name;
translationPrefix = copyOf + ' ' + translationPrefix;
}
else
{
@@ -297,15 +312,15 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
else if (AVM_PASTE_VIEW_ID.equals(viewId))
{
AVMBrowseBean avmBrowseBean = (AVMBrowseBean)FacesHelper.getManagedBean(fc, AVMBrowseBean.BEAN_NAME);
String destPath = avmBrowseBean.getCurrentPath();
NodeRef destRef = AVMNodeConverter.ToNodeRef(-1, destPath);
CrossRepositoryCopyService crossRepoCopyService = getServiceRegistry().getCrossRepositoryCopyService();
// initial name to attempt the copy of the item with
String name = getName();
boolean operationComplete = false;
while (operationComplete == false)
{
@@ -320,10 +335,10 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
// COPY operation
if (logger.isDebugEnabled())
logger.debug("Attempting to copy node: " + getNodeRef() + " into node ID: " + destRef.toString());
// inter-store copy operation
crossRepoCopyService.copy(getNodeRef(), destRef, name);
// if we get here without an exception, the clipboard copy operation was successful
operationComplete = true;
}
@@ -336,7 +351,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
catch (FileExistsException fileExistsErr)
{
if (getMode() != ClipboardStatus.COPY)
{
{
// we should not rename an item when it is being moved - so exit
throw fileExistsErr;
}

View File

@@ -15,11 +15,11 @@
* 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:
* 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.web.bean.content;
@@ -28,6 +28,8 @@ import java.text.MessageFormat;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
@@ -37,16 +39,20 @@ import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Delete Content" dialog
*
*
* @author gavinc
*/
public class DeleteContentDialog extends BaseDialogBean
{
protected MultilingualContentService multilingualContentService;
private static final Log logger = LogFactory.getLog(DeleteContentDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
@@ -55,31 +61,43 @@ public class DeleteContentDialog extends BaseDialogBean
Node node = this.browseBean.getDocument();
if (node != null)
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete content node: " + node.getId());
// delete the node
this.nodeService.deleteNode(node.getNodeRef());
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(node.getType()))
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete multilingual container: " + node.getId() + " and its translations" );
// delete the mlContainer and its translations
multilingualContentService.deleteTranslationContainer(node.getNodeRef());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete content node: " + node.getId());
// delete the node
this.nodeService.deleteNode(node.getNodeRef());
}
}
else
{
logger.warn("WARNING: delete called without a current Document!");
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// clear action context
this.browseBean.setDocument(null);
// setting the outcome will show the browse view again
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
@Override
protected String getErrorMessageId()
{
@@ -91,21 +109,51 @@ public class DeleteContentDialog extends BaseDialogBean
{
return false;
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Returns the confirmation to display to the user before deleting the content.
*
*
* @return The formatted message to display
*/
public String getConfirmMessage()
{
String fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_confirm");
return MessageFormat.format(fileConfirmMsg,
new Object[] {this.browseBean.getDocument().getName()});
String fileConfirmMsg = null;
Node document = this.browseBean.getDocument();
if(document.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_ml_container_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_empty_translation_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_translation_confirm");
}
else
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_confirm");
}
return MessageFormat.format(fileConfirmMsg,
new Object[] {document.getName()});
}
/**
* @param multilingualContentService the Multilingual Content Service to set
*/
public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
}

View File

@@ -31,13 +31,9 @@ import javax.faces.model.SelectItem;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.UserPreferencesBean;
import org.alfresco.web.bean.content.AddContentDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.Utils;
/**
* Dialog bean to upload a new document and to add it to an existing MLContainer.
@@ -81,31 +77,11 @@ public class AddTranslationDialog extends AddContentDialog
{
// add the new file to the repository
outcome = super.finishImpl(context, outcome);
// add a new translation
multilingualContentService.addTranslation(this.createdNode, this.mlTranslation, I18NUtil.parseLocale(this.language));
// Get the content data of the translation
ContentData contentData = fileFolderService.getReader(this.createdNode).getContentData();
Node createdNode = new Node(this.createdNode);
Map<String, Object> browseProp = createdNode.getProperties();
browseProp.put("size", contentData.getSize());
browseProp.put("mimetype", contentData.getMimetype());
browseProp.put("cm:content", contentData);
browseProp.put("fileType32", Utils.getFileTypeImage(createdNode.getName(), false));
browseProp.put("url", DownloadContentServlet.generateDownloadURL(this.createdNode, createdNode.getName()));
this.browseBean.setDocument(createdNode);
return outcome;
}
@Override
protected String getDefaultFinishOutcome()
{
return "showDocDetails";
return "browse";
}
@Override

View File

@@ -33,13 +33,10 @@ import javax.faces.model.SelectItem;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.UserPreferencesBean;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.Utils;
/**
* Dialog bean to add a new translation without content. I means, a new node is created
@@ -55,23 +52,22 @@ public class AddTranslationWithoutContentDialog extends BaseDialogBean
// the translation being to be created
protected NodeRef newTranslation;
private String name;
private String title;
private String description;
private String author;
private String language;
private boolean showOtherProperties;
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
name = null;
title = null;
description = null;
author = null;
language = null;
showOtherProperties = true;
}
@Override
@@ -84,29 +80,23 @@ public class AddTranslationWithoutContentDialog extends BaseDialogBean
Locale locale = I18NUtil.parseLocale(language);
// add the empty translation
newTranslation = multilingualContentService.addEmptyTranslation(refNode, name, locale);
newTranslation = multilingualContentService.addEmptyTranslation(refNode, null, locale);
// set the properties
nodeService.setProperty(newTranslation, ContentModel.PROP_DESCRIPTION, description);
nodeService.setProperty(newTranslation, ContentModel.PROP_AUTHOR, author);
nodeService.setProperty(newTranslation, ContentModel.PROP_TITLE, title);
// Get the content data of the new translation
ContentData newTranslationContentData = fileFolderService.getReader(newTranslation).getContentData();
// set the current browse node
Node browse = new Node(newTranslation);
Map<String, Object> browseProp = browse.getProperties();
browseProp.put("size", newTranslationContentData.getSize());
browseProp.put("mimetype", newTranslationContentData.getMimetype());
browseProp.put("cm:content", newTranslationContentData);
browseProp.put("fileType32", Utils.getFileTypeImage(name, false));
browseProp.put("url", DownloadContentServlet.generateDownloadURL(newTranslation, name));
this.browseBean.setDocument(browse);
return outcome;
// redirect the user according the value of (show other properties)
if(showOtherProperties)
{
this.browseBean.setDocument(new Node(this.newTranslation));
return "dialog:setContentProperties";
}
else
{
return "browse";
}
}
/**
@@ -173,22 +163,6 @@ public class AddTranslationWithoutContentDialog extends BaseDialogBean
this.language = language;
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return the title
*/
@@ -212,4 +186,20 @@ public class AddTranslationWithoutContentDialog extends BaseDialogBean
{
return userPreferencesBean.getAvailablesContentFilterLanguages(this.browseBean.getDocument().getNodeRef(), false);
}
/**
* @return the showOtherProperties
*/
public boolean isShowOtherProperties()
{
return showOtherProperties;
}
/**
* @param showOtherProperties the showOtherProperties to set
*/
public void setShowOtherProperties(boolean showOtherProperties)
{
this.showOtherProperties = showOtherProperties;
}
}

View File

@@ -15,11 +15,11 @@
* 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:
* 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.web.bean.ml;
@@ -29,6 +29,7 @@ import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -38,7 +39,7 @@ import org.alfresco.web.bean.repository.Node;
/**
* Dialog bean to edit an existing multilingual container.
*
*
* @author Yannick Pignot
*/
public class EditMLContainerDialog extends BaseDialogBean
@@ -69,7 +70,7 @@ public class EditMLContainerDialog extends BaseDialogBean
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
{
// get the container node ref
NodeRef container = editableNode.getNodeRef();
@@ -92,10 +93,20 @@ public class EditMLContainerDialog extends BaseDialogBean
*/
protected Node initEditableNode()
{
return new Node(
multilingualContentService.getTranslationContainer(
this.browseBean.getDocument().getNodeRef())
);
Node currentNode = this.browseBean.getDocument();
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(currentNode.getType()))
{
return currentNode;
}
else
{
return new Node(
multilingualContentService.getTranslationContainer(
currentNode.getNodeRef())
);
}
}
/**

View File

@@ -0,0 +1,154 @@
/*
* 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.web.bean.ml;
import java.util.Locale;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
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.security.PermissionService;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Node;
/**
* Util class for the management of multilingual documents on the web client side
*
* @author yanipig
*/
public class MultilingualUtils
{
/**
* Returns true if the current user has enough right to add a content to the space
* where the pivot translation is located in.
*
* @param multlingualDocument
* @param fc
* @return
*/
public static boolean canAddChildrenToPivotSpace(Node multlingualDocument, FacesContext fc)
{
MultilingualContentService mlservice = getMultilingualContentService(fc);
NodeService nodeService = getNodeService(fc);
// get the pivot translation and get the space where it's located
NodeRef pivot = mlservice.getPivotTranslation(multlingualDocument.getNodeRef());
NodeRef space = nodeService.getPrimaryParent(pivot).getParentRef();
// return if the current user can add a content to the space of the pivot
return new Node(space).hasPermission(PermissionService.ADD_CHILDREN);
}
/**
* Returns true if the current user can delete each translation of the mlContainer of the given node
*
* @param multlingualDocument
* @param fc
* @return
*/
public static boolean canDeleteEachTranslation(Node multlingualDocument, FacesContext fc)
{
boolean can = true;
MultilingualContentService mlservice = getMultilingualContentService(fc);
Map<Locale, NodeRef> translations = mlservice.getTranslations(multlingualDocument.getNodeRef());
for (Map.Entry<Locale, NodeRef> entry : translations.entrySet())
{
Node translation = new Node(entry.getValue());
if(translation.hasPermission(PermissionService.DELETE_NODE) == false
|| translation.isLocked() == true
|| translation.hasAspect(ContentModel.ASPECT_WORKING_COPY) == true
)
{
can = false;
break;
}
}
return can;
}
/**
* Returns true if the current user can move each translation of the mlContainer of the given node
*
* @param multlingualDocument
* @param fc
* @return
*/
public static boolean canMoveEachTranslation(Node multlingualDocument, FacesContext fc)
{
boolean can = true;
MultilingualContentService mlservice = getMultilingualContentService(fc);
Map<Locale, NodeRef> translations = mlservice.getTranslations(multlingualDocument.getNodeRef());
for (Map.Entry<Locale, NodeRef> entry : translations.entrySet())
{
Node translation = new Node(entry.getValue());
if(translation.hasPermission(PermissionService.DELETE_NODE) == false)
{
can = false;
break;
}
}
return can;
}
/**
* Returns true if the current user can delete each translation and create
* * a new content in the space
*
* @param multlingualDocument
* @param fc
* @return
*/
public static boolean canStartNewEditon(Node multlingualDocument, FacesContext fc)
{
boolean canDelete = MultilingualUtils.canMoveEachTranslation(multlingualDocument, fc);
boolean canCreate = MultilingualUtils.canAddChildrenToPivotSpace(multlingualDocument, fc);
return canDelete && canCreate;
}
private static MultilingualContentService getMultilingualContentService(FacesContext fc)
{
return (MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
}
private static NodeService getNodeService(FacesContext fc)
{
return (NodeService) FacesHelper.getManagedBean(fc, "NodeService");
}
}

View File

@@ -32,8 +32,11 @@ import java.util.Locale;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.lock.LockService;
@@ -44,36 +47,47 @@ 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.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.util.ParameterCheck;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.wizard.BaseWizardBean;
import org.alfresco.web.ui.common.component.UIActionLink;
/**
* Wizard bean to create a new edition from an existing MLContainer.
*
* @author yanipig
* @author Yanick Pignot
*/
public class NewEditionWizard extends BaseWizardBean
{
public static final String ID_MESSAGE_MINOR_CHANGE = "minor_change";
public static final String ID_MESSAGE_MAJOR_CHANGE = "major_change";
protected EditionService editionService;
protected MultilingualContentService multilingualContentService;
protected ContentFilterLanguagesService contentFilterLanguagesService;
protected LockService lockService;
protected VersionService versionService;
protected NodeRef mlContainerToVersion;
private List<SelectItem> selectableTranslations;
private String startingItemNodeString;
private List<TranslationWrapper> selectableTranslations;
private List<TranslationWrapper> translationsCheckedOut;
private String editionNotes;
private boolean minorChange;
private boolean otherProperties;
private List<SelectItem> translationCheckedOut;
private boolean skipFirstStep;
private String language;
private String title;
private String author;
private boolean hasTranslationCheckedOut;
private NodeRef startingElement;
private String author;
private String selectedLanguage;
@Override
public void init(Map<String, String> parameters)
@@ -81,32 +95,50 @@ public class NewEditionWizard extends BaseWizardBean
super.init(parameters);
// reset the fileds
startingItemNodeString = null;
editionNotes = null;
minorChange = true;
otherProperties = false;
translationCheckedOut = null;
language = "lang";
title = "title";
author = "author";
translationsCheckedOut = null;
selectableTranslations = null;
// set the mlContainer to version
NodeRef currentNodeRef = this.browseBean.getDocument().getNodeRef();
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(currentNodeRef)))
if(!skipFirstStep)
{
mlContainerToVersion = currentNodeRef;
}
else
{
mlContainerToVersion = multilingualContentService.getTranslationContainer(currentNodeRef);
// this properties is set by the skipFirstStep action event method.
language = null;
title = null;
// set the current mlContainer
setMLContainer();
}
translationCheckedOut = getTranslationCheckedOut();
hasTranslationCheckedOut = getHasTranslationCheckedOut();
// init the list of the available translations and the list of translations checked out
initTranslationList();
// true if they are at leat one translation checked out
hasTranslationCheckedOut = this.translationsCheckedOut.size() > 0;
}
/**
* Force the the lang of the new pivot translation for the new edition and skip the first step
*/
public void skipFirstStep(ActionEvent event)
{
skipFirstStep = true;
// Get the lang of the new
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String lang = params.get("lang");
// test if the parameter is valid
ParameterCheck.mandatoryString("The lang of the node", lang);
// set the current mlContainer
setMLContainer();
setStartingItem(lang.toLowerCase());
}
@Override
@@ -127,6 +159,7 @@ public class NewEditionWizard extends BaseWizardBean
// create the edition and get the reference of the new starting translation
NodeRef newPivot = editionService.createEdition(startingElement, versionProperties);
// redirect the user at the 'modify translation properties' page if desire.
if (otherProperties == true)
{
this.browseBean.setDocument(new Node(newPivot));
@@ -137,9 +170,30 @@ public class NewEditionWizard extends BaseWizardBean
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
skipFirstStep = false;
return outcome;
}
/**
* Returns the properties for checked out translations JSF DataModel
*
* @return JSF DataModel representing the translations checked out
*/
public DataModel getTranslationsCheckedOutDataModel()
{
return getDataModel(this.translationsCheckedOut);
}
/**
* Returns the properties for available translations JSF DataModel
*
* @return JSF DataModel representing the available translation for a new edition
*/
public DataModel getAvailableTranslationsDataModel()
{
return getDataModel(this.selectableTranslations);
}
/**
* Determines whether there are any translation checked out.
@@ -148,8 +202,6 @@ public class NewEditionWizard extends BaseWizardBean
*/
public boolean getHasTranslationCheckedOut()
{
hasTranslationCheckedOut = getTranslationCheckedOut().size() > 0;
return hasTranslationCheckedOut;
}
@@ -165,117 +217,94 @@ public class NewEditionWizard extends BaseWizardBean
return super.getNextButtonDisabled() || hasTranslationCheckedOut;
}
/**
* @param language of the starting translation to set as the new pivot of the new edition
*/
private void setStartingItem(String language)
{
// get the starting point translation with its locale
startingElement = multilingualContentService.getTranslationForLocale(mlContainerToVersion, I18NUtil.parseLocale(language));
// set the futur properties of the new starting element (only usefull for the summary step)
setLanguage(language);
setTitle((String) nodeService.getProperty(startingElement, ContentModel.PROP_TITLE));
setAuthor((String) nodeService.getProperty(startingElement, ContentModel.PROP_AUTHOR));
}
/**
* Return the list of cecked out document found in the mlContainer.
*
* @return the list of checked out translation
* Util metho which construct a data model with rows passed in parameter
*/
public List<SelectItem> getTranslationCheckedOut()
private DataModel getDataModel(Object rows)
{
if(translationCheckedOut == null )
DataModel translationDataModel = new ListDataModel();
translationDataModel.setWrappedData(rows);
return translationDataModel;
}
/**
* Util method which init the lists of translations
*/
private void initTranslationList()
{
this.translationsCheckedOut = new ArrayList<TranslationWrapper>();
this.selectableTranslations = new ArrayList<TranslationWrapper>();
// get all translations of the mlContainer
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainerToVersion);
// fill the data table rows list
for(Map.Entry<Locale, NodeRef> entry : translations.entrySet())
{
// first call, init the list
NodeRef nodeRef = entry.getValue();
this.translationCheckedOut = new ArrayList<SelectItem>();
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
String langCode = ((Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE)).getLanguage();
String langText = contentFilterLanguagesService.getLabelByCode(langCode);
String lockOwner = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCK_OWNER);
// get all translations of the mlContainer
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainerToVersion);
// create the row with the current translation
TranslationWrapper wrapper = new TranslationWrapper(name, langCode, lockOwner, langText);
// fill the select itms
for(Map.Entry<Locale, NodeRef> entry : translations.entrySet())
if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
NodeRef nodeRef = entry.getValue();
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE))
// add it to the selectable list if it is not empty
this.selectableTranslations.add(wrapper);
}
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE))
{
LockStatus lockStatus = lockService.getLockStatus(nodeRef);
if (lockStatus != LockStatus.NO_LOCK)
{
LockStatus lockStatus = lockService.getLockStatus(nodeRef);
if (lockStatus != LockStatus.NO_LOCK)
{
// if the node is locked, add it to the locked translation list
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
Locale lang = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
String lockOwner = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_WORKING_COPY_OWNER);
this.translationCheckedOut.add(new SelectItem(
"(" + lang.getLanguage() + ")",
name,
lockOwner
));
}
// if the node is locked, add it to the locked translation list
this.translationsCheckedOut.add(wrapper);
}
}
}
return this.translationCheckedOut;
}
}
/**
* Return the list of available translations to begin the starting translations of the new edition.
*
* @return the list of available translations
*/
public List<SelectItem> getSelectableTranslations()
private void setMLContainer()
{
if(selectableTranslations == null)
// set the mlContainer to version
NodeRef currentNodeRef = this.browseBean.getDocument().getNodeRef();
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(currentNodeRef)))
{
// first call, init the list
selectableTranslations = new ArrayList<SelectItem>();
// get all translations of the mlContainer
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainerToVersion);
// fill the select items
for(Map.Entry<Locale, NodeRef> entry : translations.entrySet())
{
NodeRef nodeRef = entry.getValue();
//add each non empty translation
if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
Locale lang = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
selectableTranslations.add(new SelectItem(
nodeRef.toString(),
name + " - " + contentFilterLanguagesService.getLabelByCode(lang.getLanguage())
));
}
}
mlContainerToVersion = currentNodeRef;
}
else
{
mlContainerToVersion = multilingualContentService.getTranslationContainer(currentNodeRef);
}
return selectableTranslations;
}
/**
* @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;
}
/**
* @param editionService the Edition Service to set
*/
public void setEditionService(EditionService editionService)
{
this.editionService = editionService;
if(!skipFirstStep)
{
// init the pivot language (it will be selected by default)
selectedLanguage = ((Locale) nodeService.getProperty(mlContainerToVersion, ContentModel.PROP_LOCALE)).getLanguage();
}
}
/**
@@ -326,49 +355,6 @@ public class NewEditionWizard extends BaseWizardBean
this.otherProperties = otherProperties;
}
/**
* @return the starting translation being the new pivot of tne new edition
*/
public String getStartingItemNodeString()
{
return startingItemNodeString;
}
/**
* @param startingItemNodeString the starting translation to set as the new pivot of tne new edition
*/
public void setStartingItemNodeString(String startingItemNodeString)
{
// get the starting point translation with its id
startingElement = new NodeRef(startingItemNodeString);
// set the futur properties of the new starting element (only usefull for the summary step)
setLanguage((Locale) nodeService.getProperty(startingElement, ContentModel.PROP_LOCALE));
setAuthor((String) nodeService.getProperty(startingElement, ContentModel.PROP_AUTHOR));
setTitle((String) nodeService.getProperty(startingElement, ContentModel.PROP_TITLE));
this.startingItemNodeString = startingItemNodeString;
}
/**
* @param contentFilterLanguagesService the Content Filter Languages Service to set
*/
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
{
this.contentFilterLanguagesService = contentFilterLanguagesService;
}
/**
* @param lockService the Lock Service to set
*/
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
/**
* @return the author
*/
@@ -378,21 +364,12 @@ public class NewEditionWizard extends BaseWizardBean
}
/**
* @param author the author to set
*/
public void setAuthor(String author)
{
this.author = author;
}
/**
* @return the language
*/
public String getLanguage()
{
return language;
return contentFilterLanguagesService.getLabelByCode(language);
}
@@ -429,19 +406,170 @@ public class NewEditionWizard extends BaseWizardBean
this.title = title;
}
/**
* @param author the author to set
*/
public void setAuthor(String author)
{
this.author = author;
}
/**
* @return the versionLabel
*/
public String getVersionLabel()
{
String toReturn = "Version Label";
String label = versionService.getCurrentVersion(mlContainerToVersion).getVersionLabel();
String nextLabel = null;
try
{
int dotPosition = label.indexOf('.');
int major = Integer.parseInt(label.substring(0, dotPosition));
int minor = Integer.parseInt(label.substring(dotPosition + 1));
if(minorChange)
{
nextLabel = major + "." + (minor + 1);
}
else
{
nextLabel = (major + 1) + ".0";
}
}
catch(Exception e)
{
nextLabel = "";
}
if(minorChange)
{
toReturn += " (minor change)";
String minorString = Application.getMessage(
FacesContext.getCurrentInstance(),
ID_MESSAGE_MINOR_CHANGE);
return nextLabel + " (" + minorString + ')' ;
}
else
{
return nextLabel;
}
}
/**
* @return the selectedTranslationLanguage
*/
public String getSelectedTranslationLanguage()
{
return selectedLanguage;
}
/**
* @param selectedTranslationLanguage the selectedTranslationLanguage to set
*/
public void setSelectedTranslationLanguage(String language)
{
// only the selected language is not set as null
if(language != null)
{
setStartingItem(language);
}
return toReturn;
}
/**
* @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;
}
/**
* @param contentFilterLanguagesService the Content Filter Languages Service to set
*/
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
{
this.contentFilterLanguagesService = contentFilterLanguagesService;
}
/**
* @param lockService the Lock Service to set
*/
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
/**
* @param editionService the Edition Service to set
*/
public void setEditionService(EditionService editionService)
{
this.editionService = editionService;
}
/**
* @param versionService the version Service to set
*/
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
/**
* Simple wrapper class to represent a translation in the data table
*/
public static class TranslationWrapper
{
private String language;
private String name;
private String checkedOutBy;
private String languageLabel;
public TranslationWrapper(String name, String language, String checkedOutBy, String languageLabel)
{
this.name = name;
this.language = language;
this.checkedOutBy = checkedOutBy;
this.languageLabel = languageLabel;
}
public String getCheckedOutBy()
{
return checkedOutBy;
}
public String getLanguage()
{
return language;
}
public String getName()
{
return name;
}
public String getLanguageLabel()
{
return this.languageLabel;
}
}
}