/**
* 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.portal.kernel.display.context;
import com.liferay.registry.Filter;
import com.liferay.registry.Registry;
import com.liferay.registry.RegistryUtil;
import com.liferay.registry.ServiceReference;
import com.liferay.registry.ServiceTracker;
import com.liferay.registry.ServiceTrackerCustomizer;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
/**
* @author Iván Zaera
*/
public class BaseDisplayContextProvider<T extends DisplayContextFactory>
implements DisplayContextProvider {
public BaseDisplayContextProvider(Class<T> displayContextFactoryClass) {
Registry registry = RegistryUtil.getRegistry();
Filter filter = registry.getFilter(
"(objectClass=" + displayContextFactoryClass.getName() + ")");
_serviceTracker = registry.trackServices(
filter, new DisplayContextFactoryServiceTrackerCustomizer());
_serviceTracker.open();
}
public void destroy() {
_serviceTracker.close();
}
public Iterable<T> getDisplayContextFactories() {
return new DisplayContextFactoriesIterable<>(
_displayContextFactoryReferences);
}
private final SortedSet<DisplayContextFactoryReference<T>>
_displayContextFactoryReferences = new ConcurrentSkipListSet<>();
private final ConcurrentMap<T, DisplayContextFactoryReference<T>>
_displayContextFactoryReferencesMap = new ConcurrentHashMap<>();
private final ServiceTracker<T, T> _serviceTracker;
private static class DisplayContextFactoriesIterable
<T extends DisplayContextFactory>
implements Iterable<T>, Iterator<T> {
public DisplayContextFactoriesIterable(
Iterable<DisplayContextFactoryReference<T>> iterable) {
_iterator = iterable.iterator();
}
@Override
public boolean hasNext() {
return _iterator.hasNext();
}
@Override
public Iterator<T> iterator() {
return this;
}
@Override
public T next() {
DisplayContextFactoryReference<T> displayContextFactoryReference =
_iterator.next();
return displayContextFactoryReference.getDisplayContextFactory();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Iterator is read-only");
}
private final Iterator<DisplayContextFactoryReference<T>> _iterator;
}
private class DisplayContextFactoryServiceTrackerCustomizer
implements ServiceTrackerCustomizer<T, T> {
@Override
public T addingService(ServiceReference<T> serviceReference) {
Registry registry = RegistryUtil.getRegistry();
T displayContextFactory = registry.getService(serviceReference);
DisplayContextFactoryReference<T> displayContextFactoryReference =
new DisplayContextFactoryReference<>(
displayContextFactory, serviceReference);
_displayContextFactoryReferences.add(
displayContextFactoryReference);
_displayContextFactoryReferencesMap.put(
displayContextFactory, displayContextFactoryReference);
return displayContextFactory;
}
@Override
public void modifiedService(
ServiceReference<T> serviceReference, T displayContextFactory) {
DisplayContextFactoryReference<T> displayContextFactoryReference =
_displayContextFactoryReferencesMap.get(displayContextFactory);
removedService(
displayContextFactoryReference.getServiceReference(),
displayContextFactoryReference.getDisplayContextFactory());
addingService(serviceReference);
}
@Override
public void removedService(
ServiceReference<T> serviceReference, T displayContextFactory) {
DisplayContextFactoryReference<T> displayContextFactoryReference =
_displayContextFactoryReferencesMap.remove(
displayContextFactory);
_displayContextFactoryReferences.remove(
displayContextFactoryReference);
}
}
}