/**
  * Creates {@link TaskDescriptor} for given Task's bean entry class. To be used for tasks without
  * descriptors, it will create one on the fly with defaults.
  */
 private <T extends Task> TaskDescriptor<T> createTaskDescriptor(
     final BeanEntry<Named, Task> taskBeanEntry) {
   final String taskName =
       taskBeanEntry.getDescription() != null
           ? taskBeanEntry.getDescription()
           : taskBeanEntry.getImplementationClass().getSimpleName();
   // by default, tasks w/o descriptors are not exposed, and not visible while run/scheduled
   return new TaskDescriptorSupport<T>(
       (Class<T>) taskBeanEntry.getImplementationClass(), taskName, false, false) {};
 }
 @Override
 public <T extends Task> TaskDescriptor<T> resolveTaskDescriptorByTypeId(final String taskTypeId) {
   // look for descriptors first
   for (TaskDescriptor<?> taskDescriptor : taskDescriptors) {
     if (taskDescriptor.getId().equals(taskTypeId)) {
       return (TaskDescriptor<T>) taskDescriptor;
     }
   }
   // not found by descriptor, try tasks directly
   for (BeanEntry<Named, Task> entry : tasks) {
     // checks: task FQCN, task SimpleName or @Named
     if (entry.getImplementationClass().getName().equals(taskTypeId)
         || entry.getImplementationClass().getSimpleName().equals(taskTypeId)
         || entry.getKey().value().equals(taskTypeId)) {
       return (TaskDescriptor<T>) findTaskDescriptor(entry);
     }
   }
   return null;
 }
 /**
  * Returns {@link TaskDescriptor} by given Task's bean entry. Will perform a search for provided
  * task descriptors, and if not found, will create one using {@link
  * #createTaskDescriptor(BeanEntry)}.
  */
 private <T extends Task> TaskDescriptor<T> findTaskDescriptor(
     final BeanEntry<Named, Task> taskBeanEntry) {
   // look for descriptor first
   for (TaskDescriptor<?> taskDescriptor : taskDescriptors) {
     if (taskDescriptor.getType().equals(taskBeanEntry.getImplementationClass())) {
       return (TaskDescriptor<T>) taskDescriptor;
     }
   }
   // not found by descriptor, create one for it
   return (TaskDescriptor<T>) createTaskDescriptor(taskBeanEntry);
 }
    @Override
    public void add(final BeanEntry<Named, Action> beanEntry, final BundleContext bundleContext)
        throws Exception {
      Command command = beanEntry.getImplementationClass().getAnnotation(Command.class);
      if (command != null) {
        // TODO: warn if @Singleton is present, this is probably not desired due to
        // @Option/@Argument processing ?

        Dictionary<String, ?> config = CommandHelper.config(command);
        log.debug("Adding action: {}, config: {}", beanEntry, config);
        bundleContext.registerService(
            Function.class, new BeanEntryCommand(beanLocator, beanEntry), config);
      } else {
        log.warn("Missing @Command annotation on action: {}", beanEntry);
      }
    }
 @Override
 public <T extends Task> T createTaskInstance(final TaskConfiguration taskConfiguration)
     throws IllegalArgumentException {
   checkNotNull(taskConfiguration);
   taskConfiguration.validate();
   log.debug("Creating task by hint: {}", taskConfiguration);
   final TaskDescriptor<T> taskDescriptor =
       getTaskDescriptorByTypeId(taskConfiguration.getTypeId());
   for (BeanEntry<Named, Task> entry : tasks) {
     if (entry.getImplementationClass().equals(taskDescriptor.getType())) {
       final T task = (T) entry.getProvider().get();
       task.configure(taskConfiguration);
       return task;
     }
   }
   throw new IllegalArgumentException(
       "No Task of type \'" + taskConfiguration.getTypeId() + "\' found");
 }
 /**
  * Returns a map with "typeId" Task descriptor mapping for all existing tasks. For tasks without
  * descriptors, descriptor will be created.
  */
 private Map<String, TaskDescriptor<?>> allTaskDescriptors() {
   // TODO: consistency checks? a) task : descriptors are 1:1, b) descriptor IDs are unique?
   // TODO: we might emit warning if some of those does not stand
   // using task class as "key" to detect tasks w/ descriptor vs tasks w/o descriptor
   final Map<Class<? extends Task>, TaskDescriptor<?>> descriptorMap = Maps.newHashMap();
   for (TaskDescriptor<?> taskDescriptor : taskDescriptors) {
     descriptorMap.put(taskDescriptor.getType(), taskDescriptor);
   }
   for (BeanEntry<Named, Task> entry : tasks) {
     if (!descriptorMap.containsKey(entry.getImplementationClass())) {
       final TaskDescriptor<?> taskDescriptor = createTaskDescriptor(entry);
       descriptorMap.put(taskDescriptor.getType(), taskDescriptor);
     }
   }
   // repack the map into result map keyed by typeId
   final Map<String, TaskDescriptor<?>> result = Maps.newHashMap();
   for (TaskDescriptor<?> taskDescriptor : descriptorMap.values()) {
     result.put(taskDescriptor.getId(), taskDescriptor);
   }
   return result;
 }
 @Override
 public Class<?> getScannableClass() {
   return entry.getImplementationClass();
 }