/*******************************************************************************
* Copyright (c) 2015 IBH SYSTEMS GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.manage.todo.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
import org.eclipse.packagedrone.repo.manage.todo.Task;
import org.eclipse.packagedrone.repo.manage.todo.TaskListener;
import org.eclipse.packagedrone.repo.manage.todo.TaskProvider;
import org.eclipse.packagedrone.repo.manage.todo.ToDoService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class ToDoServiceImpl implements ToDoService
{
private final BundleContext context;
private final ServiceTracker<TaskProvider, TaskProvider> tracker;
private final ServiceTrackerCustomizer<TaskProvider, TaskProvider> customizer = new ServiceTrackerCustomizer<TaskProvider, TaskProvider> () {
@Override
public void removedService ( final ServiceReference<TaskProvider> reference, final TaskProvider service )
{
removeService ( service );
ToDoServiceImpl.this.context.ungetService ( reference );
}
@Override
public void modifiedService ( final ServiceReference<TaskProvider> reference, final TaskProvider service )
{
removeService ( service );
addService ( service );
}
@Override
public TaskProvider addingService ( final ServiceReference<TaskProvider> reference )
{
final TaskProvider service = ToDoServiceImpl.this.context.getService ( reference );
addService ( service );
return service;
}
};
public ToDoServiceImpl ()
{
this.context = FrameworkUtil.getBundle ( ToDoService.class ).getBundleContext ();
this.tracker = new ServiceTracker<> ( this.context, TaskProvider.class, this.customizer );
}
private final Set<TaskProvider> providers = new CopyOnWriteArraySet<> ();
private final TaskListener taskListener = new TaskListener () {
@Override
public void tasksChanged ( final Collection<? extends Task> tasks )
{
updateCache ();
}
};
private volatile List<Task> allTasks;
private volatile List<Task> openTasks;
protected void addService ( final TaskProvider service )
{
this.providers.add ( service );
service.addListener ( this.taskListener );
updateCache ();
}
protected void removeService ( final TaskProvider service )
{
service.removeListener ( this.taskListener );
this.providers.remove ( service );
updateCache ();
}
protected void updateCache ()
{
this.allTasks = buildCache ();
this.openTasks = filterOpen ( this.allTasks );
}
private List<Task> filterOpen ( final List<Task> tasks )
{
return Collections.unmodifiableList ( tasks.stream ().filter ( Task::isOpen ).collect ( Collectors.toList () ) );
}
protected List<Task> buildCache ()
{
final List<Task> result = new ArrayList<> ();
for ( final TaskProvider provider : this.providers )
{
result.addAll ( provider.getTasks () );
}
Collections.sort ( result, Task.PRIORITY_COMPARATOR );
return Collections.unmodifiableList ( result );
}
public void start ()
{
this.tracker.open ();
}
public void stop ()
{
this.tracker.close ();
}
@Override
public List<Task> getOpenTasks ()
{
return this.openTasks;
}
}