/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.item.selector.web.internal.util;
import com.liferay.item.selector.ItemSelectorCriterion;
import com.liferay.item.selector.ItemSelectorReturnType;
import com.liferay.item.selector.ItemSelectorView;
import com.liferay.item.selector.ItemSelectorViewReturnTypeProvider;
import com.liferay.item.selector.ItemSelectorViewReturnTypeProviderHandler;
import com.liferay.item.selector.web.ItemSelectorCriterionSerializer;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMap;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapFactory;
import com.liferay.osgi.util.ServiceTrackerFactory;
import com.liferay.portal.kernel.json.JSONContext;
import com.liferay.portal.kernel.json.JSONDeserializer;
import com.liferay.portal.kernel.json.JSONDeserializerTransformer;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONSerializer;
import com.liferay.portal.kernel.json.JSONTransformer;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* @author Iván Zaera
* @author Roberto Díaz
*/
@Component(immediate = true)
public class ItemSelectorCriterionSerializerImpl
implements ItemSelectorCriterionSerializer {
@Override
public <T extends ItemSelectorCriterion> T deserialize(
Class<T> itemSelectorCriterionClass, String json) {
JSONDeserializer<T> jsonDeserializer =
JSONFactoryUtil.createJSONDeserializer();
jsonDeserializer.transform(
_desiredItemSelectorReturnTypesJSONDeserializerTransformer,
"desiredItemSelectorReturnTypes");
return jsonDeserializer.deserialize(json, itemSelectorCriterionClass);
}
@Override
public String serialize(ItemSelectorCriterion itemSelectorCriterion) {
JSONSerializer jsonSerializer = JSONFactoryUtil.createJSONSerializer();
jsonSerializer.transform(
_desiredItemSelectorReturnTypesJSONTransformer,
"desiredItemSelectorReturnTypes");
jsonSerializer.exclude(_EXCLUDED_FIELD_NAMES);
return jsonSerializer.serializeDeep(itemSelectorCriterion);
}
@Reference(unbind = "-")
public void setItemSelectorViewReturnTypeProviderHandler(
ItemSelectorViewReturnTypeProviderHandler
itemSelectorViewReturnTypeProviderHandler) {
_itemSelectorViewReturnTypeProviderHandler =
itemSelectorViewReturnTypeProviderHandler;
}
@Activate
protected void activate(BundleContext bundleContext) {
_bundleContext = bundleContext;
_serviceTrackerMap = ServiceTrackerMapFactory.openSingleValueMap(
bundleContext, ItemSelectorView.class, "item.selector.view.key");
_serviceTracker = ServiceTrackerFactory.open(
bundleContext, ItemSelectorViewReturnTypeProvider.class,
new ItemSelectorViewReturnTypeProviderServiceTrackerCustomizer());
_serviceTrackerItemSelectorView = ServiceTrackerFactory.open(
bundleContext, ItemSelectorView.class,
new ItemSelectorReturnTypeServiceTrackerCustomizer());
}
protected void addItemSelectorReturnType(
ItemSelectorReturnType itemSelectorReturnType) {
Class<? extends ItemSelectorReturnType> itemSelectorReturnTypeClass =
itemSelectorReturnType.getClass();
List<ItemSelectorReturnType> itemSelectorReturnTypes =
_itemSelectorReturnTypes.get(itemSelectorReturnTypeClass.getName());
if (itemSelectorReturnTypes == null) {
itemSelectorReturnTypes = new CopyOnWriteArrayList<>();
List<ItemSelectorReturnType> previousItemSelectorReturnTypes =
_itemSelectorReturnTypes.putIfAbsent(
itemSelectorReturnTypeClass.getName(),
itemSelectorReturnTypes);
if (previousItemSelectorReturnTypes != null) {
itemSelectorReturnTypes = previousItemSelectorReturnTypes;
}
}
itemSelectorReturnTypes.add(itemSelectorReturnType);
}
@Deactivate
protected void deactivate() {
_serviceTracker.close();
_serviceTrackerItemSelectorView.close();
_serviceTrackerMap.close();
}
private static final String[] _EXCLUDED_FIELD_NAMES =
new String[] {"availableItemSelectorReturnTypes", "class"};
private static final Log _log = LogFactoryUtil.getLog(
ItemSelectorCriterionSerializerImpl.class);
private BundleContext _bundleContext;
private final DesiredItemSelectorReturnTypesJSONDeserializerTransformer
_desiredItemSelectorReturnTypesJSONDeserializerTransformer =
new DesiredItemSelectorReturnTypesJSONDeserializerTransformer();
private final DesiredItemSelectorReturnTypesJSONTransformer
_desiredItemSelectorReturnTypesJSONTransformer =
new DesiredItemSelectorReturnTypesJSONTransformer();
private final ConcurrentMap<String, List<ItemSelectorReturnType>>
_itemSelectorReturnTypes = new ConcurrentHashMap<>();
private ItemSelectorViewReturnTypeProviderHandler
_itemSelectorViewReturnTypeProviderHandler;
private ServiceTracker
<ItemSelectorViewReturnTypeProvider,
ItemSelectorViewReturnTypeProvider> _serviceTracker;
private ServiceTracker<ItemSelectorView, ItemSelectorView>
_serviceTrackerItemSelectorView;
private ServiceTrackerMap<String, ItemSelectorView> _serviceTrackerMap;
private static class DesiredItemSelectorReturnTypesJSONTransformer
implements JSONTransformer {
@Override
public void transform(JSONContext jsonContext, Object object) {
List<ItemSelectorReturnType> desiredItemSelectorReturnTypes =
(List<ItemSelectorReturnType>)object;
StringBundler sb = new StringBundler(
desiredItemSelectorReturnTypes.size() * 2 + 1);
sb.append(StringPool.QUOTE);
for (ItemSelectorReturnType itemSelectorReturnType :
desiredItemSelectorReturnTypes) {
Class<? extends ItemSelectorReturnType>
itemSelectorReturnTypeClass =
itemSelectorReturnType.getClass();
sb.append(itemSelectorReturnTypeClass.getName());
sb.append(StringPool.COMMA);
}
if (desiredItemSelectorReturnTypes.isEmpty()) {
sb.append(StringPool.QUOTE);
}
else {
sb.setStringAt(StringPool.QUOTE, sb.index() - 1);
}
jsonContext.write(sb.toString());
}
}
private class DesiredItemSelectorReturnTypesJSONDeserializerTransformer
implements JSONDeserializerTransformer
<String, List<ItemSelectorReturnType>> {
@Override
public List<ItemSelectorReturnType> transform(String key) {
List<ItemSelectorReturnType> desiredItemSelectorReturnTypes =
new ArrayList<>();
String[] desiredItemSelectorReturnTypeNames = StringUtil.split(key);
for (String desiredItemSelectorReturnTypeName :
desiredItemSelectorReturnTypeNames) {
List<ItemSelectorReturnType> itemSelectorReturnTypes =
_itemSelectorReturnTypes.get(
desiredItemSelectorReturnTypeName);
if (ListUtil.isEmpty(itemSelectorReturnTypes)) {
if (_log.isWarnEnabled()) {
_log.warn(
"No return types are registered for " +
desiredItemSelectorReturnTypeName);
}
continue;
}
Iterator<ItemSelectorReturnType> iterator =
itemSelectorReturnTypes.iterator();
if (iterator.hasNext()) {
desiredItemSelectorReturnTypes.add(iterator.next());
}
}
if (desiredItemSelectorReturnTypes.isEmpty()) {
if (_log.isWarnEnabled()) {
_log.warn(
"No valid desired item selector return types found");
}
}
return desiredItemSelectorReturnTypes;
}
}
private class ItemSelectorReturnTypeServiceTrackerCustomizer
implements
ServiceTrackerCustomizer<ItemSelectorView, ItemSelectorView> {
@Override
public ItemSelectorView addingService(
ServiceReference<ItemSelectorView> serviceReference) {
ItemSelectorView itemSelectorView = _bundleContext.getService(
serviceReference);
String itemSelectorViewKey = GetterUtil.getString(
serviceReference.getProperty("item.selector.view.key"));
List<ItemSelectorReturnType> supportedItemSelectorReturnTypes =
_itemSelectorViewReturnTypeProviderHandler.
getSupportedItemSelectorReturnTypes(
itemSelectorView.getSupportedItemSelectorReturnTypes(),
itemSelectorViewKey);
for (ItemSelectorReturnType supportedItemSelectorReturnType :
supportedItemSelectorReturnTypes) {
addItemSelectorReturnType(supportedItemSelectorReturnType);
}
return itemSelectorView;
}
@Override
public void modifiedService(
ServiceReference<ItemSelectorView> serviceReference,
ItemSelectorView itemSelectorView) {
}
@Override
public void removedService(
ServiceReference<ItemSelectorView> serviceReference,
ItemSelectorView itemSelectorView) {
try {
List<ItemSelectorReturnType> supportedItemSelectorReturnTypes =
itemSelectorView.getSupportedItemSelectorReturnTypes();
for (ItemSelectorReturnType supportedItemSelectorReturnType :
supportedItemSelectorReturnTypes) {
Class<? extends ItemSelectorReturnType>
supportedItemSelectorReturnTypeClass =
supportedItemSelectorReturnType.getClass();
List<ItemSelectorReturnType> itemSelectorReturnTypes =
_itemSelectorReturnTypes.get(
supportedItemSelectorReturnTypeClass.getName());
itemSelectorReturnTypes.remove(0);
}
}
finally {
_bundleContext.ungetService(serviceReference);
}
}
}
private class ItemSelectorViewReturnTypeProviderServiceTrackerCustomizer
implements ServiceTrackerCustomizer
<ItemSelectorViewReturnTypeProvider,
ItemSelectorViewReturnTypeProvider> {
@Override
public ItemSelectorViewReturnTypeProvider addingService(
ServiceReference<ItemSelectorViewReturnTypeProvider>
serviceReference) {
ItemSelectorViewReturnTypeProvider
itemSelectorViewReturnTypeProvider = _bundleContext.getService(
serviceReference);
String itemSelectorViewKey = GetterUtil.getString(
serviceReference.getProperty("item.selector.view.key"));
ItemSelectorView itemSelectorView = _serviceTrackerMap.getService(
itemSelectorViewKey);
if (itemSelectorView == null) {
return null;
}
List<ItemSelectorReturnType> supportedItemSelectorReturnTypes =
itemSelectorViewReturnTypeProvider.
populateSupportedItemSelectorReturnTypes(
ListUtil.copy(
itemSelectorView.
getSupportedItemSelectorReturnTypes()));
for (ItemSelectorReturnType supportedItemSelectorReturnType :
supportedItemSelectorReturnTypes) {
addItemSelectorReturnType(supportedItemSelectorReturnType);
}
return itemSelectorViewReturnTypeProvider;
}
@Override
public void modifiedService(
ServiceReference<ItemSelectorViewReturnTypeProvider>
serviceReference,
ItemSelectorViewReturnTypeProvider
itemSelectorViewReturnTypeProvider) {
}
@Override
public void removedService(
ServiceReference<ItemSelectorViewReturnTypeProvider>
serviceReference,
ItemSelectorViewReturnTypeProvider
itemSelectorViewReturnTypeProvider) {
_bundleContext.ungetService(serviceReference);
}
}
}