/*
* (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.ecm.platform.ui.web.directory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.utils.i18n.I18NUtils;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.NuxeoException;
import org.nuxeo.ecm.directory.DirectoryException;
import org.nuxeo.ecm.directory.Session;
import org.nuxeo.ecm.directory.api.DirectoryService;
import org.nuxeo.runtime.api.Framework;
/**
* @author <a href="mailto:glefter@nuxeo.com">George Lefter</a>
*/
public final class DirectoryHelper {
private static final Log log = LogFactory.getLog(DirectoryHelper.class);
/** Directory with a parent column. */
public static final String XVOCABULARY_TYPE = "xvocabulary";
public static final String[] VOCABULARY_TYPES = { "vocabulary", XVOCABULARY_TYPE };
private static final String[] displayOptions = { "id", "label", "idAndLabel" };
private static DirectoryHelper instance;
private DirectoryHelper() {
}
public static DirectoryHelper instance() {
if (null == instance) {
instance = new DirectoryHelper();
}
return instance;
}
public boolean hasParentColumn(String directoryName) {
try {
return XVOCABULARY_TYPE.equals(getService().getDirectorySchema(directoryName));
} catch (DirectoryException e) {
// GR: our callers can't throw anything. Better to catch here, then
log.error("Could not retrieve schema name for directory: " + directoryName, e);
return false;
}
}
public DirectorySelectItem getSelectItem(String directoryName, Map<String, Serializable> filter) {
List<DirectorySelectItem> items = getSelectItems(directoryName, filter);
if (items.size() > 1) {
log.warn("More than one entry found in directory " + directoryName + " and filter:");
for (Map.Entry<String, Serializable> e : filter.entrySet()) {
log.warn(String.format("%s=%s", e.getKey(), e.getValue()));
}
} else if (items.isEmpty()) {
return null;
}
return items.get(0);
}
public List<DirectorySelectItem> getSelectItems(String directoryName, Map<String, Serializable> filter) {
return getSelectItems(directoryName, filter, Boolean.FALSE);
}
public List<DirectorySelectItem> getSelectItems(String directoryName, Map<String, Serializable> filter,
Boolean localize) {
List<DirectorySelectItem> list = new LinkedList<DirectorySelectItem>();
Set<String> emptySet = Collections.emptySet();
Map<String, String> orderBy = new LinkedHashMap<String, String>();
FacesContext context = FacesContext.getCurrentInstance();
// an extended schema also has parent field
try (Session session = getService().open(directoryName)) {
String schema = getService().getDirectorySchema(directoryName);
if (session == null) {
throw new NuxeoException("could not open session on directory: " + directoryName);
}
// adding sorting support
// XXX It seems that this ordering is obsolete as
// DirectoryAwareComponent made it's own (NXP-7349)
if (schema.equals(VOCABULARY_TYPES[0]) || schema.equals(VOCABULARY_TYPES[1])) {
orderBy.put("ordering", "asc");
orderBy.put("id", "asc");
}
DocumentModelList docModelList = session.query(filter, emptySet, orderBy);
for (DocumentModel docModel : docModelList) {
String id = (String) docModel.getProperty(schema, "id");
String label = (String) docModel.getProperty(schema, "label");
long ordering = (Long) docModel.getProperty(schema, "ordering");
if (Boolean.TRUE.equals(localize)) {
label = translate(context, label);
}
DirectorySelectItem item = new DirectorySelectItem(id, label, ordering);
list.add(item);
}
}
return list;
}
public static DirectoryService getDirectoryService() {
return instance().getService();
}
public static List<DirectorySelectItem> getSelectItems(VocabularyEntryList directoryValues,
Map<String, Serializable> filter) {
return getSelectItems(directoryValues, filter, Boolean.FALSE);
}
public static List<DirectorySelectItem> getSelectItems(VocabularyEntryList directoryValues,
Map<String, Serializable> filter, Boolean localize) {
List<DirectorySelectItem> list = new ArrayList<DirectorySelectItem>();
// in obsolete filter we have either null (include obsoletes)
// or 0 (don't include obsoletes)
boolean obsolete = filter.get("obsolete") == null;
String parentFilter = (String) filter.get("parent");
FacesContext context = FacesContext.getCurrentInstance();
for (VocabularyEntry entry : directoryValues.getEntries()) {
if (!obsolete && Boolean.TRUE.equals(entry.getObsolete())) {
continue;
}
String parent = entry.getParent();
if (parentFilter == null) {
if (parent != null) {
continue;
}
} else if (!parentFilter.equals(parent)) {
continue;
}
String idValue = (String) filter.get("id");
if (idValue != null && !idValue.equals(entry.getId())) {
continue;
}
String id = entry.getId();
String label = entry.getLabel();
if (Boolean.TRUE.equals(localize)) {
label = translate(context, label);
}
DirectorySelectItem item = new DirectorySelectItem(id, label);
list.add(item);
}
return list;
}
public static String getOptionValue(String optionId, String optionLabel, String display, boolean displayIdAndLabel,
String displayIdAndLabelSeparator) {
StringBuilder displayValue = new StringBuilder();
if (display != null && !"".equals(display)) {
if (display.equals(displayOptions[0])) {
displayValue.append(optionId);
} else if (display.equals(displayOptions[1])) {
displayValue.append(optionLabel);
} else if (display.equals(displayOptions[2])) {
displayValue.append(optionId).append(displayIdAndLabelSeparator).append(optionLabel);
} else {
displayValue.append(optionLabel);
}
} else if (displayIdAndLabel) {
displayValue.append(optionId).append(displayIdAndLabelSeparator).append(optionLabel);
} else {
displayValue.append(optionLabel);
}
return displayValue.toString();
}
private static DocumentModel getEntryThrows(String directoryName, String entryId) {
DirectoryService dirService = getDirectoryService();
try (Session session = dirService.open(directoryName)) {
return session.getEntry(entryId);
}
}
/**
* Returns the entry with given id from specified directory.
* <p>
* Method to use from components, since JSF base class that we extend don't allow to throw proper exceptions.
*
* @param directoryName
* @param entryId
* @return the entry, or null in case of exception in callees.
*/
public static DocumentModel getEntry(String directoryName, String entryId) {
try {
return getEntryThrows(directoryName, entryId);
} catch (DirectoryException e) {
log.error(String.format("Error retrieving the entry (dirname=%s, entryId=%s)", directoryName, entryId), e);
return null;
}
}
protected static String translate(FacesContext context, String label) {
String bundleName = context.getApplication().getMessageBundle();
Locale locale = context.getViewRoot().getLocale();
label = I18NUtils.getMessageString(bundleName, label, null, locale);
return label;
}
protected DirectoryService getService() {
return Framework.getService(DirectoryService.class);
}
}