
com.day.cq.dam.commons.util.DamLanguageUtil Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2015 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
/**
* AdobePatentID="P6809-US"
*/
package com.day.cq.dam.commons.util;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import com.adobe.granite.asset.api.AssetRelation;
import com.adobe.granite.confmgr.Conf;
import com.adobe.granite.translation.core.MachineTranslationCloudConfig;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkflowData;
import com.adobe.granite.workflow.model.WorkflowModel;
import com.day.cq.dam.api.Rendition;
import com.day.cq.wcm.api.WCMException;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.apache.sling.resource.collection.ResourceCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.commons.Language;
import com.day.cq.commons.LanguageUtil;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.PageManagerFactory;
import com.day.text.Text;
import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT;
import static com.day.cq.commons.jcr.JcrConstants.JCR_LASTMODIFIED;
import static com.day.cq.commons.jcr.JcrConstants.JCR_TITLE;
import static com.day.cq.commons.jcr.JcrConstants.NT_FOLDER;
/**
* This class provides utility method for Language Copy used by sites
*/
public class DamLanguageUtil {
private static final Logger log = LoggerFactory.getLogger(DamLanguageUtil.class);
private static final String UPDATE_ASSET_WORKFLOW_MODEL = "/var/workflow/models/dam/update_asset";
private static final String ATTRIBUTE_DESTINATION_LANGUAGE_COPY_PATH = "dam:destinationLanguageCopy";
private static final String ATTRIBUTE_EXTRACT_METADATA = "dam:extractMetadata";
private static final String ATTRIBUTE_SMART_ASSET_UPDATE_SOURCE = "dam:smartAssetUpdateSource";
private static final String ATTRIBUTE_SMART_ASSET_UPDATE_REQUIRED = "dam:smartAssetUpdateRequired";
private static final String ATTRIBUTE_CLOUD_CONFIG_PROPERTY = "cq:cloudserviceconfigs";
private static final String ATTRIBUTE_CA_CONFIG_PROPERTY = "cq:conf";
private static final String ATTRIBUTE_CQ_TRANSLATION_SOURCE_PATH = "cq:translationSourcePath";
private static final String CACONFIG_ROOT = "/conf";
private static final String CACONFIG_GLOBAL = CACONFIG_ROOT + "/global";
private static final String CACONFIG_TRANSLATIONCFG_PATH = "cloudconfigs/translation/translationcfg";
private static final String DEFAULT_LANGUAGES_HOME = "wcm/core/resources/languages";
private static final String ASSET_PERFORMANCE_NODE_RELATIVE_PATH = "/" + JCR_CONTENT + "/" + "performance";
private static final String ASSET_USAGE_NODE_RELATIVE_PATH = "/" + JCR_CONTENT + "/" + DamConstants.USAGES_FOLDER;
private static final String ASSET_VERSION_MESSAGE = "Created by Asset Update Translation";
private static final String ASSOCIATED_CONTENT_RELATIVE_PATH = JcrConstants.JCR_CONTENT + "/associated";
private static final String ASSOCIATED_CONTENT_CHILD = "associated";
private static final String CONTENT_FRAGMENT = "contentFragment";
private static final String ATTRIBUTE_ASSET_DERIVED_RELATION = "derived";
private static final String ATTRIBUTE_ASSET_OTHERS_RELATION = "others";
private static final String MIME_TYPE_HTML = "text/html";
private static final int MAX_DIFF_MILLISECOND_CHANGED = 2000; // max diff allowed in difference is 2sec
public static final String ATTRIBUTE_ASSET_LINKS_RELATION = "links";
public static final String ATTRIBUTE_ASSET_SOURCE_RELATION = "sources";
public static final String ATTRIBUTE_ASSET_UPDATE_REQUIRED = "dam:assetUpdateRequired";
public static final String ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY = "dam:collectionSourceLanguageCopy";
public static final String CQ_LASTMODIFIED = "cq:lastModified";
public static final String ATTRIBUTE_CQ_TRANSLATION_LAST_UPDATE = "cq:lastTranslationUpdate";
/**
* Category for translation while creating and updating language copies. This is a list of all possible language
* copy locations.
*/
private enum TranslationCategory {
/**
* Language copy translation is not required.
*/
NONE,
/**
* Destination Language copy needs to be created or updated.
*/
DESTINATION,
/**
* Temporary Language copies are required.
*/
TEMPORARY
}
/**
* This method returns true if language copy of an asset exists, for the
* asked locale
*
* @param assetPath The path of an asset for which language copy is asked
* @param languageCode Language for which language copy is asked
* @param resolver ResourceResolver
* @return
*/
public static boolean hasLanguageCopy(final String assetPath,
final String languageCode, final ResourceResolver resolver) {
Asset asset = findLanguageCopy(assetPath, languageCode, resolver);
if (asset != null) return true;
return false;
}
/**
* This method returns the Language copy asset if language copy exists, for
* the asked locale
*
* @param assetPath The path of an asset for which language copy is asked
* @param languageCode Language for which language copy is asked
* @param resolver ResourceResolver
* @return
*/
public static Asset getLanguageCopy(final String assetPath,
final String languageCode, final ResourceResolver resolver) {
return findLanguageCopy(assetPath, languageCode, resolver);
}
/**
* This method creates language copy of an asset/folder
*
* @param resourceResolver
* @param pageManagerFactory
* @param sourcePath - source for creating language copy
* @param targetLanguageCodes - array of language codes
* @return
*/
public static List createLanguageCopy(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String sourcePath, final String[] targetLanguageCodes) {
Session session = resourceResolver.adaptTo(Session.class);
PageManager pageManager = pageManagerFactory.getPageManager(resourceResolver);
Resource sourceResource = resourceResolver.getResource(sourcePath);
List createdCopies = new ArrayList();
String contentPath = "";
if (targetLanguageCodes == null || targetLanguageCodes.length == 0 || targetLanguageCodes[0].trim().length() == 0) {
log.error("Failed to load destination language from payload.");
return createdCopies;
}
String root = LanguageUtil.getLanguageRoot(sourcePath);
String parentOfRoot = null;
boolean createNewLanguageRoot = false;
Node sourceLanguageRootNode = null;
Node sourceLRContentNode = null;
if (root == null) {
log.debug("Language root does not exist for asset at path: {} and would be created. ", sourcePath);
//CQ-61450 User creates a language copy of a page from sites and language root for the asset (referenced in site) does not exist
if (Text.getRelativeParent(sourcePath, 1).equals(DamConstants.MOUNTPOINT_ASSETS)) {
//Asset is directly under DamConstants.MOUNTPOINT_ASSETS
parentOfRoot = DamConstants.MOUNTPOINT_ASSETS;
root = DamConstants.MOUNTPOINT_ASSETS;
} else if (sourcePath.startsWith(DamConstants.MOUNTPOINT_ASSETS + "/")) {
//Asset follows structure DamConstants.MOUNTPOINT_ASSETS//
int parentOfRootPathLength = sourcePath.indexOf('/', DamConstants.MOUNTPOINT_ASSETS.length() + 1);
int oldRootPathLength = sourcePath.indexOf('/', parentOfRootPathLength);
if (parentOfRootPathLength < 0 || sourcePath.length() <= parentOfRootPathLength) {
return createdCopies;
}
parentOfRoot = sourcePath.substring(0, parentOfRootPathLength);
if (oldRootPathLength > 0 && sourcePath.length() > oldRootPathLength) {
root = sourcePath.substring(0, oldRootPathLength);
}
}
createNewLanguageRoot = true;
log.info("Parent of New Language root at path {} added for asset at path {}", parentOfRoot, sourcePath);
contentPath = sourcePath.replaceFirst(parentOfRoot, "");
} else {
contentPath = sourcePath.replaceFirst(root, "");
parentOfRoot = Text.getRelativeParent(root, 1);
}
for (int i = 0; i < targetLanguageCodes.length; i++) {
String targetPath = "";
String languageRootPath = "";
String strDestinationLanguage = getDestinationLanguageWithAllowedDelimiters(parentOfRoot,
targetLanguageCodes[i], resourceResolver);
languageRootPath = getDestinationLanguageRoot(parentOfRoot, strDestinationLanguage, resourceResolver);
targetPath = languageRootPath + contentPath;
try {
if (contentPath.trim().length() > 0) {
String pathToCreate = Text.getRelativeParent(
targetPath, 1);
String nodeType = "sling:Folder";
sourceLanguageRootNode = session.getNode(root);
sourceLRContentNode = sourceLanguageRootNode.getNode(JcrConstants.JCR_CONTENT);
if (sourceLanguageRootNode.isNodeType(
"sling:OrderedFolder")) {
nodeType = "sling:OrderedFolder";
}
JcrUtil.createPath(pathToCreate, nodeType,
nodeType, session, false);
}
if (!session.nodeExists(targetPath)) {
Resource destinationResource = pageManager.copy(sourceResource, targetPath, null, false,
false, false);
// Remove Derived, Others Relations from this resource, if any. Ensures that if this resource,
// is a source Asset then the derived, others relations don't point to old language copies
if (destinationResource != null) {
com.adobe.granite.asset.api.Asset destinationGraniteAsset = destinationResource.adaptTo(com.adobe.granite.asset.api.Asset.class);
if (destinationGraniteAsset != null) {
removeAssetRelation(destinationGraniteAsset, ATTRIBUTE_ASSET_DERIVED_RELATION);
removeAssetRelation(destinationGraniteAsset, ATTRIBUTE_ASSET_OTHERS_RELATION);
}
}
addTranslationSourcePath(destinationResource, sourceResource.getPath());
setLastTranslationUpdate(destinationResource);
deleteInsightData(destinationResource.getPath(), resourceResolver);
//changing the title and set the Cloud Configs (CQ-61476) on the language root folder
Node targetNode = session.getNode(languageRootPath);
if (targetNode != null) {
if (!targetNode.hasNode(JcrConstants.JCR_CONTENT)) {
targetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node content = targetNode.getNode(JcrConstants.JCR_CONTENT);
if (!content.hasProperty(JcrConstants.JCR_TITLE)) {
String displayLanguage = getLanguageDisplayName(resourceResolver, strDestinationLanguage);
content.setProperty(JcrConstants.JCR_TITLE, displayLanguage);
}
if (sourceLRContentNode != null) {
// Set the cq:conf property on target LR folder if the source language root folder has and target doesn't have it
if (!content.hasProperty(ATTRIBUTE_CA_CONFIG_PROPERTY) &&
sourceLRContentNode.hasProperty(ATTRIBUTE_CA_CONFIG_PROPERTY)) {
content.setProperty(ATTRIBUTE_CA_CONFIG_PROPERTY,
sourceLRContentNode.getProperty(ATTRIBUTE_CA_CONFIG_PROPERTY).getString());
}
// Set the cq:cloudserviceconfigs property on target LR folder if the source language root folder has and target doesn't have it
if (!content.hasProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY) &&
sourceLRContentNode.hasProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY)) {
content.setProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY,
sourceLRContentNode.getProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY).getValues());
}
}
//set JCR_TITLE and Cloud Configs (CQ-61476) for all folders in the created contentPath and language root
String tempAddTitlePath = contentPath.substring(0, contentPath.lastIndexOf('/'));
while (tempAddTitlePath.length() > 0) {
Node tempNode = session.getNode(languageRootPath + tempAddTitlePath);
if (tempNode != null) {
if (!tempNode.hasNode(JcrConstants.JCR_CONTENT)) {
tempNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node tempNodeContent = tempNode.getNode(JcrConstants.JCR_CONTENT);
String sourceNodeForTitle = null;
if (createNewLanguageRoot) {
sourceNodeForTitle = parentOfRoot + tempAddTitlePath;
} else {
sourceNodeForTitle = root + tempAddTitlePath;
}
if (!tempNodeContent.hasProperty(JcrConstants.JCR_TITLE)) {
String tempNodeTitle = UIHelper.getTitle(resourceResolver.getResource(sourceNodeForTitle));
tempNodeContent.setProperty(JcrConstants.JCR_TITLE, tempNodeTitle);
Node sourceNode = session.getNode(sourceNodeForTitle);
if (sourceNode != null) {
Node sourceContentNode = sourceNode.getNode(JcrConstants.JCR_CONTENT);
if (sourceContentNode != null) {
// Set the cq:conf property on this folder if relative folder in source path has and target doesn't have it
if (!tempNodeContent.hasProperty(ATTRIBUTE_CA_CONFIG_PROPERTY) &&
sourceContentNode.hasProperty(ATTRIBUTE_CA_CONFIG_PROPERTY)) {
tempNodeContent.setProperty(ATTRIBUTE_CA_CONFIG_PROPERTY,
sourceContentNode.getProperty(ATTRIBUTE_CA_CONFIG_PROPERTY).getString());
}
// Set the cq:cloudserviceconfigs property on this folder if relative folder in source path has and target doesn't have it
if (!tempNodeContent.hasProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY) &&
sourceContentNode.hasProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY)) {
tempNodeContent.setProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY,
sourceContentNode.getProperty(ATTRIBUTE_CLOUD_CONFIG_PROPERTY).getValues());
}
}
}
}
tempAddTitlePath = tempAddTitlePath.substring(0, tempAddTitlePath.lastIndexOf('/'));
}
}
}
} else {
log.info(
"Could not create language copy for assets at path: " + targetPath +
", resource already exists. Updating language copy.");
Asset sourceAsset = resourceResolver.getResource(sourcePath).adaptTo(Asset.class);
Asset targetAsset = resourceResolver.getResource(targetPath).adaptTo(Asset.class);
if (sourceAsset != null && targetAsset != null) {
if (isSmartAssetUpdateRequired(sourceAsset, targetAsset)) {
addSmartAssetUpdateSource(targetAsset, sourcePath);
addSmartAssetUpdateProperty(targetAsset, true);
} else {
addSmartAssetUpdateProperty(targetAsset, false);
}
}
}
createdCopies.add(targetPath);
} catch (Exception e) {
log.error(
"error while creating language copy for assets at path: "
+ targetPath + "{}", e);
}
}
return createdCopies;
}
private static void addTranslationSourcePath(Resource destinationResource, String translationSourcePath) throws
RepositoryException {
Node destNode = destinationResource.adaptTo(Node.class);
if (destinationResource != null) {
Node contentNode = destNode.getNode(JCR_CONTENT);
contentNode.setProperty(ATTRIBUTE_CQ_TRANSLATION_SOURCE_PATH, translationSourcePath);
}
}
private static Asset findLanguageCopy(final String assetPath,
final String languageCode, final ResourceResolver resolver) {
Resource assetResource = resolver.getResource(assetPath);
if (assetResource == null || assetResource.adaptTo(Asset.class) == null) {
return null;
}
Asset asset = null;
String languageRootPath = LanguageUtil.getLanguageRoot(assetPath);
if(languageRootPath == null){
return null;
}
String contentPath = assetPath.replaceFirst(languageRootPath, "");
String languageRootParentPath = Text.getRelativeParent(
languageRootPath, 1);
String destinationLanguageRootPath = getDestinationLanguageRoot(languageRootParentPath , languageCode,
resolver);
String assetPathLC = destinationLanguageRootPath + contentPath;
Resource assetResourceLC = resolver.getResource(assetPathLC);
if (assetResourceLC != null) {
asset = assetResourceLC.adaptTo(Asset.class);
}
return asset;
}
/**
* Returns the language root for the given asset path by only analyzing the
* path names starting at the root. For this implementation, language root
* for dam was suffix of folder name joined by "-" ex. geometrixx-en.
*
* @param path path
* @return the language root or null
if not found
*
* @deprecated since 6.2, use {@link com.day.cq.commons.LanguageUtil} instead
*/
@Deprecated
public static String getLanguageRoot(String path) {
throw new UnsupportedOperationException("This API has been deprecated.Please use com.day.cq.commons.LanguageUtil instead.");
}
/**
* Returns the language for the given asset path by only analyzing the
* path names starting at the root. For this implementation, language
* root for dam was suffix of folder name joined by "-" ex. geometrixx-en.
*
* @param path path
* @return the language or null
if not found
*
* @deprecated since 6.2, use {@link com.day.cq.commons.LanguageUtil} instead
*/
@Deprecated
public static Language getLanguage(String path) {
throw new UnsupportedOperationException("This API has been deprecated.Please use com.day.cq.commons.LanguageUtil instead.");
}
/**
* Modified version of com.day.cq.wcm.core.impl.LanguageManagerImpl for Resources
*
* Returns a collection of language root pages for the given asset. Note that
* only the path names are respected for the determination of the language.
*
* @param resolver resource resolver
* @param path path of the current page
* @return collection of language root paths
*/
public static Collection getLanguageRoots(ResourceResolver resolver, String path) {
Iterator resources = getLanguageRootSiblings(resolver, path);
if (resources == null) {
return Collections.emptySet();
}
List roots = new ArrayList();
while(resources.hasNext()) {
Resource res = resources.next();
Locale locale = getLocaleFromResource(res);
if (locale != null) {
roots.add(res);
}
}
Resource currentResource = resolver.getResource(path);
Resource langRoot = getLanguageRootResource(currentResource);
if (null != langRoot) {
Resource langRootParent = langRoot.getParent();
boolean additionalLanguageRootsFound = false;
//go one level down
Iterator iter = langRootParent.listChildren();
while (iter.hasNext()) {
Resource sibling = iter.next();
Locale locale = getLocaleFromResource(sibling);
if (locale == null) {
additionalLanguageRootsFound = addLanguageRootsFromChildren(roots,
additionalLanguageRootsFound, sibling);
}
}
if (additionalLanguageRootsFound) {
//found roots one level down, no need to go up. Therefore, return
return roots;
}
//one level up
//find language roots which are not language countries
Resource langRootGrandParent = langRootParent.getParent();
ArrayList nonLangRootUncles = new ArrayList();
if (langRootGrandParent != null) {
Iterator langRootUncles = langRootGrandParent.listChildren();
while (langRootUncles.hasNext()) {
Resource langRootUncle = langRootUncles.next();
if (langRootUncle.getName().equals(langRootParent.getName())) { //node comparison not working :(
//already added
continue;
}
Locale gcLocale = getLocaleFromResource(langRootUncle);
//todo check that this is not a country node
if (gcLocale != null && !isCountryNode(langRootUncle)) {
roots.add(langRootUncle);
additionalLanguageRootsFound = true;
} else {
nonLangRootUncles.add(langRootUncle);
}
}
}
if (!additionalLanguageRootsFound) {
//didn't found roots one level up, no need to go down on nonLangRootUncles. Therefore, return
return roots;
}
for (Resource nonLangRootUncle : nonLangRootUncles) {
additionalLanguageRootsFound = addLanguageRootsFromChildren(roots,
additionalLanguageRootsFound, nonLangRootUncle);
}
}
return roots;
}
private static boolean addLanguageRootsFromChildren(List roots, boolean additionalLanguageRootsFound,
Resource resource) {
Iterator children = resource.listChildren();
while (children.hasNext()) {
Resource child = children.next();
Locale childLocale = getLocaleFromResource(child);
if (childLocale != null) {
roots.add(child);
additionalLanguageRootsFound = true;
}
}
return additionalLanguageRootsFound;
}
private static Iterator getLanguageRootSiblings(ResourceResolver resolver, @Nonnull String path) {
String root = LanguageUtil.getLanguageRoot(path);
if (root == null) {
return null;
}
String parent = Text.getRelativeParent(root, 1);
Resource parentResource = resolver.getResource(parent);
if (parentResource == null) {
return null;
}
return resolver.listChildren(parentResource);
}
private static Resource getLanguageRootResource(@Nonnull Resource res) {
String rootPath = LanguageUtil.getLanguageRoot(res.getPath());
if (rootPath == null) {
return null;
}
return res.getResourceResolver().getResource(rootPath);
}
/**
* This method creates update language copy of an asset/folder
*
* @param resourceResolver
* @param pageManagerFactory
* @param sourcePath - source for creating language copy
* @param targetLanguageCode - destination language code
* @param prefixPath - Root path where language copies are created
* @return
*/
public static String createUpdateLanguageCopy(final ResourceResolver resourceResolver, final PageManagerFactory pageManagerFactory, final String sourcePath,
final String targetLanguageCode, String prefixPath) {
Session session = resourceResolver.adaptTo(Session.class);
PageManager pageManager = pageManagerFactory.getPageManager(resourceResolver);
Resource sourceResource = resourceResolver.getResource(sourcePath);
String createdCopy = "";
String contentPath = "";
if (targetLanguageCode == null || targetLanguageCode.trim().length() == 0) {
log.error("Failed to load destination language from payload.");
return null;
}
String root = LanguageUtil.getLanguageRoot(sourcePath);
String parentOfRoot = null;
boolean createNewLanguageRoot = false;
if (root == null) {
log.debug("Language root does not exist for asset at path: {} and would be created. ", sourcePath);
//CQ-61450 User creates a language copy of a page from sites and language root for the asset (referenced in site) does not exist
if (Text.getRelativeParent(sourcePath, 1).equals(DamConstants.MOUNTPOINT_ASSETS)) {
//Asset is directly under DamConstants.MOUNTPOINT_ASSETS
parentOfRoot = DamConstants.MOUNTPOINT_ASSETS;
root = DamConstants.MOUNTPOINT_ASSETS;
} else if (sourcePath.startsWith(DamConstants.MOUNTPOINT_ASSETS + "/")) {
//Asset follows structure DamConstants.MOUNTPOINT_ASSETS//
int parentOfRootPathLength = sourcePath.indexOf('/', DamConstants.MOUNTPOINT_ASSETS.length() + 1);
int oldRootPathLength = sourcePath.indexOf('/', parentOfRootPathLength);
if (parentOfRootPathLength < 0 || sourcePath.length() <= parentOfRootPathLength) {
return createdCopy;
}
parentOfRoot = sourcePath.substring(0, parentOfRootPathLength);
if (oldRootPathLength > 0 && sourcePath.length() > oldRootPathLength) {
root = sourcePath.substring(0, oldRootPathLength);
}
}
createNewLanguageRoot = true;
log.info("Parent of New Language root at path {} added for asset at path {}", parentOfRoot, sourcePath);
contentPath = sourcePath.replaceFirst(parentOfRoot, "");
} else {
contentPath = sourcePath.replaceFirst(root, "");
parentOfRoot = Text.getRelativeParent(root, 1);
}
String targetPath = "";
String languageRootPath = "";
String strDestinationLanguage = getDestinationLanguageWithAllowedDelimiters(prefixPath + parentOfRoot,
targetLanguageCode, resourceResolver);
languageRootPath = prefixPath + getDestinationLanguageRoot(parentOfRoot, strDestinationLanguage,
resourceResolver);
targetPath = languageRootPath + contentPath;
try {
// if (contentPath.trim().length() > 0) {
String pathToCreate = Text.getRelativeParent(
targetPath, 1);
String nodeType = "sling:Folder";
if (session.getNode(root).isNodeType(
"sling:OrderedFolder")) {
nodeType = "sling:OrderedFolder";
}
JcrUtil.createPath(pathToCreate, nodeType,
nodeType, session, false);
// }
if (null == resourceResolver.getResource(targetPath)) {
if (DamUtil.isAsset(sourceResource)) {
Resource destinationResource = pageManager.copy(sourceResource, targetPath, null, false, true, false);
// Remove Derived, Others Relations from this resource, if any. Ensures that if this resource,
// is a source Asset then the derived, others relations don't point to old language copies
if (destinationResource != null) {
com.adobe.granite.asset.api.Asset destinationGraniteAsset = destinationResource.adaptTo(com.adobe.granite.asset.api.Asset.class);
if (destinationGraniteAsset != null) {
removeAssetRelation(destinationGraniteAsset, ATTRIBUTE_ASSET_DERIVED_RELATION);
removeAssetRelation(destinationGraniteAsset, ATTRIBUTE_ASSET_OTHERS_RELATION);
}
}
addTranslationSourcePath(destinationResource, sourceResource.getPath());
setLastTranslationUpdate(destinationResource);
deleteInsightData(destinationResource.getPath(), resourceResolver);
removeAllRenditionsInsideResource(destinationResource);
String destinationForTemporaryAsset = parentOfRoot + "/" + strDestinationLanguage + contentPath;
setDestinationLanguageCopyPath(destinationResource, destinationForTemporaryAsset);
createdCopy = destinationResource.getPath();
}
//changing the title of the folder
Node targetNode = session.getNode(languageRootPath);
if (targetNode != null) {
if (!targetNode.hasNode(JcrConstants.JCR_CONTENT)) {
targetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node content = targetNode.getNode(JcrConstants.JCR_CONTENT);
if (!content.hasProperty(JcrConstants.JCR_TITLE)) {
String displayLanguage = getLanguageDisplayName(resourceResolver, strDestinationLanguage);
content.setProperty(JcrConstants.JCR_TITLE, displayLanguage);
}
//set JCR_TITLE for all folders in the created contentPath and language root
String tempAddTitlePath = contentPath.substring(0, contentPath.lastIndexOf('/'));
while (tempAddTitlePath.length() > 0) {
Node tempNode = session.getNode(languageRootPath + tempAddTitlePath);
if (tempNode != null) {
if (!tempNode.hasNode(JcrConstants.JCR_CONTENT)) {
tempNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node tempNodeContent = tempNode.getNode(JcrConstants.JCR_CONTENT);
String sourceNodeForTitle = null;
if (createNewLanguageRoot) {
sourceNodeForTitle = parentOfRoot + tempAddTitlePath;
} else {
sourceNodeForTitle = root + tempAddTitlePath;
}
if (!tempNodeContent.hasProperty(JcrConstants.JCR_TITLE)) {
String tempNodeTitle = UIHelper.getTitle(resourceResolver.
getResource(sourceNodeForTitle));
tempNodeContent.setProperty(JcrConstants.JCR_TITLE, tempNodeTitle);
}
tempAddTitlePath = tempAddTitlePath.substring(0, tempAddTitlePath.lastIndexOf('/'));
}
}
}
session.save();
} else {
createdCopy = targetPath;
}
} catch (Exception e) {
log.error(
"error while creating language copy for assets at path: "
+ targetPath + "{}", e);
}
return createdCopy;
}
private static String getDestinationLanguageWithAllowedDelimiters(String contentPath, String strDestinationLanguage,
ResourceResolver resourceResolver) {
String langWithHyphen = strDestinationLanguage.replace("_", "-");
String langWithUnderscore = strDestinationLanguage.replace("-", "_");
boolean langWithHyphenExist = (null != resourceResolver.getResource(contentPath + "/" + langWithHyphen));
boolean langWithUnderscoreExist = (null != resourceResolver.getResource(contentPath + "/" +
langWithUnderscore));
if (langWithHyphenExist && langWithUnderscoreExist) {
return strDestinationLanguage;
} else if (langWithHyphenExist) {
return langWithHyphen;
} else if (langWithUnderscoreExist) {
return langWithUnderscore;
} else {
return strDestinationLanguage;
}
}
private static void deleteInsightData(String resourcePath, ResourceResolver resourceResolver) {
Resource resource = resourceResolver.getResource(resourcePath);
if (resource != null) {
if (DamUtil.isAsset(resource)) {
deleteResource(resourcePath + ASSET_PERFORMANCE_NODE_RELATIVE_PATH, resourceResolver);
deleteResource(resourcePath + ASSET_USAGE_NODE_RELATIVE_PATH, resourceResolver);
} else if (isFolder(resource)) {
Iterator assetIterator = DamUtil.getAssets(resource);
while (assetIterator.hasNext()) {
String assetPath = assetIterator.next().getPath();
deleteResource(assetPath + ASSET_PERFORMANCE_NODE_RELATIVE_PATH, resourceResolver);
deleteResource(assetPath + ASSET_USAGE_NODE_RELATIVE_PATH, resourceResolver);
}
}
}
}
private static void deleteResource(String path, ResourceResolver resourceResolver) {
Resource resource = resourceResolver.getResource(path);
if (resource != null) {
try {
resourceResolver.delete(resource);
} catch (PersistenceException e) {
log.error("Unable to delete resource from {} : {}", resource, e.getMessage());
}
}
}
private static void setDestinationLanguageCopyPath(Resource temporaryResource, String destinationPath)
throws RepositoryException {
Node temporaryNode = temporaryResource.adaptTo(Node.class);
if (!temporaryNode.hasNode(JcrConstants.JCR_CONTENT)) {
temporaryNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node destinationContentNode = temporaryNode.getNode(JcrConstants.JCR_CONTENT);
destinationContentNode.setProperty(ATTRIBUTE_DESTINATION_LANGUAGE_COPY_PATH, destinationPath);
}
private static boolean isFolder(Resource resource){
Node n = resource.adaptTo(Node.class);
try {
return n.isNodeType(NT_FOLDER);
} catch (RepositoryException e) {
return false;
}
}
/**
*
* @param sourcePath
* @param destinationPath
* @param userSession
* @param pageManagerFactory
* @param resolverFactory
*
* @deprecated since 6.2, use
* {@link #moveUpdatedAsset(String, String, Session, PageManagerFactory, ResourceResolver)} instead
*/
@Deprecated
public static void moveUpdatedAsset(String sourcePath, String destinationPath, Session userSession,
PageManagerFactory pageManagerFactory, ResourceResolverFactory resolverFactory){
throw new UnsupportedOperationException("This API has been deprecated.Please use moveUpdatedAsset(String, String, Session, PageManagerFactory, "
+ "ResourceResolver) instead.");
}
public static void moveUpdatedAsset(String sourcePath, String destinationPath, Session userSession,
PageManagerFactory pageManagerFactory, ResourceResolver resourceResolver){
Map authInfo = new HashMap();
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, userSession);
try {
Resource sourceResource = resourceResolver.getResource(sourcePath);
Resource destinationResource = resourceResolver.getResource(destinationPath);
Asset sourceAsset = DamUtil.resolveToAsset(sourceResource);
if(sourceAsset != null) {
PageManager pageManager = pageManagerFactory.getPageManager(resourceResolver);
if(destinationResource == null){
String pathToCreate = Text.getRelativeParent(
destinationPath, 1);
String nodeType = "sling:Folder";
// if (userSession.getNode(destinationPath).isNodeType(
// "sling:OrderedFolder")) {
// nodeType = "sling:OrderedFolder";
// }
JcrUtil.createPath(pathToCreate, nodeType,
nodeType, userSession, false);
pageManager.copy(sourceResource, destinationPath, null, false,
false, true);
} else {
Asset destinationAsset = DamUtil.resolveToAsset(destinationResource);
if(destinationAsset != null) {
destinationAsset.addRendition(DamConstants.ORIGINAL_FILE, sourceAsset.getOriginal().getBinary(), sourceAsset.getMimeType());
} else {
log.error("Unable to move updated asset : Destination Asset not found");
}
//todo copy metadata
}
userSession.save();
} else {
log.error("Unable to move updated asset : Source Asset not found");
}
} catch (Exception e) {
log.error("Unable to move updated asset {}", e.getMessage());
}
}
public static void replaceUpdatedAsset(String sourcePath, String destinationPath, Session userSession,
PageManagerFactory pageManagerFactory, ResourceResolver resourceResolver){
try {
Resource sourceResource = resourceResolver.getResource(sourcePath);
Resource destinationResource = resourceResolver.getResource(destinationPath);
Asset sourceAsset = sourceResource.adaptTo(Asset.class);
if (sourceAsset!= null && !isContentFragment(sourceAsset)) {
addExtractMetadataPropertyForAsset(sourceAsset, false);
}
if(sourceResource != null) {
PageManager pageManager = pageManagerFactory.getPageManager(resourceResolver);
if(destinationResource == null){
String pathToCreate = Text.getRelativeParent(
destinationPath, 1);
String nodeType = "sling:Folder";
JcrUtil.createPath(pathToCreate, nodeType,
nodeType, userSession, false);
pageManager.copy(sourceResource, destinationPath, null, false,
false, true);
} else {
//create version
Asset destinationAsset = resourceResolver.getResource(destinationPath).adaptTo(Asset.class);
if (destinationAsset != null) {
destinationAsset.createRevision("", ASSET_VERSION_MESSAGE);
copyInsightData(destinationResource.getPath(), sourceResource.getPath(), resourceResolver,
pageManager);
deleteAllChildren(destinationResource, userSession);
copyAllChildren(sourceResource, destinationResource, pageManager, userSession);
//See the discussion on CQ-4235761 and CQ-39476. Copy and create are two separate functionalities and we will
//not trigger update_asset workflow on PageManager.copy(). Hence it needs to be triggered explicitly to create
//renditions of the translated asset.
WorkflowSession workflowSession = resourceResolver.adaptTo(WorkflowSession.class);
WorkflowModel modelToStart = workflowSession.getModel(UPDATE_ASSET_WORKFLOW_MODEL);
WorkflowData workflowData = workflowSession.newWorkflowData("JCR_PATH", destinationPath);
workflowSession.startWorkflow(modelToStart, workflowData);
} else {
log.error("Unable to move updated asset : Destination is not an Asset");
}
}
userSession.save();
} else {
log.error("Unable to move updated asset : Source Resource not found");
}
} catch (Exception e) {
log.error("Unable to move updated asset {}", e.getMessage());
}
}
private static void copyInsightData(String sourcePath, String destinationPath, ResourceResolver resourceResolver,
PageManager pageManager) {
copyResource(sourcePath + ASSET_PERFORMANCE_NODE_RELATIVE_PATH,
destinationPath + ASSET_PERFORMANCE_NODE_RELATIVE_PATH, resourceResolver, pageManager);
copyResource(sourcePath + ASSET_USAGE_NODE_RELATIVE_PATH, destinationPath + ASSET_USAGE_NODE_RELATIVE_PATH,
resourceResolver, pageManager);
}
private static void copyResource(String sourcePath, String destinationPath, ResourceResolver resourceResolver,
PageManager pageManager) {
Resource sourceResource = resourceResolver.getResource(sourcePath);
if (sourceResource != null) {
try {
pageManager.copy(sourceResource, destinationPath, null, false, false, false);
} catch (WCMException e) {
log.error("Unable to copy resource from " + sourcePath + " to " + destinationPath + " : {}",
e.getMessage());
}
}
}
private static void copyAllChildren(Resource sourceResource, Resource destinationResource, PageManager pageManager,
Session session) throws RepositoryException, WCMException {
if (sourceResource != null && destinationResource != null) {
Iterable childList = sourceResource.getChildren();
String destinationResourcePath = destinationResource.getPath();
for (Resource child : childList) {
String destinationChildPath = destinationResourcePath + "/" + child.getName();
pageManager.copy(child, destinationChildPath, null, false, false, false);
}
session.save();
}
}
private static void deleteAllChildren(Resource resource, Session session) throws RepositoryException {
if (resource != null) {
Iterable childList = resource.getChildren();
for (Resource child : childList) {
Node childNode = child.adaptTo(Node.class);
childNode.remove();
}
}
session.save();
}
/**
* Removes all asset renditions contained in the resource.
* If resource is a folder, then all its folders are navigated recursively to delete asset renditions.
* @param resource resource
*/
private static void removeAllRenditionsInsideResource(Resource resource) throws RepositoryException {
Iterator assets = DamUtil.getAssets(resource);
while (assets.hasNext()) {
Asset asset = assets.next();
if (!isContentFragment(asset)) {
List renditions = asset.getRenditions();
for (Rendition rendition : renditions) {
String name = rendition.getName();
if (!name.equals(DamConstants.ORIGINAL_FILE)) {
asset.removeRendition(name);
}
}
}
}
}
private static boolean isContentFragment(Asset asset) throws RepositoryException {
Node assetNode = asset.adaptTo(Node.class);
Node jcrNode = assetNode.getNode(JCR_CONTENT);
if (jcrNode.hasProperty(CONTENT_FRAGMENT)) {
return jcrNode.getProperty(CONTENT_FRAGMENT).getBoolean();
}
return false;
}
public static boolean isSmartAssetUpdateRequired(Asset sourceAsset, Asset destinationAsset) {
if (sourceAsset == null || destinationAsset == null) {
return false;
}
Resource sourceResource = sourceAsset.adaptTo(Resource.class);
Resource destResource = destinationAsset.adaptTo(Resource.class);
boolean bRetVal = false;
if (sourceResource != null && destResource != null) {
// now check the modified time
Resource sourceContentResource = sourceResource.getChild(JcrConstants.JCR_CONTENT);
Resource destContentResource = destResource.getChild(JcrConstants.JCR_CONTENT);
if (sourceContentResource == null) {
sourceContentResource = sourceResource;
}
if (destContentResource == null) {
destContentResource = destResource;
}
Calendar sourceLastModified = getNodeLastModifiedTime(sourceContentResource);
Calendar lastTranslationUpdate =
getCalendarAttribute(destContentResource, ATTRIBUTE_CQ_TRANSLATION_LAST_UPDATE);
if (lastTranslationUpdate != null) {
if (sourceLastModified != null) {
bRetVal =
(sourceLastModified.getTimeInMillis() - lastTranslationUpdate.getTimeInMillis()) > MAX_DIFF_MILLISECOND_CHANGED;
}
} else {
bRetVal = true; // no translation done till now
}
}
return bRetVal;
}
@Deprecated
/**
*@deprecated since 6.2, use
*{@link #addSmartAssetUpdateSource(Asset, String)} instead
*/
public static void addSmartAssetUpdateFlag(Asset destinationAsset) throws RepositoryException {
throw new UnsupportedOperationException("This API has been deprecated.Please use addSmartAssetUpdateSource(Asset, String) instead.");
}
public static void addSmartAssetUpdateSource(Asset destinationAsset, String sourcePath) throws RepositoryException {
if (destinationAsset == null || sourcePath == null) {
return;
}
Node assetNode = destinationAsset.adaptTo(Node.class);
if (!assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
assetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node assetContentNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
assetContentNode.setProperty(ATTRIBUTE_SMART_ASSET_UPDATE_SOURCE, sourcePath);
}
private static void addSmartAssetUpdateProperty(Asset destinationAsset, boolean value) throws RepositoryException {
if (destinationAsset == null) {
return;
}
Node assetNode = destinationAsset.adaptTo(Node.class);
if (!assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
assetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node assetContentNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
assetContentNode.setProperty(ATTRIBUTE_SMART_ASSET_UPDATE_REQUIRED, value);
}
private static void addExtractMetadataPropertyForAsset(Asset asset, boolean bExtractMetadata) throws RepositoryException {
Node assetNode = asset.adaptTo(Node.class);
if (!assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
assetNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_UNSTRUCTURED);
}
Node assetContentNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
assetContentNode.setProperty(ATTRIBUTE_EXTRACT_METADATA, bExtractMetadata);
}
/**
* Creates language copy of an asset
*
* @param resourceResolver
* @param pageManagerFactory
* @param sourcePath
* @param targetLanguageCode
* @return path of created language copy or null if language copy is already exists and does not require translation.
*/
private static String createLanguageCopy(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String sourcePath, final String targetLanguageCode) {
String[] targetLanguageCodeArray = {targetLanguageCode};
List languageCopyPathArray = createLanguageCopy(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodeArray);
if (null != languageCopyPathArray && languageCopyPathArray.size() == 1) {
return languageCopyPathArray.get(0);
}
return null;
}
/**
* This method creates language copy of an asset/folder and its source(for example psd for jpeg). Information about
* language copy which triggered translation is added in case temporary asset translation is required. Finally,
* relations are changed with their language copies.
*
* @param resourceResolver
* @param pageManagerFactory
* @param sourcePath - source for creating language copy
* @param targetLanguageCodes - array of language codes
* @return list of created language copies
*/
public static List createLanguageCopyWithAssetRelations(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String sourcePath, final String[] targetLanguageCodes)
throws RepositoryException {
Resource sourceResource = resourceResolver.getResource(sourcePath);
if (null == sourceResource) {
//returning empty array list for backward compatibility
return new ArrayList();
}
//check for asset
if (null != sourceResource.adaptTo(Asset.class)) {
return createLanguageCopyWithAssetRelationsForAsset(resourceResolver, pageManagerFactory,
sourcePath, targetLanguageCodes);
}
//check for asset folder
Node sourceNode = sourceResource.adaptTo(Node.class);
if (null != sourceNode && sourceNode.isNodeType(JcrConstants.NT_FOLDER)) {
return createLanguageCopyWithAssetRelationsForNTFolder(resourceResolver, pageManagerFactory,
sourcePath, targetLanguageCodes);
}
//return empty array list for backward compatibility
return new ArrayList();
}
private static String createLanguageCopyWithAssetRelations(final String sourcePath, final String targetLanguageCode,
final ResourceResolver resourceResolver, final PageManagerFactory pageManagerFactory)
throws RepositoryException {
String[] languageArray = {targetLanguageCode};
List languageCopyList = createLanguageCopyWithAssetRelations(resourceResolver, pageManagerFactory,
sourcePath, languageArray);
if (languageCopyList != null && languageCopyList.size() == 1) {
return languageCopyList.get(0);
}
return null;
}
private static void adjustDerivedAndRemoveOthersRelationsForSourceAssetsLC (List relatedSourceAssets, String newDerivedAssetPath,
String oldDerivedAssetPath, ResourceResolver resourceResolver) {
String oldLanguageRoot = getLanguageRootLocale(oldDerivedAssetPath);
for(Asset sourceDamAsset: relatedSourceAssets) {
String targetLanguageCode = getLanguageRootLocale(newDerivedAssetPath);
String sourceAssetLCPath = findLanguageCopyPathWithAutoCreatedRoots(sourceDamAsset.getPath(),
targetLanguageCode, resourceResolver);
Resource sourceAssetLCResource = resourceResolver.getResource(sourceAssetLCPath);
if (sourceAssetLCResource != null) {
com.adobe.granite.asset.api.Asset sourceAssetLC = sourceAssetLCResource.adaptTo(com.adobe.granite.asset.api.Asset.class);
if (sourceAssetLC != null) {
// First remove derived relations that point to old language copies
removeAssetRelationWithLanguageCode(sourceAssetLC, ATTRIBUTE_ASSET_DERIVED_RELATION, oldLanguageRoot);
// Add new derived relation for the source asset
adjustAssetRelations(sourceAssetLC, ATTRIBUTE_ASSET_DERIVED_RELATION, oldDerivedAssetPath, newDerivedAssetPath);
// Delete the others relation for the source asset
removeAssetRelation(sourceAssetLC, ATTRIBUTE_ASSET_OTHERS_RELATION);
}
}
}
}
public static List createLanguageCopyWithAssetRelationsForAsset(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String sourcePath, final String[] targetLanguageCodes)
throws RepositoryException {
Resource sourceResource = resourceResolver.getResource(sourcePath);
List createdVariantCopies = new ArrayList();
String sourceResourcePath = sourceResource.getPath();
if (null != sourceResource) {
List relatedSourceAssets = getRelatedAssets(sourceResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
List relatedLinkedAssets = getRelatedAssets(sourceResource, ATTRIBUTE_ASSET_LINKS_RELATION);
if (!relatedSourceAssets.isEmpty() || !relatedLinkedAssets.isEmpty()) {
for (int languageIndex = 0; languageIndex < targetLanguageCodes.length; languageIndex++) {
TranslationCategory translationCategory = getTranslationCategoryForAssetAndItsRelations(sourcePath,
targetLanguageCodes[languageIndex], resourceResolver);
switch (translationCategory) {
case TEMPORARY:
//Temporary Language copies are required
createMissingDestinationLanguageCopies(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes[languageIndex]);
String languageCopyPath = findLanguageCopyPathWithAutoCreatedRoots(sourcePath,
targetLanguageCodes[languageIndex], resourceResolver);
Asset destinationAsset = resourceResolver.getResource(languageCopyPath).adaptTo(Asset.class);
addSmartAssetUpdateSource(destinationAsset, sourcePath);
addSmartAssetUpdateProperty(destinationAsset, true);
createdVariantCopies.add(languageCopyPath);
break;
case DESTINATION:
//Destination Language copy needs to be created or updated.
String variantLanguageCopyPath = createOrGetLanguageCopy(resourceResolver,
pageManagerFactory, sourcePath, targetLanguageCodes[languageIndex]);
Resource variantLanguageCopyResource =
resourceResolver.getResource(variantLanguageCopyPath);
com.adobe.granite.asset.api.Asset graniteDestinationAsset = variantLanguageCopyResource
.adaptTo(com.adobe.granite.asset.api.Asset.class);
createRelationLanguageCopy(ATTRIBUTE_ASSET_SOURCE_RELATION, graniteDestinationAsset,
relatedSourceAssets, targetLanguageCodes[languageIndex], resourceResolver,
pageManagerFactory);
// Adjust the derived, others relations for the source assets
adjustDerivedAndRemoveOthersRelationsForSourceAssetsLC(relatedSourceAssets, variantLanguageCopyPath,
sourceResourcePath, resourceResolver);
// Delete the others relation for destination asset
removeAssetRelation(graniteDestinationAsset, ATTRIBUTE_ASSET_OTHERS_RELATION);
createRelationLanguageCopy(ATTRIBUTE_ASSET_LINKS_RELATION, graniteDestinationAsset,
relatedLinkedAssets, targetLanguageCodes[languageIndex], resourceResolver,
pageManagerFactory);
createRelationLanguageCopyForSourceRelations(ATTRIBUTE_ASSET_LINKS_RELATION,
relatedSourceAssets, targetLanguageCodes[languageIndex],
resourceResolver, pageManagerFactory);
createdVariantCopies.add(variantLanguageCopyPath);
break;
case NONE:
String tempLanguageCopyPath = findLanguageCopyPathWithAutoCreatedRoots(sourcePath,
targetLanguageCodes[languageIndex], resourceResolver);
Asset tempDestinationAsset = resourceResolver.getResource(tempLanguageCopyPath).adaptTo(
Asset.class);
addSmartAssetUpdateProperty(tempDestinationAsset, false);
createdVariantCopies.add(tempLanguageCopyPath);
break;
}
}
} else {
createdVariantCopies = createLanguageCopy(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes);
}
//todo add destination if required
Asset sourceAsset = sourceResource.adaptTo(Asset.class);
if(isContentFragment(sourceAsset)) {
try {
createOrUpdateLanguageCopyForAssociatedContent(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes);
} catch (Exception e) {
log.error("Could not create language copy for associated content. {}", e);
}
}
if (isContentFragment(sourceAsset)) {
try {
//commit changes to get variations by query. todo: remove once this is fixed
resourceResolver.commit();
createAndReplaceLanguageCopyForEmbeddedAssets(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes);
} catch (Exception e) {
log.error("Could not create language copy for embedded assets. {}", e);
}
}
}
return createdVariantCopies;
}
private static void createAndReplaceLanguageCopyForEmbeddedAssets(ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory, String sourcePath, String[] targetLanguageCodes)
throws RepositoryException, IOException, WCMException {
String sourceLanguage = getLanguageRootLocale(sourcePath);
for (String targetLanguageCode : targetLanguageCodes) {
String languageCopyPath = findLanguageCopyPathWithAutoCreatedRoots(sourcePath, targetLanguageCode,
resourceResolver);
if (null != languageCopyPath && isTranslateInlineMediaAssets(languageCopyPath, resourceResolver)) {
if (!temporaryAssetSourcePropertyExist(languageCopyPath, resourceResolver)) {
boolean bReplacementRequired = createLanguageCopyForEmbeddedAssets(languageCopyPath,
sourceLanguage, targetLanguageCode, resourceResolver, pageManagerFactory);
if (bReplacementRequired) {
replaceEmbeddedAssets(languageCopyPath, targetLanguageCode, resourceResolver);
}
} else {
//create language copies or mark for updates for source asset
createLanguageCopyForEmbeddedAssets(sourcePath, sourceLanguage, targetLanguageCode,
resourceResolver, pageManagerFactory);
}
}
}
}
private static boolean temporaryAssetSourcePropertyExist(String assetpath, ResourceResolver resourceResolver) throws
RepositoryException {
boolean retVal = false;
Resource resource = resourceResolver.getResource(assetpath);
if (null != resource) {
Node node = resource.adaptTo(Node.class);
if (getUpdateAssetNodeSourcePath(node) != null) {
retVal = true;
}
}
return retVal;
}
private static boolean createLanguageCopyForEmbeddedAssets(String contentFragmentPath, String sourceLanguageCode,
String targetLanguageCode, ResourceResolver resourceResolver, PageManagerFactory pageManagerFactory)
throws RepositoryException, IOException {
HashSet embeddedAssets = getEmbeddedAssets(contentFragmentPath, resourceResolver);
boolean bReplacementRequired = false;
getLanguageRootLocale(contentFragmentPath);
for (Asset embeddedAsset : embeddedAssets) {
String embeddedAssetPath = embeddedAsset.getPath();
String sourceEmbeddedAssetPath;
if (!getLanguageRootLocale(embeddedAssetPath).equals(targetLanguageCode)) {
sourceEmbeddedAssetPath = embeddedAssetPath;
bReplacementRequired = true;
} else {
sourceEmbeddedAssetPath = findLanguageCopyPathWithAutoCreatedRoots(embeddedAssetPath, sourceLanguageCode,
resourceResolver);
}
createLanguageCopyWithAssetRelations(sourceEmbeddedAssetPath, targetLanguageCode, resourceResolver,
pageManagerFactory);
}
return bReplacementRequired;
}
private static void createOrUpdateLanguageCopyForAssociatedContent(ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory, String sourcePath, String[] targetLanguageCodes)
throws RepositoryException, PersistenceException, WCMException {
Resource sourceResource = resourceResolver.getResource(sourcePath);
if (null != sourceResource) {
Node sourceNode = sourceResource.adaptTo(Node.class);
targetLanguageCodes = getAssociatedContentTranslationLanguages(sourceResource, targetLanguageCodes,
resourceResolver);
ArrayList associatedAssets = getContentFragmentAssociatedAssets(sourceNode, resourceResolver);
for (Asset asset : associatedAssets) {
createLanguageCopyWithAssetRelations(resourceResolver, pageManagerFactory, asset.getPath(),
targetLanguageCodes);
}
createOrUpdateLanguageCopyForAssociatedContentNode(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes);
} else {
log.error("Could not create language copy for associated content. Resource nt found at path {}",
sourcePath);
}
}
private static String[] getAssociatedContentTranslationLanguages(Resource sourceResource,
String[] targetLanguageCodes, ResourceResolver resourceResolver) {
ArrayList applicableLanguages = new ArrayList();
String sourcePath = sourceResource.getPath();
for (String targetLanguageCode : targetLanguageCodes) {
String lcPath = findLanguageCopyPathWithAutoCreatedRoots(sourcePath, targetLanguageCode, resourceResolver);
if (null != lcPath) {
Resource lcResource = resourceResolver.getResource(lcPath);
if (isTranslateAssociatedContent(lcResource, resourceResolver)) {
applicableLanguages.add(targetLanguageCode);
}
}
}
return applicableLanguages.toArray(new String[applicableLanguages.size()]);
}
private static void createOrUpdateLanguageCopyForAssociatedContentNode(ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory, String sourcePath, String[] targetLanguageCodes)
throws PersistenceException, WCMException, RepositoryException {
createOrUpdateLanguageCopyForAssociatedContentNode(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCodes, "");
}
private static void createOrUpdateLanguageCopyForAssociatedContentNode(ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory, String sourcePath, String[] targetLanguageCodes, String prefixPath)
throws PersistenceException, WCMException, RepositoryException {
Resource sourceAssociatedContentResource = getAssociatedContentResource(sourcePath, resourceResolver);
if (sourceAssociatedContentResource == null) {
return;
}
PageManager pageManager = pageManagerFactory.getPageManager(resourceResolver);
for (String targetLanguageCode : targetLanguageCodes) {
ResourceCollection destinationAssociatedContents = findAssociatedContentLanguageCopy(sourcePath, prefixPath,
targetLanguageCode, resourceResolver);
if (null == destinationAssociatedContents) {
continue;
}
Iterator collectionResources = getResourcesFromCollection(sourceAssociatedContentResource);
if (null == collectionResources) {
continue;
}
while (collectionResources.hasNext()) {
Resource sourceCollectionResource = collectionResources.next();
createOrUpdateCollectionLanguageCopy(sourceCollectionResource, targetLanguageCode,
destinationAssociatedContents, resourceResolver, pageManager);
//nested collections
createLCForNestedCollections(sourceCollectionResource, targetLanguageCode, resourceResolver,
pageManager);
}
}
}
private static void createLCForNestedCollections(Resource sourceCollectionResource, String targetLanguageCode,
ResourceResolver resourceResolver, PageManager pageManager) throws RepositoryException, WCMException,
PersistenceException {
HashSet nestedCollections = new HashSet();
createLCForNestedCollections(sourceCollectionResource, targetLanguageCode, resourceResolver, pageManager,
nestedCollections);
}
private static void createLCForNestedCollections(Resource sourceCollectionResource, String targetLanguageCode,
ResourceResolver resourceResolver, PageManager pageManager, HashSet updatedCollections)
throws RepositoryException, WCMException, PersistenceException {
ResourceCollection sourceCollection = sourceCollectionResource.adaptTo(ResourceCollection.class);
Iterator sourceResources = sourceCollection.getResources();
while (sourceResources.hasNext()) {
Resource sourceResource = sourceResources.next();
if (isDamCollection(sourceResource) && !updatedCollections.contains(sourceResource)) {
ResourceCollection destinationCollection = getDestinationCollection(sourceCollection.getPath(),
targetLanguageCode, resourceResolver);
createOrUpdateCollectionLanguageCopy(sourceResource, targetLanguageCode, destinationCollection,
resourceResolver, pageManager);
updatedCollections.add(sourceResource);
createLCForNestedCollections(sourceResource, targetLanguageCode, resourceResolver, pageManager,
updatedCollections);
}
}
}
private static boolean isDamCollection(Resource sourceResource) {
return sourceResource.isResourceType("dam/collection");
}
private static ResourceCollection getDestinationCollection(String sourceCollectionPath, String targetLanguageCode,
ResourceResolver resourceResolver) {
String destinationCollectionPath = getAssociatedContentLanguageCopyPathOrName(sourceCollectionPath,
targetLanguageCode);
Resource resource = resourceResolver.getResource(destinationCollectionPath);
if (null == resource) {
return null;
}
return resource.adaptTo(ResourceCollection.class);
}
private static ResourceCollection findAssociatedContentLanguageCopy(String sourceContentFragmentPath, String
prefixPath, String targetLanguageCode, ResourceResolver resourceResolver) throws RepositoryException {
String destinationContentFragmentPath = findLanguageCopyPathWithAutoCreatedRoots(sourceContentFragmentPath,
targetLanguageCode, resourceResolver);
Resource targetAssociatedContentResource = null;
if (null != destinationContentFragmentPath) {
destinationContentFragmentPath = prefixPath + destinationContentFragmentPath;
targetAssociatedContentResource = getAssociatedContentResource(destinationContentFragmentPath,
resourceResolver);
}
if (null != targetAssociatedContentResource) {
return targetAssociatedContentResource.adaptTo(ResourceCollection.class);
}
return null;
}
private static Iterator getResourcesFromCollection(Resource collectionResource) {
ResourceCollection associatedContentCollection = collectionResource.adaptTo(ResourceCollection.class);
if(associatedContentCollection!=null) {
return associatedContentCollection.getResources();
}
return null;
}
private static void createOrUpdateCollectionLanguageCopy(Resource sourceCollectionResource, String
targetLanguageCode, ResourceCollection destinationAssociatedContents, ResourceResolver resourceResolver,
PageManager pageManager) throws WCMException, PersistenceException, RepositoryException {
String sourceCollectionPath = sourceCollectionResource.getPath();
String targetPath = getAssociatedContentLanguageCopyPathOrName(sourceCollectionPath, targetLanguageCode);
Resource targetCollectionResource = resourceResolver.getResource(targetPath);
if (null == targetCollectionResource) {
targetCollectionResource = pageManager.copy(sourceCollectionResource, targetPath, null, false, false, true);
setProperty(targetCollectionResource, ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY, sourceCollectionPath);
if (null != sourceCollectionResource.adaptTo(Node.class) &&
sourceCollectionResource.adaptTo(Node.class).hasProperty(JCR_TITLE)) {
String sourceCollectionName = sourceCollectionResource.adaptTo(Node.class).getProperty(JCR_TITLE)
.getString();
String destinationCollectionName = getAssociatedContentLanguageCopyPathOrName(
sourceCollectionName, targetLanguageCode);
setProperty(targetCollectionResource, JCR_TITLE, destinationCollectionName);
}
} else {
updateExistingCollectionResource(sourceCollectionResource, targetCollectionResource, targetLanguageCode,
resourceResolver);
}
ResourceCollection collectionLanguageCopy = targetCollectionResource.adaptTo(ResourceCollection.class);
replaceCollectionResource(destinationAssociatedContents, sourceCollectionResource, targetCollectionResource,
resourceResolver);
replaceCollectionAssetLanguageCopies(collectionLanguageCopy, targetLanguageCode, resourceResolver);
}
private static void setProperty(Resource resource, String property, String value) throws RepositoryException {
Node node = resource.adaptTo(Node.class);
node.setProperty(property, value);
}
private static String getAssociatedContentLanguageCopyPathOrName(String source, String targetLanguageCode) {
String initial = source;
if (initial.contains("-")) {
//check if language code exists
String languageCode = initial.substring(initial.lastIndexOf("-") + 1);
Locale locale = LanguageUtil.getLocale(languageCode);
if (locale != null) {
//remove language code
initial = initial.substring(0, initial.lastIndexOf("-"));
}
}
String languageCopyPostfix = "-" + targetLanguageCode;
return initial + languageCopyPostfix;
}
private static void updateExistingCollectionResource(Resource sourceCollectionResource, Resource
targetCollectionResource, String targetLanguageCode, ResourceResolver resourceResolver) throws
PersistenceException, RepositoryException {
if (null == sourceCollectionResource || null == targetCollectionResource) {
return;
}
ResourceCollection sourceCollection = sourceCollectionResource.adaptTo(ResourceCollection.class);
ResourceCollection targetCollection = targetCollectionResource.adaptTo(ResourceCollection.class);
if(null == sourceCollection || null == targetCollection) {
return;
}
Node targetNode = targetCollectionResource.adaptTo(Node.class);
targetNode.setProperty(ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY, sourceCollection.getPath());
Iterator sourceResources = sourceCollection.getResources();
while (sourceResources.hasNext()) {
Resource sourceResource = sourceResources.next();
if (null != sourceResource.adaptTo(Asset.class) || isFolder(sourceResource)) {
Resource destinationResource = findLanguageCopyWithAutoCreatedRootsForAssetOrNTFolder(sourceResource,
targetLanguageCode, resourceResolver);
replaceCollectionResource(targetCollection, sourceResource, destinationResource, resourceResolver);
}
}
}
private static void replaceCollectionAssetLanguageCopies(ResourceCollection collectionLanguageCopy, String
targetLanguageCode, ResourceResolver resourceResolver) throws PersistenceException, RepositoryException {
Iterator resourceIterator = collectionLanguageCopy.getResources();
while (resourceIterator.hasNext()) {
Resource resource = resourceIterator.next();
if (null != resource.adaptTo(Asset.class) || isFolder(resource)) {
String currentLanguage = getLanguageRootLocale(resource.getPath());
if (null == currentLanguage || !currentLanguage.equals(targetLanguageCode)) {
Resource languageCopyResource = findLanguageCopyWithAutoCreatedRootsForAssetOrNTFolder(
resource, targetLanguageCode, resourceResolver);
if (null != languageCopyResource) {
replaceCollectionResource(collectionLanguageCopy, resource, languageCopyResource,
resourceResolver);
}
}
}
}
}
private static void replaceCollectionResource(ResourceCollection collectionLanguageCopy, Resource
sourceLanguageResource, Resource destinationLanguageResource, ResourceResolver resourceResolver)
throws PersistenceException {
collectionLanguageCopy.remove(sourceLanguageResource);
//commit changes to before adding language copy. todo: remove once this is fixed
resourceResolver.commit();
collectionLanguageCopy.add(destinationLanguageResource);
resourceResolver.commit();
}
public static List createLanguageCopyWithAssetRelationsForNTFolder(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String sourcePath, final String[] targetLanguageCodes)
throws RepositoryException {
Resource sourceResource = resourceResolver.getResource(sourcePath);
if (null != sourceResource) {
Iterator assetIterator = DamUtil.getAssets(sourceResource);
while (assetIterator.hasNext()) {
Asset nextAsset = assetIterator.next();
createLanguageCopyWithAssetRelations(resourceResolver, pageManagerFactory, nextAsset.getPath(),
targetLanguageCodes);
}
}
List createdLanguageCopies = new ArrayList();
for (String targetLanguageCode : targetLanguageCodes) {
Node targetLanguageCopy =
findLanguageCopyForNTFolderWithAutoCreatedRoots(sourcePath, targetLanguageCode, resourceResolver);
if (null != targetLanguageCopy) {
createdLanguageCopies.add(targetLanguageCopy.getPath());
}
}
return createdLanguageCopies;
}
private static void createRelationLanguageCopyForSourceRelations(String relationName,
List relatedSourceAssets, String targetLanguageCode, ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory) {
for (Asset relatedSourceAsset : relatedSourceAssets) {
Resource relatedSourceResource = relatedSourceAsset.adaptTo(Resource.class);
com.adobe.granite.asset.api.Asset graniteSourceAsset = relatedSourceAsset
.adaptTo(com.adobe.granite.asset.api.Asset.class);
List relatedLinkedAssets = getRelatedAssets(relatedSourceResource, relationName);
Asset destinationAsset = findLanguageCopyWithAutoCreatedRoots(graniteSourceAsset.getPath(),
targetLanguageCode, resourceResolver);
com.adobe.granite.asset.api.Asset graniteDestinationAsset = destinationAsset
.adaptTo(com.adobe.granite.asset.api.Asset.class);
createRelationLanguageCopy(relationName, graniteDestinationAsset, relatedLinkedAssets,
targetLanguageCode, resourceResolver, pageManagerFactory);
}
}
private static void createRelationLanguageCopy(String relationName, com.adobe.granite.asset.api.Asset
graniteDestinationAsset, List relatedAssets, String targetLanguageCode, ResourceResolver
resourceResolver, PageManagerFactory pageManagerFactory) {
ArrayList resetRelationPaths = new ArrayList();
for (Asset relatedSourceAsset : relatedAssets) {
String sourceRelationPath = relatedSourceAsset.getPath();
String sourceRelationLanguageCopyPath = createOrGetLanguageCopy(resourceResolver, pageManagerFactory,
sourceRelationPath, targetLanguageCode);
resetRelationPaths.add(sourceRelationLanguageCopyPath);
}
// reset the source relations for this asset
resetAssetRelations(graniteDestinationAsset, relationName, resetRelationPaths);
}
private static String createOrGetLanguageCopy(ResourceResolver resourceResolver, PageManagerFactory pageManagerFactory, String sourcePath, String targetLanguageCode) {
String languageCopyPath = createLanguageCopy(resourceResolver, pageManagerFactory, sourcePath,
targetLanguageCode);
if (languageCopyPath == null) {
languageCopyPath = findLanguageCopyPathWithAutoCreatedRoots(sourcePath, targetLanguageCode, resourceResolver);
}
return languageCopyPath;
}
private static void createMissingDestinationLanguageCopies(ResourceResolver resourceResolver, PageManagerFactory pageManagerFactory, String assetPath, String targetLanguageCode) {
if (null == findLanguageCopyPathWithAutoCreatedRoots(assetPath, targetLanguageCode, resourceResolver)) {
createLanguageCopy(resourceResolver, pageManagerFactory, assetPath, targetLanguageCode);
}
Resource assetResource = resourceResolver.getResource(assetPath);
createMissingDestinationLanguageCopiesForRelations(ATTRIBUTE_ASSET_SOURCE_RELATION, assetResource,
targetLanguageCode, resourceResolver, pageManagerFactory);
createMissingDestinationLanguageCopiesForRelations(ATTRIBUTE_ASSET_LINKS_RELATION, assetResource,
targetLanguageCode, resourceResolver, pageManagerFactory);
createMissingDestinationLanguageCopiesForRelationsOfSources(ATTRIBUTE_ASSET_LINKS_RELATION, assetResource,
targetLanguageCode, resourceResolver, pageManagerFactory);
}
private static void createMissingDestinationLanguageCopiesForRelationsOfSources(String relationName, Resource
assetResource, String targetLanguageCode, ResourceResolver resourceResolver, PageManagerFactory
pageManagerFactory) {
List relatedSourceAssets = getRelatedAssets(assetResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
for (Asset relatedSourceAsset : relatedSourceAssets) {
Resource relatedSourceResource = relatedSourceAsset.adaptTo(Resource.class);
createMissingDestinationLanguageCopiesForRelations(relationName, relatedSourceResource,
targetLanguageCode, resourceResolver, pageManagerFactory);
}
}
private static void createMissingDestinationLanguageCopiesForRelations(String relationName, Resource assetResource,
String targetLanguageCode, ResourceResolver resourceResolver, PageManagerFactory pageManagerFactory) {
List relatedAssets = getRelatedAssets(assetResource, relationName);
if (!relatedAssets.isEmpty()) {
for (Asset relatedAsset : relatedAssets) {
String relatedAssetPath = relatedAsset.getPath();
if (null == findLanguageCopyPathWithAutoCreatedRoots(relatedAssetPath, targetLanguageCode,
resourceResolver)) {
createLanguageCopy(resourceResolver, pageManagerFactory, relatedAssetPath, targetLanguageCode);
}
}
}
}
public static List getRelatedAssets(Resource resource, String relationName) {
ArrayList relatedAssets = new ArrayList();
if (null != resource) {
com.adobe.granite.asset.api.Asset graniteSourceAsset = resource
.adaptTo(com.adobe.granite.asset.api.Asset.class);
if (null != graniteSourceAsset) {
Iterator assetRelationIterator = (Iterator) graniteSourceAsset
.listRelations(relationName);
while (assetRelationIterator.hasNext()) {
AssetRelation assetRelation = assetRelationIterator.next();
com.adobe.granite.asset.api.Asset graniteAsset = assetRelation.getAsset();
relatedAssets.add(graniteAsset.adaptTo(Asset.class));
}
}
}
return relatedAssets;
}
private static TranslationCategory getTranslationCategoryForAssetAndItsRelations(String assetPath, String
targetLanguageCode, ResourceResolver resourceResolver) {
if(getLanguageRootLocale(assetPath).equals(targetLanguageCode)) {
return TranslationCategory.NONE;
}
TranslationCategory groupCategory = TranslationCategory.NONE;
TranslationCategory currentCategory = null;
Resource sourceResource = resourceResolver.getResource(assetPath);
if (null != sourceResource) {
//check current asset
Asset assetInSourceLanguage = sourceResource.adaptTo(Asset.class);
Asset assetInDestinationLanguage = findLanguageCopyWithAutoCreatedRoots(assetPath, targetLanguageCode,
resourceResolver);
if (null != assetInDestinationLanguage) {
currentCategory = isSmartAssetUpdateRequired(assetInSourceLanguage, assetInDestinationLanguage) ?
TranslationCategory.TEMPORARY : TranslationCategory.NONE;
} else {
currentCategory = TranslationCategory.DESTINATION;
}
groupCategory = combineCategory(groupCategory, currentCategory);
if(groupCategory!=TranslationCategory.TEMPORARY){
currentCategory = getTranslationCategoryForRelation(ATTRIBUTE_ASSET_SOURCE_RELATION,
sourceResource, targetLanguageCode, resourceResolver);
groupCategory = combineCategory(groupCategory, currentCategory);
}
if(groupCategory!=TranslationCategory.TEMPORARY){
currentCategory = getTranslationCategoryForRelation(ATTRIBUTE_ASSET_LINKS_RELATION,
sourceResource, targetLanguageCode, resourceResolver);
groupCategory = combineCategory(groupCategory, currentCategory);
}
if (groupCategory!=TranslationCategory.TEMPORARY) {
currentCategory = getTranslationCategoryForRelationOfSources(ATTRIBUTE_ASSET_LINKS_RELATION,
sourceResource, targetLanguageCode, resourceResolver);
groupCategory = combineCategory(groupCategory, currentCategory);
}
}
return groupCategory;
}
private static TranslationCategory combineCategory(TranslationCategory c1, TranslationCategory c2) {
if (c1 == TranslationCategory.TEMPORARY || c2 == TranslationCategory.TEMPORARY) {
//any one temporary --> make the entire group temporary
return TranslationCategory.TEMPORARY;
}
if (c1 == TranslationCategory.NONE && c2 == TranslationCategory.NONE) {
//both doesn't need translation
return TranslationCategory.NONE;
}
//at least one DESTINATION and other NONE/DESTINATION
return TranslationCategory.DESTINATION;
}
private static TranslationCategory getTranslationCategoryForRelationOfSources(String relationName, Resource
relaterResource, String targetLanguageCode, ResourceResolver resourceResolver) {
TranslationCategory groupCategory = TranslationCategory.NONE;
List relatedSourceAssets = getRelatedAssets(relaterResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
for (Asset relatedSourceAsset : relatedSourceAssets) {
Resource relatedSourceResource = relatedSourceAsset.adaptTo(Resource.class);
TranslationCategory currentCategory = getTranslationCategoryForRelation(relationName, relatedSourceResource,
targetLanguageCode, resourceResolver);
groupCategory = combineCategory(groupCategory, currentCategory);
}
return groupCategory;
}
private static TranslationCategory getTranslationCategoryForRelation(String relationName, Resource sourceResource,
String targetLanguageCode, ResourceResolver resourceResolver) {
TranslationCategory translationCategory = TranslationCategory.NONE;
List relatedAssetsInSourceLanguage = getRelatedAssets(sourceResource, relationName);
for (Asset relatedAssetInSourceLanguage : relatedAssetsInSourceLanguage) {
String relatedAssetInSourceLanguagePath = relatedAssetInSourceLanguage.getPath();
Asset relatedAssetInDestinationLanguage = findLanguageCopyWithAutoCreatedRoots(
relatedAssetInSourceLanguagePath, targetLanguageCode, resourceResolver);
if (null != relatedAssetInDestinationLanguage) {
if (isSmartAssetUpdateRequired(relatedAssetInSourceLanguage, relatedAssetInDestinationLanguage)) {
translationCategory = TranslationCategory.TEMPORARY;
break;
}
} else {
translationCategory = TranslationCategory.DESTINATION;
}
}
return translationCategory;
}
/**
* Removes asset relations with given language code
* Useful for removing relations of an {@link com.adobe.granite.asset.api.Asset}
*
* @param graniteAsset Asset whose relations have to ve removed/added.
* @param relationName name of the relation.
* @param languageRoot the language root of the relations to remove
*/
private static void removeAssetRelationWithLanguageCode(com.adobe.granite.asset.api.Asset graniteAsset,
String relationName, String languageRoot) {
List relations = getRelationsPathList(graniteAsset, relationName);
String relationLanguageRoot;
for (String relation: relations) {
relationLanguageRoot = getLanguageRootLocale(relation);
if (relationLanguageRoot.equals(languageRoot)) {
graniteAsset.removeRelation(relationName, relation);
}
}
}
/**
* Removes relation passed as unlinkRelation followed by adding relation passed as linkRelation.
* Useful for replacing relations of an {@link com.adobe.granite.asset.api.Asset}.
*
* @param graniteAsset Asset whose relations have to ve removed/added.
* @param relationName name of the relation.
* @param unlinkRelation relations to be removed.
* @param linkRelation relations to be added.
*/
private static void adjustAssetRelations(com.adobe.granite.asset.api.Asset graniteAsset, String relationName,
String unlinkRelation, String linkRelation) {
List relations = getRelationsPathList(graniteAsset, relationName);
if (relations.contains(unlinkRelation)) {
graniteAsset.removeRelation(relationName, unlinkRelation);
}
if (!relations.contains(linkRelation)) {
graniteAsset.addRelation(relationName, linkRelation);
}
}
/**
* Removes relations of any type of a {@link com.adobe.granite.asset.api.Asset}.
* @param graniteAsset Asset whose relations have to ve removed/added.
* @param relationName name of the relation to remove
*/
private static void removeAssetRelation (com.adobe.granite.asset.api.Asset graniteAsset, String relationName) {
if (graniteAsset.listRelations(relationName).hasNext()) {
graniteAsset.removeRelation(relationName);
}
}
private static void resetAssetRelations(com.adobe.granite.asset.api.Asset graniteAsset, String relationName,
ArrayList linkRelations) {
if (graniteAsset.listRelations(relationName).hasNext()) {
graniteAsset.removeRelation(relationName);
}
for (String linkRelation : linkRelations) {
graniteAsset.addRelation(relationName, linkRelation);
}
}
private static List getRelationsPathList(com.adobe.granite.asset.api.Asset graniteAsset, String relation) {
Iterator> relationIterator = graniteAsset.listRelations(relation);
List relationsList = new ArrayList();
while (relationIterator.hasNext()) {
AssetRelation assetRelation = (AssetRelation) relationIterator.next();
com.adobe.granite.asset.api.Asset asset = assetRelation.getAsset();
String relationPath = asset.getPath();
relationsList.add(relationPath);
}
return relationsList;
}
private static String getUpdateAssetNodeSourcePath(Node node) throws RepositoryException {
if (node.isNodeType(DamConstants.NT_DAM_ASSET)) {
if (node.hasNode(JcrConstants.JCR_CONTENT)) {
Node assetContentNode = node.getNode(JcrConstants.JCR_CONTENT);
if (assetContentNode.hasProperty(ATTRIBUTE_SMART_ASSET_UPDATE_SOURCE)) {
return assetContentNode.getProperty(ATTRIBUTE_SMART_ASSET_UPDATE_SOURCE).getValue().getString();
}
}
}
return null;
}
/*
* Return the temporary language copy of asset as a resource, where the temporary language copy
* resides inside the prefix path
*/
private static Resource findTemporaryLanguageCopy (Asset asset, String prefixPath, ResourceResolver resourceResolver) {
String tempLCPath = prefixPath + '/' + asset.getPath();
Resource tempLCResource = resourceResolver.getResource(tempLCPath);
if (tempLCResource != null) {
return tempLCResource;
}
return null;
}
/*
* For each temporary copy of source asset, add the new derived relation and remove the others relations
*/
private static void adjustDerivedAndRemoveOthersForSourceAssetsTempLC(List relatedSourceAssets, String destinationAssetPath,
String prefixPath, String sourceLanguageRoot, ResourceResolver resourceResolver) {
for (Asset sourceDamAsset: relatedSourceAssets) {
Resource sourceDamAssetTempLC = findTemporaryLanguageCopy(sourceDamAsset, prefixPath, resourceResolver);
if (sourceDamAssetTempLC != null) {
com.adobe.granite.asset.api.Asset sourceGraniteAssetTempLC = sourceDamAssetTempLC.adaptTo(com.adobe.granite.asset.api.Asset.class);
if (sourceGraniteAssetTempLC != null) {
// First remove relations that point to old language copies
removeAssetRelationWithLanguageCode(sourceGraniteAssetTempLC, ATTRIBUTE_ASSET_DERIVED_RELATION, sourceLanguageRoot);
// Add this new derived relation
sourceGraniteAssetTempLC.addRelation(ATTRIBUTE_ASSET_DERIVED_RELATION, destinationAssetPath);
// Remove the others relation
removeAssetRelation(sourceGraniteAssetTempLC, ATTRIBUTE_ASSET_OTHERS_RELATION);
}
}
}
}
private static boolean createUpdateLanguageCopyWithAssetRelationsRequired(final ResourceResolver resourceResolver,
final String destinationPath) throws RepositoryException {
Resource destinationResource = resourceResolver.resolve(destinationPath);
if (null != destinationResource) {
Node destinationNode = destinationResource.adaptTo(Node.class);
String updateAssetSourcePath = getUpdateAssetNodeSourcePath(destinationNode);
if (null != updateAssetSourcePath) {
return true;
}
}
return false;
}
/**
* This method creates temporary language copy of an asset/folder and its source(for example psd for jpeg) in case
* temporary asset translation is required. Finally, relations are changed with their temporary copies.
*
* @param resourceResolver
* @param pageManagerFactory
* @param destinationPath - source for creating language copy
* @param targetLanguageCode - destination language code
* @param prefixPath - Root path where language copies are created
* @return created variant temporary language copy path if created, otherwise returns destinationPath
*/
public static String createUpdateLanguageCopyWithAssetRelations(final ResourceResolver resourceResolver,
final PageManagerFactory pageManagerFactory, final String destinationPath, final String targetLanguageCode,
String prefixPath) throws RepositoryException {
boolean updateRequired = createUpdateLanguageCopyWithAssetRelationsRequired(resourceResolver, destinationPath);
String variantPath = destinationPath;
if (updateRequired) {
Resource destinationResource = resourceResolver.resolve(destinationPath);
List relatedSourceAssets = getRelatedAssets(destinationResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
if (null != destinationResource) {
Node destinationNode = destinationResource.adaptTo(Node.class);
String updateAssetSourcePath = getUpdateAssetNodeSourcePath(destinationNode);
String updateAssetLanguageLocale = getLanguageRootLocale(updateAssetSourcePath);
variantPath = createUpdateLanguageCopy(resourceResolver, pageManagerFactory, updateAssetSourcePath,
targetLanguageCode, prefixPath);
createUpdateLanguageCopyForRelation(ATTRIBUTE_ASSET_SOURCE_RELATION, updateAssetSourcePath, variantPath,
targetLanguageCode, prefixPath, resourceResolver, pageManagerFactory);
//Adjust the derived, others relations for the source assets
adjustDerivedAndRemoveOthersForSourceAssetsTempLC(relatedSourceAssets, destinationPath, prefixPath,
updateAssetLanguageLocale, resourceResolver);
createUpdateLanguageCopyForRelation(ATTRIBUTE_ASSET_LINKS_RELATION, updateAssetSourcePath, variantPath,
targetLanguageCode, prefixPath, resourceResolver, pageManagerFactory);
createUpdateLanguageCopyForRelationOfSources(ATTRIBUTE_ASSET_LINKS_RELATION, updateAssetSourcePath,
variantPath, targetLanguageCode, prefixPath, resourceResolver, pageManagerFactory);
//update Content Fragment Associated Collection
if (isContentFragment(destinationResource.adaptTo(Asset.class))) {
String[] targetLanguageCodeArray = {targetLanguageCode};
try {
createOrUpdateLanguageCopyForAssociatedContentNode(resourceResolver, pageManagerFactory,
updateAssetSourcePath, targetLanguageCodeArray, prefixPath);
} catch (Exception e) {
log.error("could not create or update langauge copy for associated content node for {}",
prefixPath + destinationPath, e);
}
}
}
}
return variantPath;
}
private static void createUpdateLanguageCopyForRelationOfSources(String relationName, String
updateAssetSourcePath, String variantPath, String targetLanguageCode, String prefixPath, ResourceResolver
resourceResolver, PageManagerFactory pageManagerFactory) {
Resource updateAssetSourceResource = resourceResolver.getResource(updateAssetSourcePath);
List relatedSources = getRelatedAssets(updateAssetSourceResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
for (Asset relatedSource : relatedSources) {
String relatedSourcePath = relatedSource.getPath();
String LCofRelatedSource = findLanguageCopyPathWithAutoCreatedRoots(relatedSourcePath,
targetLanguageCode, resourceResolver);
String tempLCofRelatedSource = prefixPath + LCofRelatedSource;
createUpdateLanguageCopyForRelation(relationName, relatedSourcePath, tempLCofRelatedSource,
targetLanguageCode, prefixPath, resourceResolver, pageManagerFactory);
}
}
private static void createUpdateLanguageCopyForRelation(String relationName, String updateAssetSourcePath, String
variantPath, String targetLanguageCode, String prefixPath, ResourceResolver resourceResolver,
PageManagerFactory pageManagerFactory) {
//variantPath will have relations which should point to source language copies
adjustRelationsForAssetLanguageCopy(variantPath, relationName, targetLanguageCode,
resourceResolver);
Resource variantResource = resourceResolver.getResource(variantPath);
Resource updateAssetSourceResource = resourceResolver.getResource(updateAssetSourcePath);
List relatedAssets = getRelatedAssets(updateAssetSourceResource, relationName);
for (Asset relatedAsset : relatedAssets) {
String relatedAssetPath = relatedAsset.getPath();
if (relatedAssetPath.startsWith(DamConstants.MOUNTPOINT_ASSETS)) {
String tempLCOfRelatedAsset = createUpdateLanguageCopy(resourceResolver, pageManagerFactory,
relatedAssetPath, targetLanguageCode, prefixPath);
String LCofRelatedAsset = findLanguageCopyPathWithAutoCreatedRoots(relatedAssetPath,
targetLanguageCode, resourceResolver);
com.adobe.granite.asset.api.Asset graniteVariantAsset = variantResource.adaptTo(com.adobe.granite
.asset.api.Asset.class);
adjustAssetRelations(graniteVariantAsset, relationName, LCofRelatedAsset, tempLCOfRelatedAsset);
// Remove the others relation for the variant language copy
removeAssetRelation(graniteVariantAsset, ATTRIBUTE_ASSET_OTHERS_RELATION);
}
}
}
private static void adjustRelationsForAssetLanguageCopy(String assetPath, String relationName, String
targetLanguageCode, ResourceResolver resourceResolver) {
Resource assetResource = resourceResolver.resolve(assetPath);
if (null != assetResource) {
List relatedAssets = getRelatedAssets(assetResource, relationName);
for (Asset relatedAsset : relatedAssets) {
String relatedAssetPath = relatedAsset.getPath();
String sourceLanguageCode = getLanguageRootLocale(relatedAssetPath);
if (null == sourceLanguageCode || !sourceLanguageCode.equals(targetLanguageCode)) {
String languageCopyPath = findLanguageCopyPathWithAutoCreatedRoots(relatedAssetPath,
targetLanguageCode, resourceResolver);
com.adobe.granite.asset.api.Asset graniteAsset = assetResource.adaptTo(com.adobe.granite.asset
.api.Asset.class);
adjustAssetRelations(graniteAsset, relationName, relatedAssetPath, languageCopyPath);
}
}
}
}
public static String findLanguageCopyPathWithAutoCreatedRoots(final String assetPath,
final String languageCode, final ResourceResolver resolver) {
Asset languageCopy = findLanguageCopyWithAutoCreatedRoots(assetPath, languageCode, resolver);
return null != languageCopy ? languageCopy.getPath() : null;
}
public static Resource findLanguageCopyWithAutoCreatedRootsForAssetOrNTFolder(final Resource resource, final String
languageCode, final ResourceResolver resolver) throws RepositoryException {
if (null != resource.adaptTo(Asset.class)) {
Asset languageCopy = findLanguageCopyWithAutoCreatedRoots(resource.getPath(), languageCode, resolver);
if (null != languageCopy) {
return languageCopy.adaptTo(Resource.class);
}
} else if (isFolder(resource)) {
Node folderNode = findLanguageCopyForNTFolderWithAutoCreatedRoots(resource.getPath(), languageCode,
resolver);
if (null != folderNode) {
return resolver.getResource(folderNode.getPath());
}
}
return null;
}
public static Asset findLanguageCopyWithAutoCreatedRoots(final String assetPath, final String languageCode,
final ResourceResolver resolver) {
Resource assetResource = resolver.getResource(assetPath);
if (assetResource == null || assetResource.adaptTo(Asset.class) == null) {
return null;
}
Asset asset = null;
String languageRootPath = LanguageUtil.getLanguageRoot(assetPath);
String languageRootParentPath = null;
String contentPath = null;
if (languageRootPath != null) {
contentPath = assetPath.replaceFirst(languageRootPath, "");
languageRootParentPath = Text.getRelativeParent(
languageRootPath, 1);
} else {
//CQ-61450 User creates a language copy of a page from sites and language root for the asset (referenced in site) does not exist
if (Text.getRelativeParent(assetPath, 1).equals(DamConstants.MOUNTPOINT_ASSETS)) {
//Asset is directly under DamConstants.MOUNTPOINT_ASSETS
languageRootParentPath = DamConstants.MOUNTPOINT_ASSETS;
} else if (assetPath.startsWith(DamConstants.MOUNTPOINT_ASSETS + "/")) {
//Asset follows structure DamConstants.MOUNTPOINT_ASSETS//
int parentOfRootPathLength = assetPath.indexOf('/', DamConstants.MOUNTPOINT_ASSETS.length() + 1);
if (parentOfRootPathLength < 0 || assetPath.length() <= parentOfRootPathLength) {
return null;
}
languageRootParentPath = assetPath.substring(0, parentOfRootPathLength);
}
contentPath = assetPath.replaceFirst(languageRootParentPath, "");
}
String destLanguageRootPath = getDestinationLanguageRoot(languageRootParentPath, languageCode, resolver);
String assetPathLC = destLanguageRootPath + contentPath;
Resource assetResourceLC = resolver.getResource(assetPathLC);
if (assetResourceLC != null) {
asset = assetResourceLC.adaptTo(Asset.class);
}
return asset;
}
private static Node findLanguageCopyForNTFolderWithAutoCreatedRoots(final String folderPath, final String
languageCode, final ResourceResolver resolver) throws RepositoryException {
Resource folderResource = resolver.getResource(folderPath);
if (folderResource == null) {
return null;
}
Node folderNode = folderResource.adaptTo(Node.class);
if (!folderNode.isNodeType(JcrConstants.NT_FOLDER)) {
return null;
}
Node folderNodeLanguageCopy = null;
String languageRootPath = LanguageUtil.getLanguageRoot(folderPath);
String languageRootParentPath = null;
String contentPath = null;
if (languageRootPath != null) {
contentPath = folderPath.replaceFirst(languageRootPath, "");
languageRootParentPath = Text.getRelativeParent(
languageRootPath, 1);
} else {
//CQ-61450 User creates a language copy of a page from sites and language root for the asset (referenced in site) does not exist
if (Text.getRelativeParent(folderPath, 1).equals(DamConstants.MOUNTPOINT_ASSETS)) {
//Asset is directly under DamConstants.MOUNTPOINT_ASSETS
languageRootParentPath = DamConstants.MOUNTPOINT_ASSETS;
} else if (folderPath.startsWith(DamConstants.MOUNTPOINT_ASSETS + "/")) {
//Asset follows structure DamConstants.MOUNTPOINT_ASSETS//
int parentOfRootPathLength = folderPath.indexOf('/', DamConstants.MOUNTPOINT_ASSETS.length() + 1);
if (parentOfRootPathLength < 0 || folderPath.length() <= parentOfRootPathLength) {
return null;
}
languageRootParentPath = folderPath.substring(0, parentOfRootPathLength);
}
contentPath = folderPath.replaceFirst(languageRootParentPath, "");
}
String destLanguageRootPath = getDestinationLanguageRoot(languageRootParentPath, languageCode, resolver);
String assetPathLC = destLanguageRootPath + contentPath;
Resource folderResourceLC = resolver.getResource(assetPathLC);
if (folderResourceLC != null) {
folderNodeLanguageCopy = folderResourceLC.adaptTo(Node.class);
}
return folderNodeLanguageCopy;
}
public static void afterReplacingUpdatedAsset(String destinationPath, Session userSession, String prefixPath,
ResourceResolver resourceResolver) throws RepositoryException {
Resource resource = resourceResolver.getResource(destinationPath);
if (null != resource) {
com.adobe.granite.asset.api.Asset graniteAsset = resource.adaptTo(com.adobe.granite.asset.api.Asset.class);
afterReplacingUpdatedAssetWithRelation(ATTRIBUTE_ASSET_SOURCE_RELATION, graniteAsset, prefixPath);
afterReplacingUpdatedAssetWithRelation(ATTRIBUTE_ASSET_LINKS_RELATION, graniteAsset, prefixPath);
afterReplacingUpdatedAssetForSources(ATTRIBUTE_ASSET_LINKS_RELATION, graniteAsset, prefixPath);
}
userSession.save();
}
private static void afterReplacingUpdatedAssetForSources(String relationName,
com.adobe.granite.asset.api.Asset relaterAsset, String prefixPath) {
Resource relaterResource = relaterAsset.adaptTo(Resource.class);
List relatedSources = getRelatedAssets(relaterResource, ATTRIBUTE_ASSET_SOURCE_RELATION);
for (Asset relatedSource : relatedSources) {
com.adobe.granite.asset.api.Asset graniteSource = relatedSource
.adaptTo(com.adobe.granite.asset.api.Asset.class);
afterReplacingUpdatedAssetWithRelation(relationName, graniteSource, prefixPath);
}
}
private static void afterReplacingUpdatedAssetWithRelation(String relationName,
com.adobe.granite.asset.api.Asset graniteAsset, String prefixPath) {
List relations = getRelationsPathList(graniteAsset, relationName);
for (String relation : relations) {
String replacedRelationPath = removePrefix(relation, prefixPath);
if (null != replacedRelationPath) {
adjustAssetRelations(graniteAsset, relationName, relation, replacedRelationPath);
}
}
}
private static String removePrefix(String string, String prefix) {
return string.startsWith(prefix) ? string.replaceFirst(prefix, "") : null;
}
/**
* Returns the locale for the given path. Supports language root structures
* /<root>/\<path>lt;Language>_\<Country> and /\<root>lt;path>lt;Language>
* @param path
* @return locale or null in case any supported locale does not exist in the given path
*/
public static String getLanguageRootLocale(String path) {
String languageRootPath = LanguageUtil.getLanguageRoot(path);
if (null != languageRootPath) {
return languageRootPath.substring(languageRootPath.lastIndexOf("/") + 1);
}
return null;
}
public static String getLanguageDisplayName(ResourceResolver resolver, String langCode) {
String langDisplayName = "";
Resource languagesHome = resolver.getResource(DEFAULT_LANGUAGES_HOME);
Resource language = getLanguage(languagesHome, langCode);
if (language != null) {
ValueMap langProperties = language.adaptTo(ValueMap.class);
langDisplayName = langProperties.get("language", String.class);
}
return (langDisplayName != null && !langDisplayName.isEmpty()) ? langDisplayName : langCode;
}
private static Resource getLanguage(Resource languagesHome, String languageCode) {
if (languagesHome != null) {
languageCode = languageCode.toLowerCase();
String langWithUnderscore = languageCode.replace("-", "_");
String langWithHyphen = languageCode.replace("_", "-");
Resource languageRes = languagesHome.getChild(langWithUnderscore);
if (languageRes == null) {
languageRes = languagesHome.getChild(langWithHyphen);
}
return languageRes;
}
return null;
}
/**
* Returns a list after replacing paths with their existing language copies. If a language copy of a path does
* not exist, the path is retained in the returned list.
*
* @param paths The list of paths whose language copy has to be replaced
* @param destinationLanguageCode language code of destination language copy
* @param resourceResolver
* @return a list after replacing paths with their existing language copies.
*/
public static List replaceWithExistingLanguageCopiesIfPossible(List paths,
String destinationLanguageCode, ResourceResolver resourceResolver) {
ArrayList resolveLanguageCopies = new ArrayList();
if (null == destinationLanguageCode) {
return paths;
}
for (String path : paths) {
String languageCopyPath = DamLanguageUtil.findLanguageCopyPathWithAutoCreatedRoots(path,
destinationLanguageCode, resourceResolver);
if (null != languageCopyPath) {
path = languageCopyPath;
}
resolveLanguageCopies.add(path);
}
return resolveLanguageCopies;
}
private static ArrayList getContentFragmentAssociatedAssets(Node currentNode, ResourceResolver
resourceResolver) throws RepositoryException {
Resource associatedContentResource = getAssociatedContentResource(currentNode.getPath(), resourceResolver);
if (associatedContentResource != null) {
ResourceCollection associatedContent = associatedContentResource.adaptTo(ResourceCollection.class);
return getAssetsFromAssociatedContentNode(associatedContent);
}
return new ArrayList();
}
public static ArrayList getAssetsFromAssociatedContent(Node contentFragmentNode, String destinationLanguage,
ResourceResolver resourceResolver) throws RepositoryException {
ArrayList returnList = new ArrayList();
Node associatedContentNode = getAssociatedContentNode(contentFragmentNode);
if (null != associatedContentNode) {
Resource associatedContentResource = resourceResolver.getResource(associatedContentNode.getPath());
Iterator collectionResourceIterator = getResourcesFromCollection(associatedContentResource);
//iterate over all collections
while (collectionResourceIterator.hasNext()) {
Resource collectionResource = collectionResourceIterator.next();
//check for collection
ResourceCollection damCollection = collectionResource.adaptTo(ResourceCollection.class);
if (damCollection != null) {
//get destination asset list
ArrayList collectionAssets = new ArrayList();
addAssetsFromCollection(damCollection, collectionAssets);
addAssetsFromNestedCollections(collectionResource, collectionAssets);
ArrayList sourceCollectionAssetLanguageCopies = getAssetLanguageCopiesFromSourceOfCollection(
collectionResource, destinationLanguage, resourceResolver);
if (null != sourceCollectionAssetLanguageCopies) {
//remove asset not present in source language copy of collection
removeLanguageCopiesWithoutSource(collectionAssets, sourceCollectionAssetLanguageCopies);
}
returnList.addAll(collectionAssets);
}
}
}
return returnList;
}
private static void addAssetsFromNestedCollections(Resource collectionResource, ArrayList collectionAssets)
throws RepositoryException {
//nested collection
HashSet nestedCollections = new HashSet();
getNestedCollections(collectionResource, nestedCollections);
for (Resource resource : nestedCollections) {
ResourceCollection rc = resource.adaptTo(ResourceCollection.class);
addAssetsFromCollection(rc, collectionAssets);
}
}
private static Node getAssociatedContentNode(Node currentNode) throws RepositoryException {
if(currentNode.hasNode(ASSOCIATED_CONTENT_RELATIVE_PATH)) {
return currentNode.getNode(ASSOCIATED_CONTENT_RELATIVE_PATH);
}
if(currentNode.hasNode(ASSOCIATED_CONTENT_CHILD)) {
return currentNode.getNode(ASSOCIATED_CONTENT_CHILD);
}
return null;
}
private static Resource getAssociatedContentResource(String cfPath, ResourceResolver resourceResolver) throws
RepositoryException {
Resource resource = resourceResolver.getResource(cfPath + "/" + ASSOCIATED_CONTENT_RELATIVE_PATH);
if (null == resource) {
resource = resourceResolver.getResource(cfPath + "/" + ASSOCIATED_CONTENT_CHILD);
}
return resource;
}
private static void removeLanguageCopiesWithoutSource(ArrayList collectionAssets, ArrayList
sourceCollectionLanguageCopyPaths) {
if (null != sourceCollectionLanguageCopyPaths) {
for (int ndx = collectionAssets.size() - 1; ndx >= 0; ndx--) {
Asset collectionAsset = collectionAssets.get(ndx);
if (!sourceCollectionLanguageCopyPaths.contains(collectionAsset.getPath())) {
collectionAssets.remove(ndx);
}
}
}
}
private static ArrayList getAssetLanguageCopiesFromSourceOfCollection(Resource collectionResource, String
destinationLanguage, ResourceResolver resourceResolver) throws RepositoryException {
ArrayList sourceAssetList = getAssetsFromSourceOfCollection(collectionResource, resourceResolver);
if (null != sourceAssetList) {
ArrayList destinationCollectionAssets = new ArrayList();
for (Asset asset : sourceAssetList) {
Asset languageCopy = DamLanguageUtil.findLanguageCopyWithAutoCreatedRoots(asset.getPath(),
destinationLanguage, resourceResolver);
if (null != languageCopy) {
destinationCollectionAssets.add(languageCopy.getPath());
}
}
return destinationCollectionAssets;
}
return null;
}
private static ArrayList getAssetsFromSourceOfCollection(Resource collectionResource,
ResourceResolver resourceResolver) throws RepositoryException {
Resource sourceCollection = getSourceCollection(collectionResource, resourceResolver);
if (null != sourceCollection) {
ArrayList sourceAssetList = getAssetsFromCollection(sourceCollection);
deleteProperty(collectionResource, ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY);
return sourceAssetList;
}
return null;
}
private static void deleteProperty(Resource collectionResource, String property) throws RepositoryException {
Node collectionNode = collectionResource.adaptTo(Node.class);
if (collectionNode.hasProperty(property)) {
javax.jcr.Property sourceCollectionProperty = collectionNode.getProperty(property);
sourceCollectionProperty.remove();
}
}
private static Resource getSourceCollection(Resource collectionResource, ResourceResolver resourceResolver)
throws RepositoryException {
Node collectionNode = collectionResource.adaptTo(Node.class);
if (collectionNode.hasProperty(ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY)) {
javax.jcr.Property sourceCollectionProperty = collectionNode.getProperty(
ATTRIBUTE_COLLECTION_SOURCE_LANGUAGE_COPY);
String sourceCollectionPath = sourceCollectionProperty.getString();
return resourceResolver.getResource(sourceCollectionPath);
}
return null;
}
private static ArrayList getAssetsFromCollection(Resource collectionResource)
throws RepositoryException {
ArrayList assetList = new ArrayList();
return addAssetsFromCollectionResource(collectionResource, assetList);
}
private static ArrayList getAssetsFromAssociatedContentNode(ResourceCollection resourceCollection) throws
RepositoryException {
ArrayList assetList = new ArrayList();
Iterator resourceIterator = resourceCollection.getResources();
while (resourceIterator.hasNext()) {
Resource collectionResource = resourceIterator.next();
addAssetsFromCollectionResource(collectionResource, assetList);
}
return assetList;
}
private static ArrayList addAssetsFromCollectionResource(Resource collectionResource,
ArrayList assetList) throws RepositoryException {
if (null == collectionResource) {
return assetList;
}
ResourceCollection resourceCollection = collectionResource.adaptTo(ResourceCollection.class);
if (null == resourceCollection) {
return assetList;
}
addAssetsFromCollection(resourceCollection, assetList);
addAssetsFromNestedCollections(collectionResource, assetList);
return assetList;
}
private static void getNestedCollections(Resource sourceCollectionResource, HashSet updatedCollections)
throws RepositoryException {
ResourceCollection sourceCollection = sourceCollectionResource.adaptTo(ResourceCollection.class);
Iterator sourceResources = sourceCollection.getResources();
while (sourceResources.hasNext()) {
Resource sourceResource = sourceResources.next();
if (isDamCollection(sourceResource) && !updatedCollections.contains(sourceResource)) {
updatedCollections.add(sourceResource);
getNestedCollections(sourceResource, updatedCollections);
}
}
}
private static void addAssetsFromCollection(ResourceCollection resourceCollection, ArrayList assetList)
throws RepositoryException {
Iterator resourceIterator = resourceCollection.getResources();
while (resourceIterator.hasNext()) {
Resource resource = resourceIterator.next();
Asset asset = resource.adaptTo(Asset.class);
if (asset != null && !isContentFragment(asset)) {
assetList.add(asset);
} else if (isFolder(resource)) {
Iterator assetIterator = DamUtil.getAssets(resource);
while (assetIterator.hasNext()) {
Asset folderAsset = assetIterator.next();
if(!isContentFragment(folderAsset)) {
assetList.add(folderAsset);
}
}
}
}
}
private static boolean isTranslateAssociatedContent(Resource contentFragmentResource, ResourceResolver
resourceResolver) {
boolean retVal = false;
//get cloud config resource
Resource cloudConfigResource = getCloudConfigResourceAppliedOnResource(contentFragmentResource,
MachineTranslationCloudConfig.class, null, resourceResolver);
//check if translation is required
if (null != cloudConfigResource) {
MachineTranslationCloudConfig cloudConfig = cloudConfigResource.adaptTo(
MachineTranslationCloudConfig.class);
if (null != cloudConfig) {
retVal = cloudConfig.isTranslateAssociatedContentForAssets();
}
}
return retVal;
}
private static boolean isTranslateInlineMediaAssets(String contentFragmentPath, ResourceResolver
resourceResolver) {
boolean retVal = false;
Resource contentFragmentResource = resourceResolver.getResource(contentFragmentPath);
if (null != contentFragmentResource) {
//get cloud config resource
Resource cloudConfigResource = getCloudConfigResourceAppliedOnResource(contentFragmentResource,
MachineTranslationCloudConfig.class, null, resourceResolver);
//check if translation is required
if (null != cloudConfigResource) {
MachineTranslationCloudConfig cloudConfig = cloudConfigResource.adaptTo(
MachineTranslationCloudConfig.class);
if (null != cloudConfig) {
retVal = cloudConfig.isTranslateInlineMediaAssets();
}
}
}
return retVal;
}
private static Resource getContentResource(Resource resource) {
if(resource != null) {
boolean isContentNode = resource.getPath().equals(JcrConstants.JCR_CONTENT);
Resource content;
if (!isContentNode) {
content = resource.getChild(JcrConstants.JCR_CONTENT);
} else {
content = resource;
}
return content;
}
return null;
}
private static Resource getCloudConfigResourceAppliedOnResource(Resource resource,
Class> cloudConfigClass, String strCloudConfigResourceType, ResourceResolver resourceResolver) {
String cloudConfigPath = getCloudConfigPathAppliedOnResourceFromClassOrResourceType(resource, cloudConfigClass,
strCloudConfigResourceType, resourceResolver);
if (null != cloudConfigPath) {
return resourceResolver.getResource(cloudConfigPath);
}
return null;
}
/**
* Returns the path of cloud config applied on or inherited by a resource.
*/
private static String getCloudConfigPathAppliedOnResourceFromClassOrResourceType(Resource resource,
Class> cloudConfigClass, String strCloudConfigResourceType, ResourceResolver resourceResolver) {
if (resource == null || (cloudConfigClass == null && strCloudConfigResourceType == null)) {
return null;
}
log.debug("In Function: getCloudConfigAppliedOnResource({})", resource.getPath());
String strCloudConfigPath = null;
String[] appliedCloudConfigs = null;
if (resourceResolver != null) {
Resource content = getContentResource(resource);
if (content != null) {
if (log.isDebugEnabled()) {
log.debug("Resource: {}", resource.getPath());
log.debug("Content: {}", content.getPath());
}
boolean isContextAwareConfig = false;
if (ResourceUtil.getValueMap(content).get(ATTRIBUTE_CA_CONFIG_PROPERTY) != null) {
isContextAwareConfig = true;
}
// First look for context aware cloud configurations
if (isContextAwareConfig) {
try {
appliedCloudConfigs = getCAConfigs(resource);
} catch (Exception e) {
log.error("Failed to get configs.", e);
}
}
// if no configurations found, look for legacy cloud configurations
if (appliedCloudConfigs == null || appliedCloudConfigs.length == 0) {
try {
appliedCloudConfigs = (String[]) ResourceUtil.getValueMap(content).get(
ATTRIBUTE_CLOUD_CONFIG_PROPERTY);
} catch (ClassCastException cce) {
log.debug("Trying to cast as String as String[] failed");
String singleValue = (String) ResourceUtil.getValueMap(content).get(
ATTRIBUTE_CLOUD_CONFIG_PROPERTY);
if (singleValue != null && !"".equals(singleValue)) {
appliedCloudConfigs = new String[1];
appliedCloudConfigs[0] = singleValue;
}
}
}
if (appliedCloudConfigs != null) {
for (String appliedCloudConfig : appliedCloudConfigs) {
Resource appliedConfig = resourceResolver.getResource(appliedCloudConfig);
if (cloudConfigClass != null) {
if (appliedConfig != null && appliedConfig.adaptTo(cloudConfigClass) != null) {
strCloudConfigPath = appliedCloudConfig;
log.debug("Found ObjectCloudConfig {}", strCloudConfigPath);
return strCloudConfigPath;
} else {
log.debug("Applied Cloud Config {} is not of type {}.", appliedCloudConfig,
cloudConfigClass.toString());
}
} else {
Resource appliedConfigContent = getContentResource(appliedConfig);
if (appliedConfigContent != null) {
String strCurrentResourceType = appliedConfigContent.getResourceType();
if (strCloudConfigResourceType.equals(strCurrentResourceType)) {
strCloudConfigPath = appliedCloudConfig;
log.debug("Found ObjectCloudConfig {}", strCloudConfigPath);
return strCloudConfigPath;
} else {
log.debug("Applied Cloud Config {} is not of type {}.", appliedCloudConfig,
strCloudConfigResourceType);
}
}
}
}
}
}
//getCloudConfigPathApplied on parent resource
strCloudConfigPath = getCloudConfigPathAppliedOnResourceFromClassOrResourceType(resource.getParent(),
cloudConfigClass, strCloudConfigResourceType, resourceResolver);
} else {
log.warn("Failed to get resourceResolver");
}
return strCloudConfigPath;
}
private static String[] getCAConfigs(Resource resource) throws Exception {
ArrayList caConfigs = new ArrayList();
Conf conf = resource.adaptTo(Conf.class);
if (conf != null) {
// get TIF config
Collection tifCollection = conf.getListResources(CACONFIG_TRANSLATIONCFG_PATH);
if (null == tifCollection) {
return new String[0];
}
Resource tif = getConfigFromCollection(tifCollection);
caConfigs.add(tif.getPath());
}
String[] caConfigsArray = new String[caConfigs.size()];
return caConfigs.toArray(caConfigsArray);
}
private static Resource getConfigFromCollection(Collection tifCollection) {
Iterator tifIterator = tifCollection.iterator();
ArrayList tifList = new ArrayList();
while (tifIterator.hasNext()) {
tifList.add(tifIterator.next());
}
if (tifList.size() == 1) {
return tifList.get(0);
} else if (tifList.size() > 1) {
// custom configuration
for (int ndx = 0; ndx < tifList.size(); ndx++) {
Resource currTif = tifList.get(ndx);
if (currTif.getPath().startsWith(CACONFIG_ROOT) && !currTif.getPath().startsWith(CACONFIG_GLOBAL)) {
return currTif;
}
}
String[] fallbackPaths = {CACONFIG_GLOBAL, "/apps"};
// fallback from /conf/global, then apps
// case of /libs taken care of in tifList.size() == 1
for (String fallbackPath : fallbackPaths) {
for (int ndx = 0; ndx < tifList.size(); ndx++) {
Resource currTif = tifList.get(ndx);
if (currTif.getPath().startsWith(fallbackPath)) {
return currTif;
}
}
}
}
return null;
}
private static HashSet getEmbeddedAssets(String contentFragmentNodePath, ResourceResolver resourceResolver)
throws RepositoryException, IOException {
log.debug("In Function: getEmbeddedAssets");
HashSet embeddedAssets = new HashSet();
NodeIterator ntFileNodes = getAllNtFilesAtPath(resourceResolver, contentFragmentNodePath, log);
if (ntFileNodes != null) {
while (ntFileNodes.hasNext()) {
Node variationNode = ntFileNodes.nextNode();
String mimeType = getMimeType(variationNode);
String jcrDataProperty = JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA;
if (mimeType.equals(MIME_TYPE_HTML) && variationNode.hasProperty(jcrDataProperty)) {
Property variationProperty = variationNode.getProperty(jcrDataProperty);
String variationData = getVariationData(variationProperty);
if (!StringUtils.isEmpty(variationData)) {
HashSet embeddedAssetsForVariation = getEmbeddedAssetsForVariation(variationData,
resourceResolver);
embeddedAssets.addAll(embeddedAssetsForVariation);
}
}
}
}
return embeddedAssets;
}
private static void replaceEmbeddedAssets(String contentFragmentNodePath, String targetLanguageCode,
ResourceResolver resourceResolver) throws RepositoryException, IOException {
log.debug("In Function: replaceEmbeddedAssets");
NodeIterator ntFileNodes = getAllNtFilesAtPath(resourceResolver, contentFragmentNodePath, log);
if (ntFileNodes != null) {
while (ntFileNodes.hasNext()) {
Node variationNode = ntFileNodes.nextNode();
String mimeType = getMimeType(variationNode);
String jcrDataProperty = JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA;
if (mimeType.equals(MIME_TYPE_HTML) && variationNode.hasProperty(jcrDataProperty)) {
Property variationProperty = variationNode.getProperty(jcrDataProperty);
String variationData = getVariationData(variationProperty);
if (!StringUtils.isEmpty(variationData)) {
String replacementData = replaceEmbeddedAssetsForVariation(variationData, targetLanguageCode,
resourceResolver);
ValueFactory valueFactory = resourceResolver.adaptTo(Session.class).getValueFactory();
Value replacementValue = valueFactory.createValue(replacementData, PropertyType.BINARY);
variationProperty.setValue(replacementValue);
}
}
}
}
}
private static String getVariationData(Property variationProperty) throws RepositoryException, IOException {
InputStream is = null;
String variationData = null;
is = variationProperty.getValue().getBinary().getStream();
try {
variationData = IOUtils.toString(is, "UTF-8");
} finally {
is.close();
}
return variationData;
}
private static String getMimeType(Node variation) throws RepositoryException {
String retVal = "";
if (variation.hasNode(JcrConstants.JCR_CONTENT)) {
Node contentNode = variation.getNode(JcrConstants.JCR_CONTENT);
if (contentNode.hasProperty(JcrConstants.JCR_MIMETYPE)) {
retVal = contentNode.getProperty(JcrConstants.JCR_MIMETYPE).getString();
}
}
return retVal;
}
private static NodeIterator getAllNtFilesAtPath(ResourceResolver resolver, String path, Logger logger) {
logger.trace("In function: getAllNtFilesAtPath path:{}", path);
try {
Session session = resolver.adaptTo(Session.class);
QueryManager qm = session.getWorkspace().getQueryManager();
QueryResult result;
result =
qm.createQuery("/jcr:root" + ISO9075.encodePath(path) + "//element(*, " + JcrConstants.NT_FILE + ")",
Query.XPATH).execute();
return result.getNodes();
} catch (RepositoryException e) {
logger.error("Can't get nt:file from {}", path, e);
return null;
}
}
private static HashSet getEmbeddedAssetsForVariation(String variationData, ResourceResolver
resourceResolver) {
log.debug("In Function: getEmbeddedAssetsForVariation");
HashSet embeddedAssets = new HashSet();
HashSet assetPaths = getEmbeddedAssetPaths(variationData);
for (String assetPath : assetPaths) {
Resource resource = resourceResolver.getResource(decodeURL(assetPath));
if (null != resource) {
Asset asset = resource.adaptTo(Asset.class);
if (null != asset) {
embeddedAssets.add(asset);
}
}
}
return embeddedAssets;
}
private static String decodeURL(String url) {
try {
return URIUtil.decode(url);
} catch (URIException e) {
log.error("could not decode url : {}", url, e);
return url;
}
}
private static String encodeURL(String url) {
try {
return URIUtil.encodePath(url);
} catch (URIException e) {
log.error("could not encode url : {}", url, e);
return url;
}
}
private static String replaceEmbeddedAssetsForVariation(String variationData, String targetLanguageCode,
ResourceResolver resourceResolver) {
log.debug("In Function: replaceEmbeddedAssetsForVariation");
String regEx = getRegexForInlineMediaAssets();
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(variationData);
int lastEnd = 0;
String updatedVariationData = "";
while (matcher.find()) {
String sourceCopyPath = matcher.group(getRegexGroupInlineMediaAssets());
sourceCopyPath = decodeURL(sourceCopyPath);
String languageCopyPath = DamLanguageUtil.findLanguageCopyPathWithAutoCreatedRoots(sourceCopyPath,
targetLanguageCode,
resourceResolver);
languageCopyPath = encodeURL(languageCopyPath);
int start = matcher.start(getRegexGroupInlineMediaAssets());
int end = matcher.end(getRegexGroupInlineMediaAssets());
updatedVariationData += variationData.substring(lastEnd, start) + languageCopyPath;
lastEnd = end;
}
updatedVariationData += variationData.substring(lastEnd);
return updatedVariationData;
}
private static HashSet getEmbeddedAssetPaths(String variationData) {
log.debug("In Function: getEmbeddedAssetPaths");
HashSet assetPaths = new HashSet();
String regEx = getRegexForInlineMediaAssets();
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(variationData);
while (matcher.find()) {
assetPaths.add(matcher.group(getRegexGroupInlineMediaAssets()));
}
return assetPaths;
}
private static String getRegexForInlineMediaAssets() {
final String TOKEN_UNLIMITED_SPACE = "[\\n ]*";
final String TOKEN_IMAGE_TAG = "img";
final String TOKEN_ATTRIBUTE_KEY = "[a-zA-Z-]+"; //todo
final String TOKEN_ATTRIBUTE_KEY_SOURCE = "src";
final String TOKEN_SOURCE_ATTRIBUTE_VALUE = "\"" + TOKEN_UNLIMITED_SPACE + "([^>\" \\n]+)" +
TOKEN_UNLIMITED_SPACE + "\"";
final String TOKEN_ATTRIBUTE_VALUE = "\"" + TOKEN_UNLIMITED_SPACE + "([^>\"\\n]+)" + TOKEN_UNLIMITED_SPACE
+ "\"";
final String TOKEN_UNLIMITED_KEY_VALUE = "((" + TOKEN_ATTRIBUTE_KEY + TOKEN_UNLIMITED_SPACE +
"=" + TOKEN_UNLIMITED_SPACE + TOKEN_ATTRIBUTE_VALUE + ")* *)*";
final String TOKEN_SOURCE_KEY_VALUE = TOKEN_ATTRIBUTE_KEY_SOURCE + TOKEN_UNLIMITED_SPACE +
"=" + TOKEN_UNLIMITED_SPACE + TOKEN_SOURCE_ATTRIBUTE_VALUE;
final String regex = "<"
+ TOKEN_UNLIMITED_SPACE + TOKEN_IMAGE_TAG
+ TOKEN_UNLIMITED_SPACE + TOKEN_UNLIMITED_KEY_VALUE
+ TOKEN_UNLIMITED_SPACE + TOKEN_SOURCE_KEY_VALUE
+ TOKEN_UNLIMITED_SPACE + TOKEN_UNLIMITED_KEY_VALUE
+ TOKEN_UNLIMITED_SPACE + "\\/?"
+ TOKEN_UNLIMITED_SPACE + ">";
return regex;
}
private static int getRegexGroupInlineMediaAssets() {
return 4;
}
private static void setLastTranslationUpdate(Resource resource) throws RepositoryException {
if (resource != null) {
Resource contentResource = resource.getChild(JcrConstants.JCR_CONTENT);
if (contentResource != null) {
Node sourceContentNode = contentResource.adaptTo(Node.class);
Calendar lastModified = getNodeLastModifiedTime(contentResource);
if (lastModified == null) {
lastModified = Calendar.getInstance();
}
sourceContentNode.setProperty(ATTRIBUTE_CQ_TRANSLATION_LAST_UPDATE, lastModified);
}
}
}
private static Calendar getNodeLastModifiedTime(Resource contentNode) {
Calendar retVal = null;
Calendar cqLastModified = getCalendarAttribute(contentNode, CQ_LASTMODIFIED);
Calendar jcrLastModified = getCalendarAttribute(contentNode, JCR_LASTMODIFIED);
if (cqLastModified != null && jcrLastModified != null) {
if (cqLastModified.compareTo(jcrLastModified) > 0) {
retVal = cqLastModified;
} else {
retVal = jcrLastModified;
}
} else if (jcrLastModified != null) {
retVal = jcrLastModified;
} else if (cqLastModified != null) {
retVal = cqLastModified;
}
return retVal;
}
private static Calendar getCalendarAttribute(Resource resource, String strAttributeName) {
ValueMap contentVM = resource.adaptTo(ValueMap.class);
return contentVM.get(strAttributeName, Calendar.class);
}
/**
* Returns the destination language root for the given path by analyzing the path names starting at the root.
*
* @param srcLanguageRootParentPath source language root's parent path
* @return the destination language root or null
if not found
*/
private static String getDestinationLanguageRoot(@Nonnull String srcLanguageRootParentPath, @Nonnull String
destinationLanguage, @Nonnull ResourceResolver resourceResolver) {
Resource langRootParent = resourceResolver.getResource(srcLanguageRootParentPath);
if (null != langRootParent) {
//language root based on path
destinationLanguage = getDestinationLanguageWithAllowedDelimiters(srcLanguageRootParentPath,
destinationLanguage, resourceResolver);
String sameLevelDestinationRootPath = srcLanguageRootParentPath + "/" + destinationLanguage;
if (null != resourceResolver.getResource(sameLevelDestinationRootPath)) {
return sameLevelDestinationRootPath;
}
/**
* Check for Language roots at two level
*/
//go one level down
Iterator iter = langRootParent.listChildren();
while (iter.hasNext()) {
Resource sibling = iter.next();
Locale locale = getLocaleFromResource(sibling);
if (locale == null) {
String retVal = checkAndGetLanguageRootsFromChildren(sibling, destinationLanguage);
if (null != retVal) {
return retVal;
}
}
}
//one level up
//find language roots which are not language countries
Resource langRootGrandParent = langRootParent.getParent();
ArrayList nonLangRootUncles = new ArrayList();
boolean additionalLanguageRootsFound = false;
if (langRootGrandParent != null) {
Iterator langRootUncles = langRootGrandParent.listChildren();
while (langRootUncles.hasNext()) {
Resource langRootUncle = langRootUncles.next();
if (langRootUncle.getName().equals(langRootParent.getName())) { //node comparison not working :(
//already checked
continue;
}
Locale gcLocale = getLocaleFromResource(langRootUncle);
//check that this is not a country node and locale is same
if (!isCountryNode(langRootUncle)) {
additionalLanguageRootsFound = true;
if (null != gcLocale) {
String gcLanguage = gcLocale.getLanguage().toString();
if (destinationLanguage.equals(gcLanguage)) {
return langRootUncle.getPath();
}
} else {
nonLangRootUncles.add(langRootUncle);
}
}
}
}
if (additionalLanguageRootsFound) {
//found roots one level up, need to go down on nonLangRootUncles.
for (Resource nonLangRootUncle : nonLangRootUncles) {
String retVal = checkAndGetLanguageRootsFromChildren(nonLangRootUncle,
destinationLanguage);
if (null != retVal) {
return retVal;
}
}
}
//fallback to language root based on path
return sameLevelDestinationRootPath;
}
return null;
}
private static String checkAndGetLanguageRootsFromChildren(Resource resource, String destLanguage) {
Iterator children = resource.listChildren();
while (children.hasNext()) {
Resource child = children.next();
Locale childLocale = getLocaleFromResource(child);
if (childLocale != null) {
String childLanguage = childLocale.getLanguage().toString();
if(childLanguage.equals(destLanguage)) {
return child.getPath();
}
}
}
return null;
}
private static Locale getLocaleFromResource(@Nonnull Resource res) {
Language language = LanguageUtil.getLanguage(res.getName());
if (language != null) {
return language.getLocale();
}
return null;
}
private static boolean isCountryNode(Resource resource) {
Iterator children = resource.listChildren();
while (children.hasNext()) {
Resource child = children.next();
Locale gcLocale = getLocaleFromResource(child);
if (gcLocale != null) {
return true;
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy